Merge "Increased user switch timeout to 3s"
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..010b2b4
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,18 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+subdirs = [
+    "native/android",
+    "native/graphics/jni",
+]
diff --git a/Android.mk b/Android.mk
index d646d9c..e352bc7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -63,7 +63,6 @@
 	core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl \
 	core/java/android/accounts/IAccountManager.aidl \
 	core/java/android/accounts/IAccountManagerResponse.aidl \
-	core/java/android/accounts/IAccountAccessTracker.aidl \
 	core/java/android/accounts/IAccountAuthenticator.aidl \
 	core/java/android/accounts/IAccountAuthenticatorResponse.aidl \
 	core/java/android/app/IActivityContainer.aidl \
@@ -201,6 +200,7 @@
 	core/java/android/net/ICaptivePortal.aidl \
 	core/java/android/net/IConnectivityManager.aidl \
 	core/java/android/net/IConnectivityMetricsLogger.aidl \
+	core/java/android/net/IIpConnectivityMetrics.aidl \
 	core/java/android/net/IEthernetManager.aidl \
 	core/java/android/net/IEthernetServiceListener.aidl \
 	core/java/android/net/INetworkManagementEventObserver.aidl \
@@ -332,6 +332,7 @@
 	core/java/com/android/internal/os/IDropBoxManagerService.aidl \
 	core/java/com/android/internal/os/IParcelFileDescriptorFactory.aidl \
 	core/java/com/android/internal/os/IResultReceiver.aidl \
+	core/java/com/android/internal/os/IShellCallback.aidl \
 	core/java/com/android/internal/statusbar/IStatusBar.aidl \
 	core/java/com/android/internal/statusbar/IStatusBarService.aidl \
 	core/java/com/android/internal/textservice/ISpellCheckerService.aidl \
@@ -501,7 +502,7 @@
 LOCAL_ADDITIONAL_DEPENDENCIES := $(framework_res_R_stamp)
 
 LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart core-lambda-stubs conscrypt okhttp core-junit bouncycastle ext
+LOCAL_JAVA_LIBRARIES := core-oj core-libart conscrypt okhttp core-junit bouncycastle ext
 LOCAL_STATIC_JAVA_LIBRARIES := framework-protos
 
 LOCAL_MODULE := framework
@@ -1113,7 +1114,14 @@
 $(static_doc_index_redirect): $(LOCAL_PATH)/docs/docs-documentation-redirect.html
 	$(copy-file-to-target)
 
+static_doc_properties := $(out_dir)/source.properties
+$(static_doc_properties): \
+	$(LOCAL_PATH)/docs/source.properties | $(ACP)
+	$(hide) mkdir -p $(dir $@)
+	$(hide) $(ACP) $< $@
+
 $(full_target): $(static_doc_index_redirect)
+$(full_target): $(static_doc_properties)
 $(full_target): $(framework_built)
 
 
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTest.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTest.java
index bd0139f..cdbca63 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTest.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTest.java
@@ -18,7 +18,8 @@
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
-import android.app.SynchronousUserSwitchObserver;
+import android.app.IStopUserCallback;
+import android.app.UserSwitchObserver;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -43,18 +44,36 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
+/**
+ * Perf tests for user life cycle events.
+ *
+ * Running the tests:
+ * make MultiUserPerfTests &&
+ * adb install -r \
+ *     ${ANDROID_PRODUCT_OUT}/data/app/MultiUserPerfTests/MultiUserPerfTests.apk &&
+ * adb shell am instrument -e class android.multiuser.UserLifecycleTest \
+ *     -w com.android.perftests.multiuser/android.support.test.runner.AndroidJUnitRunner
+ */
 @LargeTest
 @RunWith(AndroidJUnit4.class)
 public class UserLifecycleTest {
     private final int MIN_REPEAT_TIMES = 4;
 
-    private final int TIMEOUT_REMOVE_USER_SEC = 4;
+    private final int TIMEOUT_REMOVE_USER_MS = 4 * 1000; // 4 sec
     private final int CHECK_USER_REMOVED_INTERVAL_MS = 200; // 0.2 sec
 
     private final int TIMEOUT_USER_START_SEC = 4; // 4 sec
 
     private final int TIMEOUT_USER_SWITCH_SEC = 8; // 8 sec
 
+    private final int TIMEOUT_USER_STOP_SEC = 1; // 1 sec
+
+    private final int TIMEOUT_MANAGED_PROFILE_UNLOCK_SEC = 2; // 2 sec
+
+    private final int TIMEOUT_LOCKED_BOOT_COMPLETE_MS = 5 * 1000; // 5 sec
+
+    private final int TIMEOUT_EPHERMAL_USER_STOP_SEC = 6; // 6 sec
+
     private UserManager mUm;
     private ActivityManager mAm;
     private IActivityManager mIam;
@@ -78,7 +97,11 @@
     @After
     public void tearDown() {
         for (int userId : mUsersToRemove) {
-            mUm.removeUser(userId);
+            try {
+                mUm.removeUser(userId);
+            } catch (Exception e) {
+                // Ignore
+            }
         }
     }
 
@@ -88,14 +111,7 @@
             final UserInfo userInfo = mUm.createUser("TestUser", 0);
 
             final CountDownLatch latch = new CountDownLatch(1);
-            InstrumentationRegistry.getContext().registerReceiverAsUser(new BroadcastReceiver() {
-                @Override
-                public void onReceive(Context context, Intent intent) {
-                    if (Intent.ACTION_USER_STARTED.equals(intent.getAction())) {
-                        latch.countDown();
-                    }
-                }
-            }, UserHandle.ALL, new IntentFilter(Intent.ACTION_USER_STARTED), null, null);
+            registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch, userInfo.id);
             mIam.startUserInBackground(userInfo.id);
             latch.await(TIMEOUT_USER_START_SEC, TimeUnit.SECONDS);
 
@@ -122,37 +138,163 @@
         }
     }
 
+    @Test
+    public void stopUserPerf() throws Exception {
+        while (mState.keepRunning()) {
+            mState.pauseTiming();
+            final UserInfo userInfo = mUm.createUser("TestUser", 0);
+            final CountDownLatch latch = new CountDownLatch(1);
+            registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch, userInfo.id);
+            mIam.startUserInBackground(userInfo.id);
+            latch.await(TIMEOUT_USER_START_SEC, TimeUnit.SECONDS);
+            mState.resumeTiming();
+
+            stopUser(userInfo.id);
+
+            mState.pauseTiming();
+            removeUser(userInfo.id);
+            mState.resumeTiming();
+        }
+    }
+
+    @Test
+    public void lockedBootCompletedPerf() throws Exception {
+        while (mState.keepRunning()) {
+            mState.pauseTiming();
+            final int startUser = mAm.getCurrentUser();
+            final UserInfo userInfo = mUm.createUser("TestUser", 0);
+            final CountDownLatch latch = new CountDownLatch(1);
+            registerUserSwitchObserver(null, latch, userInfo.id);
+            mState.resumeTiming();
+
+            mAm.switchUser(userInfo.id);
+            latch.await(TIMEOUT_LOCKED_BOOT_COMPLETE_MS, TimeUnit.SECONDS);
+
+            mState.pauseTiming();
+            switchUser(startUser);
+            removeUser(userInfo.id);
+            mState.resumeTiming();
+        }
+    }
+
+    @Test
+    public void managedProfileUnlockPerf() throws Exception {
+        while (mState.keepRunning()) {
+            mState.pauseTiming();
+            final UserInfo userInfo = mUm.createProfileForUser("TestUser",
+                    UserInfo.FLAG_MANAGED_PROFILE, mAm.getCurrentUser());
+            final CountDownLatch latch = new CountDownLatch(1);
+            registerBroadcastReceiver(Intent.ACTION_USER_UNLOCKED, latch, userInfo.id);
+            mState.resumeTiming();
+
+            mIam.startUserInBackground(userInfo.id);
+            latch.await(TIMEOUT_MANAGED_PROFILE_UNLOCK_SEC, TimeUnit.SECONDS);
+
+            mState.pauseTiming();
+            removeUser(userInfo.id);
+            mState.resumeTiming();
+        }
+    }
+
+    @Test
+    public void ephemeralUserStoppedPerf() throws Exception {
+        while (mState.keepRunning()) {
+            mState.pauseTiming();
+            final int startUser = mAm.getCurrentUser();
+            final UserInfo userInfo = mUm.createUser("TestUser",
+                    UserInfo.FLAG_EPHEMERAL | UserInfo.FLAG_DEMO);
+            switchUser(userInfo.id);
+            final CountDownLatch latch = new CountDownLatch(1);
+            InstrumentationRegistry.getContext().registerReceiver(new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    if (Intent.ACTION_USER_STOPPED.equals(intent.getAction()) && intent.getIntExtra(
+                            Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL) == userInfo.id) {
+                        latch.countDown();
+                    }
+                }
+            }, new IntentFilter(Intent.ACTION_USER_STOPPED));
+            final CountDownLatch switchLatch = new CountDownLatch(1);
+            registerUserSwitchObserver(switchLatch, null, startUser);
+            mState.resumeTiming();
+
+            mAm.switchUser(startUser);
+            latch.await(TIMEOUT_EPHERMAL_USER_STOP_SEC, TimeUnit.SECONDS);
+
+            mState.pauseTiming();
+            switchLatch.await(TIMEOUT_USER_SWITCH_SEC, TimeUnit.SECONDS);
+            removeUser(userInfo.id);
+            mState.resumeTiming();
+        }
+    }
+
     private void switchUser(int userId) throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
-        registerUserSwitchObserver(latch);
+        registerUserSwitchObserver(latch, null, userId);
         mAm.switchUser(userId);
         latch.await(TIMEOUT_USER_SWITCH_SEC, TimeUnit.SECONDS);
     }
 
-    private void registerUserSwitchObserver(final CountDownLatch latch) throws Exception {
-        ActivityManagerNative.getDefault().registerUserSwitchObserver(
-                new SynchronousUserSwitchObserver() {
-                    @Override
-                    public void onUserSwitching(int newUserId) throws RemoteException {
-                    }
+    private void stopUser(int userId) throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+        mIam.stopUser(userId, false /* force */, new IStopUserCallback.Stub() {
+            @Override
+            public void userStopped(int userId) throws RemoteException {
+                latch.countDown();
+            }
 
+            @Override
+            public void userStopAborted(int userId) throws RemoteException {
+            }
+        });
+        latch.await(TIMEOUT_USER_STOP_SEC, TimeUnit.SECONDS);
+    }
+
+    private void registerUserSwitchObserver(final CountDownLatch switchLatch,
+            final CountDownLatch bootCompleteLatch, final int userId) throws Exception {
+        ActivityManagerNative.getDefault().registerUserSwitchObserver(
+                new UserSwitchObserver() {
                     @Override
                     public void onUserSwitchComplete(int newUserId) throws RemoteException {
-                        latch.countDown();
+                        if (switchLatch != null && userId == newUserId) {
+                            switchLatch.countDown();
+                        }
                     }
 
                     @Override
-                    public void onForegroundProfileSwitch(int newProfileId) throws RemoteException {
+                    public void onLockedBootComplete(int newUserId) {
+                        if (bootCompleteLatch != null && userId == newUserId) {
+                            bootCompleteLatch.countDown();
+                        }
                     }
                 }, "UserLifecycleTest");
     }
 
-    private void removeUser(int userId) throws Exception {
-        mUm.removeUser(userId);
-        final long startTime = System.currentTimeMillis();
-        while (mUm.getUserInfo(userId) != null &&
-                System.currentTimeMillis() - startTime < TIMEOUT_REMOVE_USER_SEC) {
-            Thread.sleep(CHECK_USER_REMOVED_INTERVAL_MS);
+    private void registerBroadcastReceiver(final String action, final CountDownLatch latch,
+            final int userId) {
+        InstrumentationRegistry.getContext().registerReceiverAsUser(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (action.equals(intent.getAction()) && intent.getIntExtra(
+                        Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL) == userId) {
+                    latch.countDown();
+                }
+            }
+        }, UserHandle.of(userId), new IntentFilter(action), null, null);
+    }
+
+    private void removeUser(int userId) {
+        try {
+            mUm.removeUser(userId);
+            final long startTime = System.currentTimeMillis();
+            while (mUm.getUserInfo(userId) != null &&
+                    System.currentTimeMillis() - startTime < TIMEOUT_REMOVE_USER_MS) {
+                Thread.sleep(CHECK_USER_REMOVED_INTERVAL_MS);
+            }
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+        } catch (Exception e) {
+            // Ignore
         }
         if (mUm.getUserInfo(userId) != null) {
             mUsersToRemove.add(userId);
diff --git a/api/current.txt b/api/current.txt
index 7b8930c..3d11602 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2921,11 +2921,11 @@
     field public static final java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
   }
 
-  public abstract interface AccountManagerCallback {
+  public abstract interface AccountManagerCallback<V> {
     method public abstract void run(android.accounts.AccountManagerFuture<V>);
   }
 
-  public abstract interface AccountManagerFuture {
+  public abstract interface AccountManagerFuture<V> {
     method public abstract boolean cancel(boolean);
     method public abstract V getResult() throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
     method public abstract V getResult(long, java.util.concurrent.TimeUnit) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
@@ -3071,7 +3071,7 @@
     method public java.lang.Object evaluate(float, java.lang.Object, java.lang.Object);
   }
 
-  public abstract class BidirectionalTypeConverter extends android.animation.TypeConverter {
+  public abstract class BidirectionalTypeConverter<T, V> extends android.animation.TypeConverter {
     ctor public BidirectionalTypeConverter(java.lang.Class<T>, java.lang.Class<V>);
     method public abstract T convertBack(V);
     method public android.animation.BidirectionalTypeConverter<V, T> invert();
@@ -3163,26 +3163,26 @@
     method public java.lang.String getPropertyName();
     method public java.lang.Object getTarget();
     method public static android.animation.ObjectAnimator ofArgb(java.lang.Object, java.lang.String, int...);
-    method public static android.animation.ObjectAnimator ofArgb(T, android.util.Property<T, java.lang.Integer>, int...);
+    method public static <T> android.animation.ObjectAnimator ofArgb(T, android.util.Property<T, java.lang.Integer>, int...);
     method public static android.animation.ObjectAnimator ofFloat(java.lang.Object, java.lang.String, float...);
     method public static android.animation.ObjectAnimator ofFloat(java.lang.Object, java.lang.String, java.lang.String, android.graphics.Path);
-    method public static android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, float...);
-    method public static android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, android.util.Property<T, java.lang.Float>, android.graphics.Path);
+    method public static <T> android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, float...);
+    method public static <T> android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, android.util.Property<T, java.lang.Float>, android.graphics.Path);
     method public static android.animation.ObjectAnimator ofInt(java.lang.Object, java.lang.String, int...);
     method public static android.animation.ObjectAnimator ofInt(java.lang.Object, java.lang.String, java.lang.String, android.graphics.Path);
-    method public static android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, int...);
-    method public static android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, android.util.Property<T, java.lang.Integer>, android.graphics.Path);
+    method public static <T> android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, int...);
+    method public static <T> android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, android.util.Property<T, java.lang.Integer>, android.graphics.Path);
     method public static android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, float[][]);
     method public static android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, android.graphics.Path);
-    method public static android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, android.animation.TypeConverter<T, float[]>, android.animation.TypeEvaluator<T>, T...);
+    method public static <T> android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, android.animation.TypeConverter<T, float[]>, android.animation.TypeEvaluator<T>, T...);
     method public static android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, int[][]);
     method public static android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, android.graphics.Path);
-    method public static android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, android.animation.TypeConverter<T, int[]>, android.animation.TypeEvaluator<T>, T...);
+    method public static <T> android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, android.animation.TypeConverter<T, int[]>, android.animation.TypeEvaluator<T>, T...);
     method public static android.animation.ObjectAnimator ofObject(java.lang.Object, java.lang.String, android.animation.TypeEvaluator, java.lang.Object...);
     method public static android.animation.ObjectAnimator ofObject(java.lang.Object, java.lang.String, android.animation.TypeConverter<android.graphics.PointF, ?>, android.graphics.Path);
-    method public static android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeEvaluator<V>, V...);
-    method public static android.animation.ObjectAnimator ofObject(T, android.util.Property<T, P>, android.animation.TypeConverter<V, P>, android.animation.TypeEvaluator<V>, V...);
-    method public static android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeConverter<android.graphics.PointF, V>, android.graphics.Path);
+    method public static <T, V> android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeEvaluator<V>, V...);
+    method public static <T, V, P> android.animation.ObjectAnimator ofObject(T, android.util.Property<T, P>, android.animation.TypeConverter<V, P>, android.animation.TypeEvaluator<V>, V...);
+    method public static <T, V> android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeConverter<android.graphics.PointF, V>, android.graphics.Path);
     method public static android.animation.ObjectAnimator ofPropertyValuesHolder(java.lang.Object, android.animation.PropertyValuesHolder...);
     method public void setAutoCancel(boolean);
     method public void setProperty(android.util.Property);
@@ -3206,17 +3206,17 @@
     method public static android.animation.PropertyValuesHolder ofKeyframe(android.util.Property, android.animation.Keyframe...);
     method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, float[][]);
     method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.graphics.Path);
-    method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter<V, float[]>, android.animation.TypeEvaluator<V>, V...);
-    method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter<T, float[]>, android.animation.TypeEvaluator<T>, android.animation.Keyframe...);
+    method public static <V> android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter<V, float[]>, android.animation.TypeEvaluator<V>, V...);
+    method public static <T> android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter<T, float[]>, android.animation.TypeEvaluator<T>, android.animation.Keyframe...);
     method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, int[][]);
     method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.graphics.Path);
-    method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter<V, int[]>, android.animation.TypeEvaluator<V>, V...);
-    method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter<T, int[]>, android.animation.TypeEvaluator<T>, android.animation.Keyframe...);
+    method public static <V> android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter<V, int[]>, android.animation.TypeEvaluator<V>, V...);
+    method public static <T> android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter<T, int[]>, android.animation.TypeEvaluator<T>, android.animation.Keyframe...);
     method public static android.animation.PropertyValuesHolder ofObject(java.lang.String, android.animation.TypeEvaluator, java.lang.Object...);
     method public static android.animation.PropertyValuesHolder ofObject(java.lang.String, android.animation.TypeConverter<android.graphics.PointF, ?>, android.graphics.Path);
-    method public static android.animation.PropertyValuesHolder ofObject(android.util.Property, android.animation.TypeEvaluator<V>, V...);
-    method public static android.animation.PropertyValuesHolder ofObject(android.util.Property<?, V>, android.animation.TypeConverter<T, V>, android.animation.TypeEvaluator<T>, T...);
-    method public static android.animation.PropertyValuesHolder ofObject(android.util.Property<?, V>, android.animation.TypeConverter<android.graphics.PointF, V>, android.graphics.Path);
+    method public static <V> android.animation.PropertyValuesHolder ofObject(android.util.Property, android.animation.TypeEvaluator<V>, V...);
+    method public static <T, V> android.animation.PropertyValuesHolder ofObject(android.util.Property<?, V>, android.animation.TypeConverter<T, V>, android.animation.TypeEvaluator<T>, T...);
+    method public static <V> android.animation.PropertyValuesHolder ofObject(android.util.Property<?, V>, android.animation.TypeConverter<android.graphics.PointF, V>, android.graphics.Path);
     method public void setConverter(android.animation.TypeConverter);
     method public void setEvaluator(android.animation.TypeEvaluator);
     method public void setFloatValues(float...);
@@ -3253,12 +3253,12 @@
     method public abstract float getInterpolation(float);
   }
 
-  public abstract class TypeConverter {
+  public abstract class TypeConverter<T, V> {
     ctor public TypeConverter(java.lang.Class<T>, java.lang.Class<V>);
     method public abstract V convert(T);
   }
 
-  public abstract interface TypeEvaluator {
+  public abstract interface TypeEvaluator<T> {
     method public abstract T evaluate(float, T, T);
   }
 
@@ -4042,6 +4042,7 @@
     field public static final java.lang.String OPSTR_MOCK_LOCATION = "android:mock_location";
     field public static final java.lang.String OPSTR_MONITOR_HIGH_POWER_LOCATION = "android:monitor_location_high_power";
     field public static final java.lang.String OPSTR_MONITOR_LOCATION = "android:monitor_location";
+    field public static final java.lang.String OPSTR_PROCESS_OUTGOING_CALLS = "android:process_outgoing_calls";
     field public static final java.lang.String OPSTR_READ_CALENDAR = "android:read_calendar";
     field public static final java.lang.String OPSTR_READ_CALL_LOG = "android:read_call_log";
     field public static final java.lang.String OPSTR_READ_CELL_BROADCASTS = "android:read_cell_broadcasts";
@@ -4588,7 +4589,7 @@
     method public android.os.Parcelable saveAllState();
   }
 
-  public abstract class FragmentHostCallback extends android.app.FragmentContainer {
+  public abstract class FragmentHostCallback<E> extends android.app.FragmentContainer {
     ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
     method public void onAttachFragment(android.app.Fragment);
     method public void onDump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
@@ -4855,12 +4856,12 @@
     method public abstract void destroyLoader(int);
     method public abstract void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
     method public static void enableDebugLogging(boolean);
-    method public abstract android.content.Loader<D> getLoader(int);
-    method public abstract android.content.Loader<D> initLoader(int, android.os.Bundle, android.app.LoaderManager.LoaderCallbacks<D>);
-    method public abstract android.content.Loader<D> restartLoader(int, android.os.Bundle, android.app.LoaderManager.LoaderCallbacks<D>);
+    method public abstract <D> android.content.Loader<D> getLoader(int);
+    method public abstract <D> android.content.Loader<D> initLoader(int, android.os.Bundle, android.app.LoaderManager.LoaderCallbacks<D>);
+    method public abstract <D> android.content.Loader<D> restartLoader(int, android.os.Bundle, android.app.LoaderManager.LoaderCallbacks<D>);
   }
 
-  public static abstract interface LoaderManager.LoaderCallbacks {
+  public static abstract interface LoaderManager.LoaderCallbacks<D> {
     method public abstract android.content.Loader<D> onCreateLoader(int, android.os.Bundle);
     method public abstract void onLoadFinished(android.content.Loader<D>, D);
     method public abstract void onLoaderReset(android.content.Loader<D>);
@@ -7677,7 +7678,7 @@
     ctor public AsyncQueryHandler.WorkerHandler(android.os.Looper);
   }
 
-  public abstract class AsyncTaskLoader extends android.content.Loader {
+  public abstract class AsyncTaskLoader<D> extends android.content.Loader {
     ctor public AsyncTaskLoader(android.content.Context);
     method public void cancelLoadInBackground();
     method public boolean isLoadInBackgroundCanceled();
@@ -7859,7 +7860,7 @@
     method public android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
     method public android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method protected final android.os.ParcelFileDescriptor openFileHelper(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
-    method public android.os.ParcelFileDescriptor openPipeHelper(android.net.Uri, java.lang.String, android.os.Bundle, T, android.content.ContentProvider.PipeDataWriter<T>) throws java.io.FileNotFoundException;
+    method public <T> android.os.ParcelFileDescriptor openPipeHelper(android.net.Uri, java.lang.String, android.os.Bundle, T, android.content.ContentProvider.PipeDataWriter<T>) throws java.io.FileNotFoundException;
     method public android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle) throws java.io.FileNotFoundException;
     method public android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public abstract android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
@@ -7872,7 +7873,7 @@
     method public abstract int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
   }
 
-  public static abstract interface ContentProvider.PipeDataWriter {
+  public static abstract interface ContentProvider.PipeDataWriter<T> {
     method public abstract void writeDataToPipe(android.os.ParcelFileDescriptor, android.net.Uri, java.lang.String, android.os.Bundle, T);
   }
 
@@ -8143,7 +8144,7 @@
     method public final java.lang.String getString(int);
     method public final java.lang.String getString(int, java.lang.Object...);
     method public abstract java.lang.Object getSystemService(java.lang.String);
-    method public final T getSystemService(java.lang.Class<T>);
+    method public final <T> T getSystemService(java.lang.Class<T>);
     method public abstract java.lang.String getSystemServiceName(java.lang.Class<?>);
     method public final java.lang.CharSequence getText(int);
     method public abstract android.content.res.Resources.Theme getTheme();
@@ -8498,8 +8499,8 @@
     method public long getLongExtra(java.lang.String, long);
     method public java.lang.String getPackage();
     method public android.os.Parcelable[] getParcelableArrayExtra(java.lang.String);
-    method public java.util.ArrayList<T> getParcelableArrayListExtra(java.lang.String);
-    method public T getParcelableExtra(java.lang.String);
+    method public <T extends android.os.Parcelable> java.util.ArrayList<T> getParcelableArrayListExtra(java.lang.String);
+    method public <T extends android.os.Parcelable> T getParcelableExtra(java.lang.String);
     method public java.lang.String getScheme();
     method public android.content.Intent getSelector();
     method public java.io.Serializable getSerializableExtra(java.lang.String);
@@ -8974,7 +8975,7 @@
     ctor public IntentSender.SendIntentException(java.lang.Exception);
   }
 
-  public class Loader {
+  public class Loader<D> {
     ctor public Loader(android.content.Context);
     method public void abandon();
     method public boolean cancelLoad();
@@ -9011,11 +9012,11 @@
     ctor public Loader.ForceLoadContentObserver();
   }
 
-  public static abstract interface Loader.OnLoadCanceledListener {
+  public static abstract interface Loader.OnLoadCanceledListener<D> {
     method public abstract void onLoadCanceled(android.content.Loader<D>);
   }
 
-  public static abstract interface Loader.OnLoadCompleteListener {
+  public static abstract interface Loader.OnLoadCompleteListener<D> {
     method public abstract void onLoadComplete(android.content.Loader<D>, D);
   }
 
@@ -10887,7 +10888,7 @@
     method public boolean isNull(int);
   }
 
-  public abstract class Observable {
+  public abstract class Observable<T> {
     ctor public Observable();
     method public void registerObserver(T);
     method public void unregisterAll();
@@ -12692,6 +12693,7 @@
   public class SurfaceTexture {
     ctor public SurfaceTexture(int);
     ctor public SurfaceTexture(int, boolean);
+    ctor public SurfaceTexture(boolean);
     method public void attachToGLContext(int);
     method public void detachFromGLContext();
     method public long getTimestamp();
@@ -12778,7 +12780,7 @@
   public class AnimatedStateListDrawable extends android.graphics.drawable.StateListDrawable {
     ctor public AnimatedStateListDrawable();
     method public void addState(int[], android.graphics.drawable.Drawable, int);
-    method public void addTransition(int, int, T, boolean);
+    method public <T extends android.graphics.drawable.Drawable & android.graphics.drawable.Animatable> void addTransition(int, int, T, boolean);
   }
 
   public class AnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable2 {
@@ -13903,7 +13905,7 @@
   }
 
   public final class CameraCharacteristics extends android.hardware.camera2.CameraMetadata {
-    method public T get(android.hardware.camera2.CameraCharacteristics.Key<T>);
+    method public <T> T get(android.hardware.camera2.CameraCharacteristics.Key<T>);
     method public java.util.List<android.hardware.camera2.CaptureRequest.Key<?>> getAvailableCaptureRequestKeys();
     method public java.util.List<android.hardware.camera2.CaptureResult.Key<?>> getAvailableCaptureResultKeys();
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES;
@@ -13988,7 +13990,7 @@
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> TONEMAP_MAX_CURVE_POINTS;
   }
 
-  public static final class CameraCharacteristics.Key {
+  public static final class CameraCharacteristics.Key<T> {
     method public final boolean equals(java.lang.Object);
     method public java.lang.String getName();
     method public final int hashCode();
@@ -14053,7 +14055,7 @@
     method public void onTorchModeUnavailable(java.lang.String);
   }
 
-  public abstract class CameraMetadata {
+  public abstract class CameraMetadata<TKey> {
     method public java.util.List<TKey> getKeys();
     field public static final int COLOR_CORRECTION_ABERRATION_MODE_FAST = 1; // 0x1
     field public static final int COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY = 2; // 0x2
@@ -14261,7 +14263,7 @@
 
   public final class CaptureRequest extends android.hardware.camera2.CameraMetadata implements android.os.Parcelable {
     method public int describeContents();
-    method public T get(android.hardware.camera2.CaptureRequest.Key<T>);
+    method public <T> T get(android.hardware.camera2.CaptureRequest.Key<T>);
     method public java.lang.Object getTag();
     method public boolean isReprocess();
     method public void writeToParcel(android.os.Parcel, int);
@@ -14324,20 +14326,20 @@
   public static final class CaptureRequest.Builder {
     method public void addTarget(android.view.Surface);
     method public android.hardware.camera2.CaptureRequest build();
-    method public T get(android.hardware.camera2.CaptureRequest.Key<T>);
+    method public <T> T get(android.hardware.camera2.CaptureRequest.Key<T>);
     method public void removeTarget(android.view.Surface);
-    method public void set(android.hardware.camera2.CaptureRequest.Key<T>, T);
+    method public <T> void set(android.hardware.camera2.CaptureRequest.Key<T>, T);
     method public void setTag(java.lang.Object);
   }
 
-  public static final class CaptureRequest.Key {
+  public static final class CaptureRequest.Key<T> {
     method public final boolean equals(java.lang.Object);
     method public java.lang.String getName();
     method public final int hashCode();
   }
 
   public class CaptureResult extends android.hardware.camera2.CameraMetadata {
-    method public T get(android.hardware.camera2.CaptureResult.Key<T>);
+    method public <T> T get(android.hardware.camera2.CaptureResult.Key<T>);
     method public long getFrameNumber();
     method public android.hardware.camera2.CaptureRequest getRequest();
     method public int getSequenceId();
@@ -14418,7 +14420,7 @@
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> TONEMAP_PRESET_CURVE;
   }
 
-  public static final class CaptureResult.Key {
+  public static final class CaptureResult.Key<T> {
     method public final boolean equals(java.lang.Object);
     method public java.lang.String getName();
     method public final int hashCode();
@@ -14545,14 +14547,14 @@
     method public android.util.Size[] getInputSizes(int);
     method public final int[] getOutputFormats();
     method public long getOutputMinFrameDuration(int, android.util.Size);
-    method public long getOutputMinFrameDuration(java.lang.Class<T>, android.util.Size);
-    method public android.util.Size[] getOutputSizes(java.lang.Class<T>);
+    method public <T> long getOutputMinFrameDuration(java.lang.Class<T>, android.util.Size);
+    method public <T> android.util.Size[] getOutputSizes(java.lang.Class<T>);
     method public android.util.Size[] getOutputSizes(int);
     method public long getOutputStallDuration(int, android.util.Size);
-    method public long getOutputStallDuration(java.lang.Class<T>, android.util.Size);
+    method public <T> long getOutputStallDuration(java.lang.Class<T>, android.util.Size);
     method public final int[] getValidOutputFormatsForInput(int);
     method public boolean isOutputSupportedFor(int);
-    method public static boolean isOutputSupportedFor(java.lang.Class<T>);
+    method public static <T> boolean isOutputSupportedFor(java.lang.Class<T>);
     method public boolean isOutputSupportedFor(android.view.Surface);
   }
 
@@ -16253,7 +16255,7 @@
 
 package android.icu.text {
 
-  public final class AlphabeticIndex implements java.lang.Iterable {
+  public final class AlphabeticIndex<V> implements java.lang.Iterable {
     ctor public AlphabeticIndex(android.icu.util.ULocale);
     ctor public AlphabeticIndex(java.util.Locale);
     ctor public AlphabeticIndex(android.icu.text.RuleBasedCollator);
@@ -16279,7 +16281,7 @@
     method public android.icu.text.AlphabeticIndex<V> setUnderflowLabel(java.lang.String);
   }
 
-  public static class AlphabeticIndex.Bucket implements java.lang.Iterable {
+  public static class AlphabeticIndex.Bucket<V> implements java.lang.Iterable {
     method public java.lang.String getLabel();
     method public android.icu.text.AlphabeticIndex.Bucket.LabelType getLabelType();
     method public java.util.Iterator<android.icu.text.AlphabeticIndex.Record<V>> iterator();
@@ -16295,14 +16297,14 @@
     enum_constant public static final android.icu.text.AlphabeticIndex.Bucket.LabelType UNDERFLOW;
   }
 
-  public static final class AlphabeticIndex.ImmutableIndex implements java.lang.Iterable {
+  public static final class AlphabeticIndex.ImmutableIndex<V> implements java.lang.Iterable {
     method public android.icu.text.AlphabeticIndex.Bucket<V> getBucket(int);
     method public int getBucketCount();
     method public int getBucketIndex(java.lang.CharSequence);
     method public java.util.Iterator<android.icu.text.AlphabeticIndex.Bucket<V>> iterator();
   }
 
-  public static class AlphabeticIndex.Record {
+  public static class AlphabeticIndex.Record<V> {
     method public V getData();
     method public java.lang.CharSequence getName();
   }
@@ -17815,8 +17817,8 @@
     method public final android.icu.text.UnicodeSet addAll(java.lang.CharSequence);
     method public android.icu.text.UnicodeSet addAll(android.icu.text.UnicodeSet);
     method public android.icu.text.UnicodeSet addAll(java.lang.Iterable<?>);
-    method public android.icu.text.UnicodeSet addAll(T...);
-    method public T addAllTo(T);
+    method public <T extends java.lang.CharSequence> android.icu.text.UnicodeSet addAll(T...);
+    method public <T extends java.util.Collection<java.lang.String>> T addAllTo(T);
     method public void addMatchSetTo(android.icu.text.UnicodeSet);
     method public android.icu.text.UnicodeSet applyIntPropertyValue(int, int);
     method public final android.icu.text.UnicodeSet applyPattern(java.lang.String);
@@ -17844,15 +17846,15 @@
     method public final boolean contains(java.lang.CharSequence);
     method public boolean containsAll(android.icu.text.UnicodeSet);
     method public boolean containsAll(java.lang.String);
-    method public boolean containsAll(java.lang.Iterable<T>);
+    method public <T extends java.lang.CharSequence> boolean containsAll(java.lang.Iterable<T>);
     method public boolean containsNone(int, int);
     method public boolean containsNone(android.icu.text.UnicodeSet);
     method public boolean containsNone(java.lang.CharSequence);
-    method public boolean containsNone(java.lang.Iterable<T>);
+    method public <T extends java.lang.CharSequence> boolean containsNone(java.lang.Iterable<T>);
     method public final boolean containsSome(int, int);
     method public final boolean containsSome(android.icu.text.UnicodeSet);
     method public final boolean containsSome(java.lang.CharSequence);
-    method public final boolean containsSome(java.lang.Iterable<T>);
+    method public final <T extends java.lang.CharSequence> boolean containsSome(java.lang.Iterable<T>);
     method public android.icu.text.UnicodeSet freeze();
     method public static android.icu.text.UnicodeSet from(java.lang.CharSequence);
     method public static android.icu.text.UnicodeSet fromAll(java.lang.CharSequence);
@@ -17870,14 +17872,14 @@
     method public final android.icu.text.UnicodeSet remove(java.lang.CharSequence);
     method public final android.icu.text.UnicodeSet removeAll(java.lang.CharSequence);
     method public android.icu.text.UnicodeSet removeAll(android.icu.text.UnicodeSet);
-    method public android.icu.text.UnicodeSet removeAll(java.lang.Iterable<T>);
+    method public <T extends java.lang.CharSequence> android.icu.text.UnicodeSet removeAll(java.lang.Iterable<T>);
     method public final android.icu.text.UnicodeSet removeAllStrings();
     method public android.icu.text.UnicodeSet retain(int, int);
     method public final android.icu.text.UnicodeSet retain(int);
     method public final android.icu.text.UnicodeSet retain(java.lang.CharSequence);
     method public final android.icu.text.UnicodeSet retainAll(java.lang.CharSequence);
     method public android.icu.text.UnicodeSet retainAll(android.icu.text.UnicodeSet);
-    method public android.icu.text.UnicodeSet retainAll(java.lang.Iterable<T>);
+    method public <T extends java.lang.CharSequence> android.icu.text.UnicodeSet retainAll(java.lang.Iterable<T>);
     method public android.icu.text.UnicodeSet set(int, int);
     method public android.icu.text.UnicodeSet set(android.icu.text.UnicodeSet);
     method public int size();
@@ -18287,7 +18289,7 @@
     method public long getToDate();
   }
 
-  public abstract interface Freezable implements java.lang.Cloneable {
+  public abstract interface Freezable<T> implements java.lang.Cloneable {
     method public abstract T cloneAsThawed();
     method public abstract T freeze();
     method public abstract boolean isFrozen();
@@ -18569,7 +18571,7 @@
     field public static final android.icu.util.TimeUnit YEAR;
   }
 
-  public class Output {
+  public class Output<T> {
     ctor public Output();
     ctor public Output(T);
     field public T value;
@@ -23897,19 +23899,6 @@
     field public static final android.os.Parcelable.Creator<android.net.ProxyInfo> CREATOR;
   }
 
-  public abstract class PskKeyManager {
-    ctor public PskKeyManager();
-    method public java.lang.String chooseClientKeyIdentity(java.lang.String, java.net.Socket);
-    method public java.lang.String chooseClientKeyIdentity(java.lang.String, javax.net.ssl.SSLEngine);
-    method public java.lang.String chooseServerKeyIdentityHint(java.net.Socket);
-    method public java.lang.String chooseServerKeyIdentityHint(javax.net.ssl.SSLEngine);
-    method public javax.crypto.SecretKey getKey(java.lang.String, java.lang.String, java.net.Socket);
-    method public javax.crypto.SecretKey getKey(java.lang.String, java.lang.String, javax.net.ssl.SSLEngine);
-    field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
-    field public static final int MAX_IDENTITY_LENGTH_BYTES = 128; // 0x80
-    field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100
-  }
-
   public final class RouteInfo implements android.os.Parcelable {
     method public int describeContents();
     method public android.net.IpPrefix getDestination();
@@ -28264,7 +28253,7 @@
 
 package android.os {
 
-  public abstract class AsyncTask {
+  public abstract class AsyncTask<Params, Progress, Result> {
     ctor public AsyncTask();
     method public final boolean cancel(boolean);
     method protected abstract Result doInBackground(Params...);
@@ -28493,16 +28482,16 @@
     method public float getFloat(java.lang.String, float);
     method public float[] getFloatArray(java.lang.String);
     method public java.util.ArrayList<java.lang.Integer> getIntegerArrayList(java.lang.String);
-    method public T getParcelable(java.lang.String);
+    method public <T extends android.os.Parcelable> T getParcelable(java.lang.String);
     method public android.os.Parcelable[] getParcelableArray(java.lang.String);
-    method public java.util.ArrayList<T> getParcelableArrayList(java.lang.String);
+    method public <T extends android.os.Parcelable> java.util.ArrayList<T> getParcelableArrayList(java.lang.String);
     method public java.io.Serializable getSerializable(java.lang.String);
     method public short getShort(java.lang.String);
     method public short getShort(java.lang.String, short);
     method public short[] getShortArray(java.lang.String);
     method public android.util.Size getSize(java.lang.String);
     method public android.util.SizeF getSizeF(java.lang.String);
-    method public android.util.SparseArray<T> getSparseParcelableArray(java.lang.String);
+    method public <T extends android.os.Parcelable> android.util.SparseArray<T> getSparseParcelableArray(java.lang.String);
     method public java.util.ArrayList<java.lang.String> getStringArrayList(java.lang.String);
     method public boolean hasFileDescriptors();
     method public void putAll(android.os.Bundle);
@@ -29007,8 +28996,8 @@
     method public final long[] createLongArray();
     method public final java.lang.String[] createStringArray();
     method public final java.util.ArrayList<java.lang.String> createStringArrayList();
-    method public final T[] createTypedArray(android.os.Parcelable.Creator<T>);
-    method public final java.util.ArrayList<T> createTypedArrayList(android.os.Parcelable.Creator<T>);
+    method public final <T> T[] createTypedArray(android.os.Parcelable.Creator<T>);
+    method public final <T> java.util.ArrayList<T> createTypedArrayList(android.os.Parcelable.Creator<T>);
     method public final int dataAvail();
     method public final int dataCapacity();
     method public final int dataPosition();
@@ -29041,7 +29030,7 @@
     method public final long readLong();
     method public final void readLongArray(long[]);
     method public final void readMap(java.util.Map, java.lang.ClassLoader);
-    method public final T readParcelable(java.lang.ClassLoader);
+    method public final <T extends android.os.Parcelable> T readParcelable(java.lang.ClassLoader);
     method public final android.os.Parcelable[] readParcelableArray(java.lang.ClassLoader);
     method public final android.os.PersistableBundle readPersistableBundle();
     method public final android.os.PersistableBundle readPersistableBundle(java.lang.ClassLoader);
@@ -29054,9 +29043,9 @@
     method public final void readStringArray(java.lang.String[]);
     method public final void readStringList(java.util.List<java.lang.String>);
     method public final android.os.IBinder readStrongBinder();
-    method public final void readTypedArray(T[], android.os.Parcelable.Creator<T>);
-    method public final void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>);
-    method public final T readTypedObject(android.os.Parcelable.Creator<T>);
+    method public final <T> void readTypedArray(T[], android.os.Parcelable.Creator<T>);
+    method public final <T> void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>);
+    method public final <T> T readTypedObject(android.os.Parcelable.Creator<T>);
     method public final java.lang.Object readValue(java.lang.ClassLoader);
     method public final void recycle();
     method public final void setDataCapacity(int);
@@ -29087,7 +29076,7 @@
     method public final void writeMap(java.util.Map);
     method public final void writeNoException();
     method public final void writeParcelable(android.os.Parcelable, int);
-    method public final void writeParcelableArray(T[], int);
+    method public final <T extends android.os.Parcelable> void writeParcelableArray(T[], int);
     method public final void writePersistableBundle(android.os.PersistableBundle);
     method public final void writeSerializable(java.io.Serializable);
     method public final void writeSize(android.util.Size);
@@ -29099,9 +29088,9 @@
     method public final void writeStringList(java.util.List<java.lang.String>);
     method public final void writeStrongBinder(android.os.IBinder);
     method public final void writeStrongInterface(android.os.IInterface);
-    method public final void writeTypedArray(T[], int);
-    method public final void writeTypedList(java.util.List<T>);
-    method public final void writeTypedObject(T, int);
+    method public final <T extends android.os.Parcelable> void writeTypedArray(T[], int);
+    method public final <T extends android.os.Parcelable> void writeTypedList(java.util.List<T>);
+    method public final <T extends android.os.Parcelable> void writeTypedObject(T, int);
     method public final void writeValue(java.lang.Object);
     field public static final android.os.Parcelable.Creator<java.lang.String> STRING_CREATOR;
   }
@@ -29179,11 +29168,11 @@
     field public static final int PARCELABLE_WRITE_RETURN_VALUE = 1; // 0x1
   }
 
-  public static abstract interface Parcelable.ClassLoaderCreator implements android.os.Parcelable.Creator {
+  public static abstract interface Parcelable.ClassLoaderCreator<T> implements android.os.Parcelable.Creator {
     method public abstract T createFromParcel(android.os.Parcel, java.lang.ClassLoader);
   }
 
-  public static abstract interface Parcelable.Creator {
+  public static abstract interface Parcelable.Creator<T> {
     method public abstract T createFromParcel(android.os.Parcel);
     method public abstract T[] newArray(int);
   }
@@ -29298,7 +29287,7 @@
     method public abstract void onProgress(int);
   }
 
-  public class RemoteCallbackList {
+  public class RemoteCallbackList<E extends android.os.IInterface> {
     ctor public RemoteCallbackList();
     method public int beginBroadcast();
     method public void finishBroadcast();
@@ -34625,7 +34614,7 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.carrier.CarrierMessagingService";
   }
 
-  public static abstract interface CarrierMessagingService.ResultCallback {
+  public static abstract interface CarrierMessagingService.ResultCallback<T> {
     method public abstract void onReceiveResult(T) throws android.os.RemoteException;
   }
 
@@ -34777,7 +34766,7 @@
     field public static final java.lang.String EXTRA_SUGGESTION_KEYWORDS = "android.service.media.extra.SUGGESTION_KEYWORDS";
   }
 
-  public class MediaBrowserService.Result {
+  public class MediaBrowserService.Result<T> {
     method public void detach();
     method public void sendResult(T);
   }
@@ -36927,6 +36916,7 @@
     field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
     field public static final java.lang.String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT = "duration_blocking_disabled_after_emergency_int";
     field public static final java.lang.String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool";
+    field public static final java.lang.String KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL = "editable_voicemail_number_bool";
     field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_key_vibration_bool";
     field public static final java.lang.String KEY_FORCE_HOME_NETWORK_BOOL = "force_home_network_bool";
     field public static final java.lang.String KEY_GSM_DTMF_TONE_DELAY_INT = "gsm_dtmf_tone_delay_int";
@@ -37705,14 +37695,14 @@
 
 package android.test {
 
-  public abstract deprecated class ActivityInstrumentationTestCase extends android.test.ActivityTestCase {
+  public abstract deprecated class ActivityInstrumentationTestCase<T extends android.app.Activity> extends android.test.ActivityTestCase {
     ctor public ActivityInstrumentationTestCase(java.lang.String, java.lang.Class<T>);
     ctor public ActivityInstrumentationTestCase(java.lang.String, java.lang.Class<T>, boolean);
     method public T getActivity();
     method public void testActivityTestCaseSetUpProperly() throws java.lang.Exception;
   }
 
-  public abstract deprecated class ActivityInstrumentationTestCase2 extends android.test.ActivityTestCase {
+  public abstract deprecated class ActivityInstrumentationTestCase2<T extends android.app.Activity> extends android.test.ActivityTestCase {
     ctor public deprecated ActivityInstrumentationTestCase2(java.lang.String, java.lang.Class<T>);
     ctor public ActivityInstrumentationTestCase2(java.lang.Class<T>);
     method public T getActivity();
@@ -37727,7 +37717,7 @@
     method protected void setActivity(android.app.Activity);
   }
 
-  public abstract deprecated class ActivityUnitTestCase extends android.test.ActivityTestCase {
+  public abstract deprecated class ActivityUnitTestCase<T extends android.app.Activity> extends android.test.ActivityTestCase {
     ctor public ActivityUnitTestCase(java.lang.Class<T>);
     method public T getActivity();
     method public int getFinishedActivityRequest();
@@ -37773,7 +37763,7 @@
     method public void testStarted(java.lang.String);
   }
 
-  public abstract deprecated class ApplicationTestCase extends android.test.AndroidTestCase {
+  public abstract deprecated class ApplicationTestCase<T extends android.app.Application> extends android.test.AndroidTestCase {
     ctor public ApplicationTestCase(java.lang.Class<T>);
     method protected final void createApplication();
     method public T getApplication();
@@ -37799,8 +37789,8 @@
     method public android.app.Instrumentation getInstrumentation();
     method public deprecated void injectInsrumentation(android.app.Instrumentation);
     method public void injectInstrumentation(android.app.Instrumentation);
-    method public final T launchActivity(java.lang.String, java.lang.Class<T>, android.os.Bundle);
-    method public final T launchActivityWithIntent(java.lang.String, java.lang.Class<T>, android.content.Intent);
+    method public final <T extends android.app.Activity> T launchActivity(java.lang.String, java.lang.Class<T>, android.os.Bundle);
+    method public final <T extends android.app.Activity> T launchActivityWithIntent(java.lang.String, java.lang.Class<T>, android.content.Intent);
     method public void runTestOnUiThread(java.lang.Runnable) throws java.lang.Throwable;
     method public void sendKeys(java.lang.String);
     method public void sendKeys(int...);
@@ -37840,7 +37830,7 @@
 
   public class LoaderTestCase extends android.test.AndroidTestCase {
     ctor public LoaderTestCase();
-    method public T getLoaderResultSynchronously(android.content.Loader<T>);
+    method public <T> T getLoaderResultSynchronously(android.content.Loader<T>);
   }
 
   public final deprecated class MoreAsserts {
@@ -37895,20 +37885,20 @@
     method public abstract void startTiming(boolean);
   }
 
-  public abstract deprecated class ProviderTestCase extends android.test.InstrumentationTestCase {
+  public abstract deprecated class ProviderTestCase<T extends android.content.ContentProvider> extends android.test.InstrumentationTestCase {
     ctor public ProviderTestCase(java.lang.Class<T>, java.lang.String);
     method public android.test.mock.MockContentResolver getMockContentResolver();
     method public android.test.IsolatedContext getMockContext();
     method public T getProvider();
-    method public static android.content.ContentResolver newResolverWithContentProviderFromSql(android.content.Context, java.lang.Class<T>, java.lang.String, java.lang.String, int, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public static <T extends android.content.ContentProvider> android.content.ContentResolver newResolverWithContentProviderFromSql(android.content.Context, java.lang.Class<T>, java.lang.String, java.lang.String, int, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
   }
 
-  public abstract class ProviderTestCase2 extends android.test.AndroidTestCase {
+  public abstract class ProviderTestCase2<T extends android.content.ContentProvider> extends android.test.AndroidTestCase {
     ctor public ProviderTestCase2(java.lang.Class<T>, java.lang.String);
     method public android.test.mock.MockContentResolver getMockContentResolver();
     method public android.test.IsolatedContext getMockContext();
     method public T getProvider();
-    method public static android.content.ContentResolver newResolverWithContentProviderFromSql(android.content.Context, java.lang.String, java.lang.Class<T>, java.lang.String, java.lang.String, int, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public static <T extends android.content.ContentProvider> android.content.ContentResolver newResolverWithContentProviderFromSql(android.content.Context, java.lang.String, java.lang.Class<T>, java.lang.String, java.lang.String, int, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
   }
 
   public deprecated class RenamingDelegatingContext extends android.content.ContextWrapper {
@@ -37916,11 +37906,11 @@
     ctor public RenamingDelegatingContext(android.content.Context, android.content.Context, java.lang.String);
     method public java.lang.String getDatabasePrefix();
     method public void makeExistingFilesAndDbsAccessible();
-    method public static T providerWithRenamedContext(java.lang.Class<T>, android.content.Context, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
-    method public static T providerWithRenamedContext(java.lang.Class<T>, android.content.Context, java.lang.String, boolean) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public static <T extends android.content.ContentProvider> T providerWithRenamedContext(java.lang.Class<T>, android.content.Context, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public static <T extends android.content.ContentProvider> T providerWithRenamedContext(java.lang.Class<T>, android.content.Context, java.lang.String, boolean) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
   }
 
-  public abstract deprecated class ServiceTestCase extends android.test.AndroidTestCase {
+  public abstract deprecated class ServiceTestCase<T extends android.app.Service> extends android.test.AndroidTestCase {
     ctor public ServiceTestCase(java.lang.Class<T>);
     method protected android.os.IBinder bindService(android.content.Intent);
     method public android.app.Application getApplication();
@@ -37933,7 +37923,7 @@
     method public void testServiceTestCaseSetUpProperly() throws java.lang.Exception;
   }
 
-  public abstract deprecated class SingleLaunchActivityTestCase extends android.test.InstrumentationTestCase {
+  public abstract deprecated class SingleLaunchActivityTestCase<T extends android.app.Activity> extends android.test.InstrumentationTestCase {
     ctor public SingleLaunchActivityTestCase(java.lang.String, java.lang.Class<T>);
     method public T getActivity();
     method public void testActivityTestCaseSetUpProperly() throws java.lang.Exception;
@@ -38288,7 +38278,7 @@
     ctor public TestMethod(java.lang.String, java.lang.Class<? extends junit.framework.TestCase>);
     ctor public TestMethod(junit.framework.TestCase);
     method public junit.framework.TestCase createTest() throws java.lang.IllegalAccessException, java.lang.InstantiationException, java.lang.reflect.InvocationTargetException;
-    method public T getAnnotation(java.lang.Class<T>);
+    method public <T extends java.lang.annotation.Annotation> T getAnnotation(java.lang.Class<T>);
     method public java.lang.Class<? extends junit.framework.TestCase> getEnclosingClass();
     method public java.lang.String getEnclosingClassname();
     method public java.lang.String getName();
@@ -38736,7 +38726,7 @@
     method public int getSpanEnd(java.lang.Object);
     method public int getSpanFlags(java.lang.Object);
     method public int getSpanStart(java.lang.Object);
-    method public T[] getSpans(int, int, java.lang.Class<T>);
+    method public <T> T[] getSpans(int, int, java.lang.Class<T>);
     method public deprecated int getTextRunCursor(int, int, int, int, int, android.graphics.Paint);
     method public int getTextWatcherDepth();
     method public android.text.SpannableStringBuilder insert(int, java.lang.CharSequence, int, int);
@@ -38758,7 +38748,7 @@
     method public int getSpanEnd(java.lang.Object);
     method public int getSpanFlags(java.lang.Object);
     method public int getSpanStart(java.lang.Object);
-    method public T[] getSpans(int, int, java.lang.Class<T>);
+    method public <T> T[] getSpans(int, int, java.lang.Class<T>);
     method public final int length();
     method public int nextSpanTransition(int, int, java.lang.Class);
     method public final java.lang.String toString();
@@ -38768,7 +38758,7 @@
     method public abstract int getSpanEnd(java.lang.Object);
     method public abstract int getSpanFlags(java.lang.Object);
     method public abstract int getSpanStart(java.lang.Object);
-    method public abstract T[] getSpans(int, int, java.lang.Class<T>);
+    method public abstract <T> T[] getSpans(int, int, java.lang.Class<T>);
     method public abstract int nextSpanTransition(int, int, java.lang.Class);
     field public static final int SPAN_COMPOSING = 256; // 0x100
     field public static final int SPAN_EXCLUSIVE_EXCLUSIVE = 33; // 0x21
@@ -39746,7 +39736,7 @@
     field public static final int WEEKDAY_WEDNESDAY = 4; // 0x4
   }
 
-  public static class TtsSpan.Builder {
+  public static class TtsSpan.Builder<C extends android.text.style.TtsSpan.Builder<?>> {
     ctor public TtsSpan.Builder(java.lang.String);
     method public android.text.style.TtsSpan build();
     method public C setIntArgument(java.lang.String, int);
@@ -39842,7 +39832,7 @@
     method public android.text.style.TtsSpan.OrdinalBuilder setNumber(java.lang.String);
   }
 
-  public static class TtsSpan.SemioticClassBuilder extends android.text.style.TtsSpan.Builder {
+  public static class TtsSpan.SemioticClassBuilder<C extends android.text.style.TtsSpan.SemioticClassBuilder<?>> extends android.text.style.TtsSpan.Builder {
     ctor public TtsSpan.SemioticClassBuilder(java.lang.String);
     method public C setAnimacy(java.lang.String);
     method public C setCase(java.lang.String);
@@ -40249,7 +40239,7 @@
     ctor public AndroidRuntimeException(java.lang.Exception);
   }
 
-  public final class ArrayMap implements java.util.Map {
+  public final class ArrayMap<K, V> implements java.util.Map {
     ctor public ArrayMap();
     ctor public ArrayMap(int);
     ctor public ArrayMap(android.util.ArrayMap<K, V>);
@@ -40277,7 +40267,7 @@
     method public java.util.Collection<V> values();
   }
 
-  public final class ArraySet implements java.util.Collection java.util.Set {
+  public final class ArraySet<E> implements java.util.Collection java.util.Set {
     ctor public ArraySet();
     ctor public ArraySet(int);
     ctor public ArraySet(android.util.ArraySet<E>);
@@ -40298,7 +40288,7 @@
     method public boolean retainAll(java.util.Collection<?>);
     method public int size();
     method public java.lang.Object[] toArray();
-    method public T[] toArray(T[]);
+    method public <T> T[] toArray(T[]);
     method public E valueAt(int);
   }
 
@@ -40443,13 +40433,13 @@
   public deprecated class FloatMath {
   }
 
-  public abstract class FloatProperty extends android.util.Property {
+  public abstract class FloatProperty<T> extends android.util.Property {
     ctor public FloatProperty(java.lang.String);
     method public final void set(T, java.lang.Float);
     method public abstract void setValue(T, float);
   }
 
-  public abstract class IntProperty extends android.util.Property {
+  public abstract class IntProperty<T> extends android.util.Property {
     ctor public IntProperty(java.lang.String);
     method public final void set(T, java.lang.Integer);
     method public abstract void setValue(T, int);
@@ -40549,7 +40539,7 @@
     method public void println(java.lang.String);
   }
 
-  public class LongSparseArray implements java.lang.Cloneable {
+  public class LongSparseArray<E> implements java.lang.Cloneable {
     ctor public LongSparseArray();
     ctor public LongSparseArray(int);
     method public void append(long, E);
@@ -40570,7 +40560,7 @@
     method public E valueAt(int);
   }
 
-  public class LruCache {
+  public class LruCache<K, V> {
     ctor public LruCache(int);
     method protected V create(K);
     method public final synchronized int createCount();
@@ -40658,9 +40648,9 @@
     ctor public NoSuchPropertyException(java.lang.String);
   }
 
-  public class Pair {
+  public class Pair<F, S> {
     ctor public Pair(F, S);
-    method public static android.util.Pair<A, B> create(A, B);
+    method public static <A, B> android.util.Pair<A, B> create(A, B);
     field public final F first;
     field public final S second;
   }
@@ -40693,22 +40683,22 @@
     method public abstract void println(java.lang.String);
   }
 
-  public abstract class Property {
+  public abstract class Property<T, V> {
     ctor public Property(java.lang.Class<V>, java.lang.String);
     method public abstract V get(T);
     method public java.lang.String getName();
     method public java.lang.Class<V> getType();
     method public boolean isReadOnly();
-    method public static android.util.Property<T, V> of(java.lang.Class<T>, java.lang.Class<V>, java.lang.String);
+    method public static <T, V> android.util.Property<T, V> of(java.lang.Class<T>, java.lang.Class<V>, java.lang.String);
     method public void set(T, V);
   }
 
-  public final class Range {
+  public final class Range<T extends java.lang.Comparable<? super T>> {
     ctor public Range(T, T);
     method public T clamp(T);
     method public boolean contains(T);
     method public boolean contains(android.util.Range<T>);
-    method public static android.util.Range<T> create(T, T);
+    method public static <T extends java.lang.Comparable<? super T>> android.util.Range<T> create(T, T);
     method public android.util.Range<T> extend(android.util.Range<T>);
     method public android.util.Range<T> extend(T, T);
     method public android.util.Range<T> extend(T);
@@ -40752,7 +40742,7 @@
     method public static android.util.SizeF parseSizeF(java.lang.String) throws java.lang.NumberFormatException;
   }
 
-  public class SparseArray implements java.lang.Cloneable {
+  public class SparseArray<E> implements java.lang.Cloneable {
     ctor public SparseArray();
     ctor public SparseArray(int);
     method public void append(int, E);
@@ -45487,7 +45477,7 @@
     method public static java.lang.String stripAnchor(java.lang.String);
   }
 
-  public abstract interface ValueCallback {
+  public abstract interface ValueCallback<T> {
     method public abstract void onReceiveValue(T);
   }
 
@@ -45848,7 +45838,7 @@
     method public int getContentHeight();
     method public android.graphics.Bitmap getFavicon();
     method public android.webkit.WebView.HitTestResult getHitTestResult();
-    method public java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
+    method public deprecated java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
     method public java.lang.String getOriginalUrl();
     method public int getProgress();
     method public deprecated float getScale();
@@ -45891,7 +45881,7 @@
     method public void setDownloadListener(android.webkit.DownloadListener);
     method public void setFindListener(android.webkit.WebView.FindListener);
     method public deprecated void setHorizontalScrollbarOverlay(boolean);
-    method public void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public deprecated void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
     method public void setInitialScale(int);
     method public deprecated void setMapTrackballToArrowKeys(boolean);
     method public void setNetworkAvailable(boolean);
@@ -45989,10 +45979,12 @@
     method public abstract void clearFormData();
     method public abstract void clearHttpAuthUsernamePassword();
     method public abstract deprecated void clearUsernamePassword();
+    method public abstract java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
     method public static android.webkit.WebViewDatabase getInstance(android.content.Context);
     method public abstract boolean hasFormData();
     method public abstract boolean hasHttpAuthUsernamePassword();
     method public abstract deprecated boolean hasUsernamePassword();
+    method public abstract void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
   }
 
   public class WebViewFragment extends android.app.Fragment {
@@ -46221,7 +46213,7 @@
     field public static final int NO_SELECTION = -2147483648; // 0x80000000
   }
 
-  public abstract class AdapterView extends android.view.ViewGroup {
+  public abstract class AdapterView<T extends android.widget.Adapter> extends android.view.ViewGroup {
     ctor public AdapterView(android.content.Context);
     ctor public AdapterView(android.content.Context, android.util.AttributeSet);
     ctor public AdapterView(android.content.Context, android.util.AttributeSet, int);
@@ -46344,7 +46336,7 @@
     ctor public AnalogClock(android.content.Context, android.util.AttributeSet, int, int);
   }
 
-  public class ArrayAdapter extends android.widget.BaseAdapter implements android.widget.Filterable android.widget.ThemedSpinnerAdapter {
+  public class ArrayAdapter<T> extends android.widget.BaseAdapter implements android.widget.Filterable android.widget.ThemedSpinnerAdapter {
     ctor public ArrayAdapter(android.content.Context, int);
     ctor public ArrayAdapter(android.content.Context, int, int);
     ctor public ArrayAdapter(android.content.Context, int, T[]);
@@ -46405,7 +46397,7 @@
     method protected void performFiltering(java.lang.CharSequence, int);
     method public void performValidation();
     method protected void replaceText(java.lang.CharSequence);
-    method public void setAdapter(T);
+    method public <T extends android.widget.ListAdapter & android.widget.Filterable> void setAdapter(T);
     method public void setCompletionHint(java.lang.CharSequence);
     method public void setDropDownAnchor(int);
     method public void setDropDownBackgroundDrawable(android.graphics.drawable.Drawable);
@@ -48691,7 +48683,7 @@
 
 package com.android.internal.util {
 
-  public abstract interface Predicate {
+  public abstract interface Predicate<T> {
     method public abstract boolean apply(T);
   }
 
@@ -50763,22 +50755,22 @@
     enum_constant public static final java.lang.Character.UnicodeScript YI;
   }
 
-  public final class Class implements java.lang.reflect.AnnotatedElement java.lang.reflect.GenericDeclaration java.io.Serializable java.lang.reflect.Type {
-    method public java.lang.Class<? extends U> asSubclass(java.lang.Class<U>);
+  public final class Class<T> implements java.lang.reflect.AnnotatedElement java.lang.reflect.GenericDeclaration java.io.Serializable java.lang.reflect.Type {
+    method public <U> java.lang.Class<? extends U> asSubclass(java.lang.Class<U>);
     method public T cast(java.lang.Object);
     method public boolean desiredAssertionStatus();
     method public static java.lang.Class<?> forName(java.lang.String) throws java.lang.ClassNotFoundException;
     method public static java.lang.Class<?> forName(java.lang.String, boolean, java.lang.ClassLoader) throws java.lang.ClassNotFoundException;
-    method public A getAnnotation(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
-    method public A[] getAnnotationsByType(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A[] getAnnotationsByType(java.lang.Class<A>);
     method public java.lang.String getCanonicalName();
     method public java.lang.ClassLoader getClassLoader();
     method public java.lang.Class<?>[] getClasses();
     method public java.lang.Class<?> getComponentType();
     method public java.lang.reflect.Constructor<T> getConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
-    method public A getDeclaredAnnotation(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A getDeclaredAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public java.lang.Class<?>[] getDeclaredClasses();
     method public java.lang.reflect.Constructor<T> getDeclaredConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
@@ -50890,7 +50882,7 @@
   public abstract interface Cloneable {
   }
 
-  public abstract interface Comparable {
+  public abstract interface Comparable<T> {
     method public abstract int compareTo(T);
   }
 
@@ -50944,7 +50936,7 @@
     field public static final java.lang.Class<java.lang.Double> TYPE;
   }
 
-  public abstract class Enum implements java.lang.Comparable java.io.Serializable {
+  public abstract class Enum<E extends java.lang.Enum<E>> implements java.lang.Comparable java.io.Serializable {
     ctor protected Enum(java.lang.String, int);
     method protected final java.lang.Object clone() throws java.lang.CloneNotSupportedException;
     method public final int compareTo(E);
@@ -50954,7 +50946,7 @@
     method public final int hashCode();
     method public final java.lang.String name();
     method public final int ordinal();
-    method public static T valueOf(java.lang.Class<T>, java.lang.String);
+    method public static <T extends java.lang.Enum<T>> T valueOf(java.lang.Class<T>, java.lang.String);
   }
 
   public class EnumConstantNotPresentException extends java.lang.RuntimeException {
@@ -51073,7 +51065,7 @@
     ctor public IndexOutOfBoundsException(java.lang.String);
   }
 
-  public class InheritableThreadLocal extends java.lang.ThreadLocal {
+  public class InheritableThreadLocal<T> extends java.lang.ThreadLocal {
     ctor public InheritableThreadLocal();
     method protected T childValue(T);
   }
@@ -51152,7 +51144,7 @@
     ctor public InterruptedException(java.lang.String);
   }
 
-  public abstract interface Iterable {
+  public abstract interface Iterable<T> {
     method public default void forEach(java.util.function.Consumer<? super T>);
     method public abstract java.util.Iterator<T> iterator();
     method public default java.util.Spliterator<T> spliterator();
@@ -51367,12 +51359,12 @@
   }
 
   public class Package implements java.lang.reflect.AnnotatedElement {
-    method public A getAnnotation(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
-    method public A[] getAnnotationsByType(java.lang.Class<A>);
-    method public A getDeclaredAnnotation(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A[] getAnnotationsByType(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A getDeclaredAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
-    method public A[] getDeclaredAnnotationsByType(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A[] getDeclaredAnnotationsByType(java.lang.Class<A>);
     method public java.lang.String getImplementationTitle();
     method public java.lang.String getImplementationVendor();
     method public java.lang.String getImplementationVersion();
@@ -51971,13 +51963,13 @@
     method public void uncaughtException(java.lang.Thread, java.lang.Throwable);
   }
 
-  public class ThreadLocal {
+  public class ThreadLocal<T> {
     ctor public ThreadLocal();
     method public T get();
     method protected T initialValue();
     method public void remove();
     method public void set(T);
-    method public static java.lang.ThreadLocal<S> withInitial(java.util.function.Supplier<? extends S>);
+    method public static <S> java.lang.ThreadLocal<S> withInitial(java.util.function.Supplier<? extends S>);
   }
 
   public class Throwable implements java.io.Serializable {
@@ -52080,6 +52072,8 @@
     enum_constant public static final java.lang.annotation.ElementType PACKAGE;
     enum_constant public static final java.lang.annotation.ElementType PARAMETER;
     enum_constant public static final java.lang.annotation.ElementType TYPE;
+    enum_constant public static final java.lang.annotation.ElementType TYPE_PARAMETER;
+    enum_constant public static final java.lang.annotation.ElementType TYPE_USE;
   }
 
   public class IncompleteAnnotationException extends java.lang.RuntimeException {
@@ -52115,30 +52109,30 @@
 
 package java.lang.ref {
 
-  public class PhantomReference extends java.lang.ref.Reference {
+  public class PhantomReference<T> extends java.lang.ref.Reference {
     ctor public PhantomReference(T, java.lang.ref.ReferenceQueue<? super T>);
   }
 
-  public abstract class Reference {
+  public abstract class Reference<T> {
     method public void clear();
     method public boolean enqueue();
     method public T get();
     method public boolean isEnqueued();
   }
 
-  public class ReferenceQueue {
+  public class ReferenceQueue<T> {
     ctor public ReferenceQueue();
     method public java.lang.ref.Reference<? extends T> poll();
     method public java.lang.ref.Reference<? extends T> remove(long) throws java.lang.IllegalArgumentException, java.lang.InterruptedException;
     method public java.lang.ref.Reference<? extends T> remove() throws java.lang.InterruptedException;
   }
 
-  public class SoftReference extends java.lang.ref.Reference {
+  public class SoftReference<T> extends java.lang.ref.Reference {
     ctor public SoftReference(T);
     ctor public SoftReference(T, java.lang.ref.ReferenceQueue<? super T>);
   }
 
-  public class WeakReference extends java.lang.ref.Reference {
+  public class WeakReference<T> extends java.lang.ref.Reference {
     ctor public WeakReference(T);
     ctor public WeakReference(T, java.lang.ref.ReferenceQueue<? super T>);
   }
@@ -52149,7 +52143,7 @@
 
   public class AccessibleObject implements java.lang.reflect.AnnotatedElement {
     ctor protected AccessibleObject();
-    method public T getAnnotation(java.lang.Class<T>);
+    method public <T extends java.lang.annotation.Annotation> T getAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getAnnotations();
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public boolean isAccessible();
@@ -52158,12 +52152,12 @@
   }
 
   public abstract interface AnnotatedElement {
-    method public abstract T getAnnotation(java.lang.Class<T>);
+    method public abstract <T extends java.lang.annotation.Annotation> T getAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getAnnotations();
-    method public default T[] getAnnotationsByType(java.lang.Class<T>);
-    method public default java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
+    method public default <T extends java.lang.annotation.Annotation> T[] getAnnotationsByType(java.lang.Class<T>);
+    method public default <T extends java.lang.annotation.Annotation> T getDeclaredAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getDeclaredAnnotations();
-    method public default T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
+    method public default <T extends java.lang.annotation.Annotation> T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public default boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
   }
 
@@ -52191,7 +52185,7 @@
     method public static void setShort(java.lang.Object, int, short) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
   }
 
-  public final class Constructor extends java.lang.reflect.Executable {
+  public final class Constructor<T> extends java.lang.reflect.Executable {
     method public java.lang.Class<T> getDeclaringClass();
     method public java.lang.Class<?>[] getExceptionTypes();
     method public int getModifiers();
@@ -52339,7 +52333,7 @@
   }
 
   public final class Parameter implements java.lang.reflect.AnnotatedElement {
-    method public T getAnnotation(java.lang.Class<T>);
+    method public <T extends java.lang.annotation.Annotation> T getAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getAnnotations();
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public java.lang.reflect.Executable getDeclaringExecutable();
@@ -52376,7 +52370,7 @@
   public abstract interface Type {
   }
 
-  public abstract interface TypeVariable implements java.lang.reflect.Type {
+  public abstract interface TypeVariable<D extends java.lang.reflect.GenericDeclaration> implements java.lang.reflect.Type {
     method public abstract java.lang.reflect.Type[] getBounds();
     method public abstract D getGenericDeclaration();
     method public abstract java.lang.String getName();
@@ -53165,7 +53159,7 @@
     method public abstract java.net.SocketImpl createSocketImpl();
   }
 
-  public abstract interface SocketOption {
+  public abstract interface SocketOption<T> {
     method public abstract java.lang.String name();
     method public abstract java.lang.Class<T> type();
   }
@@ -53697,9 +53691,9 @@
   }
 
   public abstract interface AsynchronousByteChannel implements java.nio.channels.AsynchronousChannel {
-    method public abstract void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer);
-    method public abstract void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer);
   }
 
@@ -53727,25 +53721,25 @@
   public abstract class AsynchronousFileChannel implements java.nio.channels.AsynchronousChannel {
     ctor protected AsynchronousFileChannel();
     method public abstract void force(boolean) throws java.io.IOException;
-    method public abstract void lock(long, long, boolean, A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
-    method public final void lock(A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
+    method public abstract <A> void lock(long, long, boolean, A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
+    method public final <A> void lock(A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
     method public abstract java.util.concurrent.Future<java.nio.channels.FileLock> lock(long, long, boolean);
     method public final java.util.concurrent.Future<java.nio.channels.FileLock> lock();
     method public static java.nio.channels.AsynchronousFileChannel open(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.util.concurrent.ExecutorService, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
     method public static java.nio.channels.AsynchronousFileChannel open(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public abstract void read(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void read(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer, long);
     method public abstract long size() throws java.io.IOException;
     method public abstract java.nio.channels.AsynchronousFileChannel truncate(long) throws java.io.IOException;
     method public abstract java.nio.channels.FileLock tryLock(long, long, boolean) throws java.io.IOException;
     method public final java.nio.channels.FileLock tryLock() throws java.io.IOException;
-    method public abstract void write(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void write(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer, long);
   }
 
   public abstract class AsynchronousServerSocketChannel implements java.nio.channels.AsynchronousChannel java.nio.channels.NetworkChannel {
     ctor protected AsynchronousServerSocketChannel(java.nio.channels.spi.AsynchronousChannelProvider);
-    method public abstract void accept(A, java.nio.channels.CompletionHandler<java.nio.channels.AsynchronousSocketChannel, ? super A>);
+    method public abstract <A> void accept(A, java.nio.channels.CompletionHandler<java.nio.channels.AsynchronousSocketChannel, ? super A>);
     method public abstract java.util.concurrent.Future<java.nio.channels.AsynchronousSocketChannel> accept();
     method public final java.nio.channels.AsynchronousServerSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.nio.channels.AsynchronousServerSocketChannel bind(java.net.SocketAddress, int) throws java.io.IOException;
@@ -53753,30 +53747,30 @@
     method public static java.nio.channels.AsynchronousServerSocketChannel open(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
     method public static java.nio.channels.AsynchronousServerSocketChannel open() throws java.io.IOException;
     method public final java.nio.channels.spi.AsynchronousChannelProvider provider();
-    method public abstract java.nio.channels.AsynchronousServerSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <T> java.nio.channels.AsynchronousServerSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
   }
 
   public abstract class AsynchronousSocketChannel implements java.nio.channels.AsynchronousByteChannel java.nio.channels.NetworkChannel {
     ctor protected AsynchronousSocketChannel(java.nio.channels.spi.AsynchronousChannelProvider);
     method public abstract java.nio.channels.AsynchronousSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
-    method public abstract void connect(java.net.SocketAddress, A, java.nio.channels.CompletionHandler<java.lang.Void, ? super A>);
+    method public abstract <A> void connect(java.net.SocketAddress, A, java.nio.channels.CompletionHandler<java.lang.Void, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Void> connect(java.net.SocketAddress);
     method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
     method public abstract java.net.SocketAddress getRemoteAddress() throws java.io.IOException;
     method public static java.nio.channels.AsynchronousSocketChannel open(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
     method public static java.nio.channels.AsynchronousSocketChannel open() throws java.io.IOException;
     method public final java.nio.channels.spi.AsynchronousChannelProvider provider();
-    method public abstract void read(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public final void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void read(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public final <A> void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer);
-    method public abstract void read(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
-    method public abstract java.nio.channels.AsynchronousSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <A> void read(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
+    method public abstract <T> java.nio.channels.AsynchronousSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public abstract java.nio.channels.AsynchronousSocketChannel shutdownInput() throws java.io.IOException;
     method public abstract java.nio.channels.AsynchronousSocketChannel shutdownOutput() throws java.io.IOException;
-    method public abstract void write(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public final void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void write(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public final <A> void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer);
-    method public abstract void write(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
+    method public abstract <A> void write(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
   }
 
   public abstract interface ByteChannel implements java.nio.channels.ReadableByteChannel java.nio.channels.WritableByteChannel {
@@ -53816,7 +53810,7 @@
     ctor public ClosedSelectorException();
   }
 
-  public abstract interface CompletionHandler {
+  public abstract interface CompletionHandler<V, A> {
     method public abstract void completed(V, A);
     method public abstract void failed(java.lang.Throwable, A);
   }
@@ -53840,7 +53834,7 @@
     method public final long read(java.nio.ByteBuffer[]) throws java.io.IOException;
     method public abstract java.net.SocketAddress receive(java.nio.ByteBuffer) throws java.io.IOException;
     method public abstract int send(java.nio.ByteBuffer, java.net.SocketAddress) throws java.io.IOException;
-    method public abstract java.nio.channels.DatagramChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <T> java.nio.channels.DatagramChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public abstract java.net.DatagramSocket socket();
     method public final int validOps();
     method public abstract int write(java.nio.ByteBuffer) throws java.io.IOException;
@@ -53945,8 +53939,8 @@
   public abstract interface NetworkChannel implements java.nio.channels.Channel {
     method public abstract java.nio.channels.NetworkChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
-    method public abstract T getOption(java.net.SocketOption<T>) throws java.io.IOException;
-    method public abstract java.nio.channels.NetworkChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <T> T getOption(java.net.SocketOption<T>) throws java.io.IOException;
+    method public abstract <T> java.nio.channels.NetworkChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public abstract java.util.Set<java.net.SocketOption<?>> supportedOptions();
   }
 
@@ -54068,7 +54062,7 @@
     method public abstract java.nio.channels.ServerSocketChannel bind(java.net.SocketAddress, int) throws java.io.IOException;
     method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
     method public static java.nio.channels.ServerSocketChannel open() throws java.io.IOException;
-    method public abstract java.nio.channels.ServerSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <T> java.nio.channels.ServerSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public abstract java.net.ServerSocket socket();
     method public final int validOps();
   }
@@ -54091,7 +54085,7 @@
     method public abstract int read(java.nio.ByteBuffer) throws java.io.IOException;
     method public abstract long read(java.nio.ByteBuffer[], int, int) throws java.io.IOException;
     method public final long read(java.nio.ByteBuffer[]) throws java.io.IOException;
-    method public abstract java.nio.channels.SocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <T> java.nio.channels.SocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public abstract java.nio.channels.SocketChannel shutdownInput() throws java.io.IOException;
     method public abstract java.nio.channels.SocketChannel shutdownOutput() throws java.io.IOException;
     method public abstract java.net.Socket socket();
@@ -54376,11 +54370,11 @@
     ctor public DirectoryNotEmptyException(java.lang.String);
   }
 
-  public abstract interface DirectoryStream implements java.io.Closeable java.lang.Iterable {
+  public abstract interface DirectoryStream<T> implements java.io.Closeable java.lang.Iterable {
     method public abstract java.util.Iterator<T> iterator();
   }
 
-  public static abstract interface DirectoryStream.Filter {
+  public static abstract interface DirectoryStream.Filter<T> {
     method public abstract boolean accept(T) throws java.io.IOException;
   }
 
@@ -54392,7 +54386,7 @@
   public abstract class FileStore {
     ctor protected FileStore();
     method public abstract java.lang.Object getAttribute(java.lang.String) throws java.io.IOException;
-    method public abstract V getFileStoreAttributeView(java.lang.Class<V>);
+    method public abstract <V extends java.nio.file.attribute.FileStoreAttributeView> V getFileStoreAttributeView(java.lang.Class<V>);
     method public abstract long getTotalSpace() throws java.io.IOException;
     method public abstract long getUnallocatedSpace() throws java.io.IOException;
     method public abstract long getUsableSpace() throws java.io.IOException;
@@ -54464,7 +54458,7 @@
     enum_constant public static final java.nio.file.FileVisitResult TERMINATE;
   }
 
-  public abstract interface FileVisitor {
+  public abstract interface FileVisitor<T> {
     method public abstract java.nio.file.FileVisitResult postVisitDirectory(T, java.io.IOException) throws java.io.IOException;
     method public abstract java.nio.file.FileVisitResult preVisitDirectory(T, java.nio.file.attribute.BasicFileAttributes) throws java.io.IOException;
     method public abstract java.nio.file.FileVisitResult visitFile(T, java.nio.file.attribute.BasicFileAttributes) throws java.io.IOException;
@@ -54489,7 +54483,7 @@
     method public static boolean exists(java.nio.file.Path, java.nio.file.LinkOption...);
     method public static java.util.stream.Stream<java.nio.file.Path> find(java.nio.file.Path, int, java.util.function.BiPredicate<java.nio.file.Path, java.nio.file.attribute.BasicFileAttributes>, java.nio.file.FileVisitOption...) throws java.io.IOException;
     method public static java.lang.Object getAttribute(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
+    method public static <V extends java.nio.file.attribute.FileAttributeView> V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
     method public static java.nio.file.FileStore getFileStore(java.nio.file.Path) throws java.io.IOException;
     method public static java.nio.file.attribute.FileTime getLastModifiedTime(java.nio.file.Path, java.nio.file.LinkOption...) throws java.io.IOException;
     method public static java.nio.file.attribute.UserPrincipal getOwner(java.nio.file.Path, java.nio.file.LinkOption...) throws java.io.IOException;
@@ -54522,7 +54516,7 @@
     method public static byte[] readAllBytes(java.nio.file.Path) throws java.io.IOException;
     method public static java.util.List<java.lang.String> readAllLines(java.nio.file.Path, java.nio.charset.Charset) throws java.io.IOException;
     method public static java.util.List<java.lang.String> readAllLines(java.nio.file.Path) throws java.io.IOException;
-    method public static A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
+    method public static <A extends java.nio.file.attribute.BasicFileAttributes> A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
     method public static java.util.Map<java.lang.String, java.lang.Object> readAttributes(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
     method public static java.nio.file.Path readSymbolicLink(java.nio.file.Path) throws java.io.IOException;
     method public static java.nio.file.Path setAttribute(java.nio.file.Path, java.lang.String, java.lang.Object, java.nio.file.LinkOption...) throws java.io.IOException;
@@ -54630,17 +54624,17 @@
     ctor public ReadOnlyFileSystemException();
   }
 
-  public abstract interface SecureDirectoryStream implements java.nio.file.DirectoryStream {
+  public abstract interface SecureDirectoryStream<T> implements java.nio.file.DirectoryStream {
     method public abstract void deleteDirectory(T) throws java.io.IOException;
     method public abstract void deleteFile(T) throws java.io.IOException;
-    method public abstract V getFileAttributeView(java.lang.Class<V>);
-    method public abstract V getFileAttributeView(T, java.lang.Class<V>, java.nio.file.LinkOption...);
+    method public abstract <V extends java.nio.file.attribute.FileAttributeView> V getFileAttributeView(java.lang.Class<V>);
+    method public abstract <V extends java.nio.file.attribute.FileAttributeView> V getFileAttributeView(T, java.lang.Class<V>, java.nio.file.LinkOption...);
     method public abstract void move(T, java.nio.file.SecureDirectoryStream<T>, T) throws java.io.IOException;
     method public abstract java.nio.channels.SeekableByteChannel newByteChannel(T, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
     method public abstract java.nio.file.SecureDirectoryStream<T> newDirectoryStream(T, java.nio.file.LinkOption...) throws java.io.IOException;
   }
 
-  public class SimpleFileVisitor implements java.nio.file.FileVisitor {
+  public class SimpleFileVisitor<T> implements java.nio.file.FileVisitor {
     ctor protected SimpleFileVisitor();
     method public java.nio.file.FileVisitResult postVisitDirectory(T, java.io.IOException) throws java.io.IOException;
     method public java.nio.file.FileVisitResult preVisitDirectory(T, java.nio.file.attribute.BasicFileAttributes) throws java.io.IOException;
@@ -54678,13 +54672,13 @@
     field public static final java.nio.file.WatchEvent.Kind<java.lang.Object> OVERFLOW;
   }
 
-  public abstract interface WatchEvent {
+  public abstract interface WatchEvent<T> {
     method public abstract T context();
     method public abstract int count();
     method public abstract java.nio.file.WatchEvent.Kind<T> kind();
   }
 
-  public static abstract interface WatchEvent.Kind {
+  public static abstract interface WatchEvent.Kind<T> {
     method public abstract java.lang.String name();
     method public abstract java.lang.Class<T> type();
   }
@@ -54820,7 +54814,7 @@
     method public abstract boolean isSystem();
   }
 
-  public abstract interface FileAttribute {
+  public abstract interface FileAttribute<T> {
     method public abstract java.lang.String name();
     method public abstract T value();
   }
@@ -54917,7 +54911,7 @@
     method public void createSymbolicLink(java.nio.file.Path, java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
     method public abstract void delete(java.nio.file.Path) throws java.io.IOException;
     method public boolean deleteIfExists(java.nio.file.Path) throws java.io.IOException;
-    method public abstract V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
+    method public abstract <V extends java.nio.file.attribute.FileAttributeView> V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
     method public abstract java.nio.file.FileStore getFileStore(java.nio.file.Path) throws java.io.IOException;
     method public abstract java.nio.file.FileSystem getFileSystem(java.net.URI);
     method public abstract java.nio.file.Path getPath(java.net.URI);
@@ -54934,7 +54928,7 @@
     method public java.nio.file.FileSystem newFileSystem(java.nio.file.Path, java.util.Map<java.lang.String, ?>) throws java.io.IOException;
     method public java.io.InputStream newInputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
     method public java.io.OutputStream newOutputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public abstract A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
+    method public abstract <A extends java.nio.file.attribute.BasicFileAttributes> A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
     method public abstract java.util.Map<java.lang.String, java.lang.Object> readAttributes(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
     method public java.nio.file.Path readSymbolicLink(java.nio.file.Path) throws java.io.IOException;
     method public abstract void setAttribute(java.nio.file.Path, java.lang.String, java.lang.Object, java.nio.file.LinkOption...) throws java.io.IOException;
@@ -54964,12 +54958,12 @@
 
   public final class AccessController {
     method public static void checkPermission(java.security.Permission) throws java.security.AccessControlException;
-    method public static T doPrivileged(java.security.PrivilegedAction<T>);
-    method public static T doPrivileged(java.security.PrivilegedAction<T>, java.security.AccessControlContext);
-    method public static T doPrivileged(java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
-    method public static T doPrivileged(java.security.PrivilegedExceptionAction<T>, java.security.AccessControlContext) throws java.security.PrivilegedActionException;
-    method public static T doPrivilegedWithCombiner(java.security.PrivilegedAction<T>);
-    method public static T doPrivilegedWithCombiner(java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
+    method public static <T> T doPrivileged(java.security.PrivilegedAction<T>);
+    method public static <T> T doPrivileged(java.security.PrivilegedAction<T>, java.security.AccessControlContext);
+    method public static <T> T doPrivileged(java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
+    method public static <T> T doPrivileged(java.security.PrivilegedExceptionAction<T>, java.security.AccessControlContext) throws java.security.PrivilegedActionException;
+    method public static <T> T doPrivilegedWithCombiner(java.security.PrivilegedAction<T>);
+    method public static <T> T doPrivilegedWithCombiner(java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
     method public static java.security.AccessControlContext getContext();
   }
 
@@ -55008,7 +55002,7 @@
     method public static java.security.AlgorithmParameters getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
     method public static java.security.AlgorithmParameters getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
     method public static java.security.AlgorithmParameters getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
-    method public final T getParameterSpec(java.lang.Class<T>) throws java.security.spec.InvalidParameterSpecException;
+    method public final <T extends java.security.spec.AlgorithmParameterSpec> T getParameterSpec(java.lang.Class<T>) throws java.security.spec.InvalidParameterSpecException;
     method public final java.security.Provider getProvider();
     method public final void init(java.security.spec.AlgorithmParameterSpec) throws java.security.spec.InvalidParameterSpecException;
     method public final void init(byte[]) throws java.io.IOException;
@@ -55020,7 +55014,7 @@
     ctor public AlgorithmParametersSpi();
     method protected abstract byte[] engineGetEncoded() throws java.io.IOException;
     method protected abstract byte[] engineGetEncoded(java.lang.String) throws java.io.IOException;
-    method protected abstract T engineGetParameterSpec(java.lang.Class<T>) throws java.security.spec.InvalidParameterSpecException;
+    method protected abstract <T extends java.security.spec.AlgorithmParameterSpec> T engineGetParameterSpec(java.lang.Class<T>) throws java.security.spec.InvalidParameterSpecException;
     method protected abstract void engineInit(java.security.spec.AlgorithmParameterSpec) throws java.security.spec.InvalidParameterSpecException;
     method protected abstract void engineInit(byte[]) throws java.io.IOException;
     method protected abstract void engineInit(byte[], java.lang.String) throws java.io.IOException;
@@ -55212,7 +55206,7 @@
     method public static java.security.KeyFactory getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
     method public static java.security.KeyFactory getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
     method public static java.security.KeyFactory getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
-    method public final T getKeySpec(java.security.Key, java.lang.Class<T>) throws java.security.spec.InvalidKeySpecException;
+    method public final <T extends java.security.spec.KeySpec> T getKeySpec(java.security.Key, java.lang.Class<T>) throws java.security.spec.InvalidKeySpecException;
     method public final java.security.Provider getProvider();
     method public final java.security.Key translateKey(java.security.Key) throws java.security.InvalidKeyException;
   }
@@ -55221,7 +55215,7 @@
     ctor public KeyFactorySpi();
     method protected abstract java.security.PrivateKey engineGeneratePrivate(java.security.spec.KeySpec) throws java.security.spec.InvalidKeySpecException;
     method protected abstract java.security.PublicKey engineGeneratePublic(java.security.spec.KeySpec) throws java.security.spec.InvalidKeySpecException;
-    method protected abstract T engineGetKeySpec(java.security.Key, java.lang.Class<T>) throws java.security.spec.InvalidKeySpecException;
+    method protected abstract <T extends java.security.spec.KeySpec> T engineGetKeySpec(java.security.Key, java.lang.Class<T>) throws java.security.spec.InvalidKeySpecException;
     method protected abstract java.security.Key engineTranslateKey(java.security.Key) throws java.security.InvalidKeyException;
   }
 
@@ -55509,7 +55503,7 @@
     field public static final long serialVersionUID = 6034044314589513430L; // 0x53bd3b559a12c6d6L
   }
 
-  public abstract interface PrivilegedAction {
+  public abstract interface PrivilegedAction<T> {
     method public abstract T run();
   }
 
@@ -55518,7 +55512,7 @@
     method public java.lang.Exception getException();
   }
 
-  public abstract interface PrivilegedExceptionAction {
+  public abstract interface PrivilegedExceptionAction<T> {
     method public abstract T run() throws java.lang.Exception;
   }
 
@@ -57712,11 +57706,11 @@
     method public abstract void free() throws java.sql.SQLException;
     method public abstract java.io.InputStream getBinaryStream() throws java.sql.SQLException;
     method public abstract java.io.Reader getCharacterStream() throws java.sql.SQLException;
-    method public abstract T getSource(java.lang.Class<T>) throws java.sql.SQLException;
+    method public abstract <T extends javax.xml.transform.Source> T getSource(java.lang.Class<T>) throws java.sql.SQLException;
     method public abstract java.lang.String getString() throws java.sql.SQLException;
     method public abstract java.io.OutputStream setBinaryStream() throws java.sql.SQLException;
     method public abstract java.io.Writer setCharacterStream() throws java.sql.SQLException;
-    method public abstract T setResult(java.lang.Class<T>) throws java.sql.SQLException;
+    method public abstract <T extends javax.xml.transform.Result> T setResult(java.lang.Class<T>) throws java.sql.SQLException;
     method public abstract void setString(java.lang.String) throws java.sql.SQLException;
   }
 
@@ -57840,7 +57834,7 @@
 
   public abstract interface Wrapper {
     method public abstract boolean isWrapperFor(java.lang.Class<?>) throws java.sql.SQLException;
-    method public abstract T unwrap(java.lang.Class<T>) throws java.sql.SQLException;
+    method public abstract <T> T unwrap(java.lang.Class<T>) throws java.sql.SQLException;
   }
 
 }
@@ -58373,7 +58367,7 @@
 
 package java.util {
 
-  public abstract class AbstractCollection implements java.util.Collection {
+  public abstract class AbstractCollection<E> implements java.util.Collection {
     ctor protected AbstractCollection();
     method public boolean add(E);
     method public boolean addAll(java.util.Collection<? extends E>);
@@ -58387,10 +58381,10 @@
     method public boolean retainAll(java.util.Collection<?>);
     method public abstract int size();
     method public java.lang.Object[] toArray();
-    method public T[] toArray(T[]);
+    method public <T> T[] toArray(T[]);
   }
 
-  public abstract class AbstractList extends java.util.AbstractCollection implements java.util.List {
+  public abstract class AbstractList<E> extends java.util.AbstractCollection implements java.util.List {
     ctor protected AbstractList();
     method public void add(int, E);
     method public boolean addAll(int, java.util.Collection<? extends E>);
@@ -58407,7 +58401,7 @@
     field protected transient int modCount;
   }
 
-  public abstract class AbstractMap implements java.util.Map {
+  public abstract class AbstractMap<K, V> implements java.util.Map {
     ctor protected AbstractMap();
     method public void clear();
     method public boolean containsKey(java.lang.Object);
@@ -58423,7 +58417,7 @@
     method public java.util.Collection<V> values();
   }
 
-  public static class AbstractMap.SimpleEntry implements java.util.Map.Entry java.io.Serializable {
+  public static class AbstractMap.SimpleEntry<K, V> implements java.util.Map.Entry java.io.Serializable {
     ctor public AbstractMap.SimpleEntry(K, V);
     ctor public AbstractMap.SimpleEntry(java.util.Map.Entry<? extends K, ? extends V>);
     method public K getKey();
@@ -58431,7 +58425,7 @@
     method public V setValue(V);
   }
 
-  public static class AbstractMap.SimpleImmutableEntry implements java.util.Map.Entry java.io.Serializable {
+  public static class AbstractMap.SimpleImmutableEntry<K, V> implements java.util.Map.Entry java.io.Serializable {
     ctor public AbstractMap.SimpleImmutableEntry(K, V);
     ctor public AbstractMap.SimpleImmutableEntry(java.util.Map.Entry<? extends K, ? extends V>);
     method public K getKey();
@@ -58439,23 +58433,23 @@
     method public V setValue(V);
   }
 
-  public abstract class AbstractQueue extends java.util.AbstractCollection implements java.util.Queue {
+  public abstract class AbstractQueue<E> extends java.util.AbstractCollection implements java.util.Queue {
     ctor protected AbstractQueue();
     method public E element();
     method public E remove();
   }
 
-  public abstract class AbstractSequentialList extends java.util.AbstractList {
+  public abstract class AbstractSequentialList<E> extends java.util.AbstractList {
     ctor protected AbstractSequentialList();
     method public E get(int);
     method public abstract java.util.ListIterator<E> listIterator(int);
   }
 
-  public abstract class AbstractSet extends java.util.AbstractCollection implements java.util.Set {
+  public abstract class AbstractSet<E> extends java.util.AbstractCollection implements java.util.Set {
     ctor protected AbstractSet();
   }
 
-  public class ArrayDeque extends java.util.AbstractCollection implements java.lang.Cloneable java.util.Deque java.io.Serializable {
+  public class ArrayDeque<E> extends java.util.AbstractCollection implements java.lang.Cloneable java.util.Deque java.io.Serializable {
     ctor public ArrayDeque();
     ctor public ArrayDeque(int);
     ctor public ArrayDeque(java.util.Collection<? extends E>);
@@ -58487,7 +58481,7 @@
     method public java.util.Spliterator<E> spliterator();
   }
 
-  public class ArrayList extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
+  public class ArrayList<E> extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
     ctor public ArrayList(int);
     ctor public ArrayList();
     ctor public ArrayList(java.util.Collection<? extends E>);
@@ -58504,7 +58498,7 @@
   }
 
   public class Arrays {
-    method public static java.util.List<T> asList(T...);
+    method public static <T> java.util.List<T> asList(T...);
     method public static int binarySearch(long[], long);
     method public static int binarySearch(long[], int, int, long);
     method public static int binarySearch(int[], int);
@@ -58521,10 +58515,10 @@
     method public static int binarySearch(float[], int, int, float);
     method public static int binarySearch(java.lang.Object[], java.lang.Object);
     method public static int binarySearch(java.lang.Object[], int, int, java.lang.Object);
-    method public static int binarySearch(T[], T, java.util.Comparator<? super T>);
-    method public static int binarySearch(T[], int, int, T, java.util.Comparator<? super T>);
-    method public static T[] copyOf(T[], int);
-    method public static T[] copyOf(U[], int, java.lang.Class<? extends T[]>);
+    method public static <T> int binarySearch(T[], T, java.util.Comparator<? super T>);
+    method public static <T> int binarySearch(T[], int, int, T, java.util.Comparator<? super T>);
+    method public static <T> T[] copyOf(T[], int);
+    method public static <T, U> T[] copyOf(U[], int, java.lang.Class<? extends T[]>);
     method public static byte[] copyOf(byte[], int);
     method public static short[] copyOf(short[], int);
     method public static int[] copyOf(int[], int);
@@ -58533,8 +58527,8 @@
     method public static float[] copyOf(float[], int);
     method public static double[] copyOf(double[], int);
     method public static boolean[] copyOf(boolean[], int);
-    method public static T[] copyOfRange(T[], int, int);
-    method public static T[] copyOfRange(U[], int, int, java.lang.Class<? extends T[]>);
+    method public static <T> T[] copyOfRange(T[], int, int);
+    method public static <T, U> T[] copyOfRange(U[], int, int, java.lang.Class<? extends T[]>);
     method public static byte[] copyOfRange(byte[], int, int);
     method public static short[] copyOfRange(short[], int, int);
     method public static int[] copyOfRange(int[], int, int);
@@ -58582,15 +58576,15 @@
     method public static int hashCode(float[]);
     method public static int hashCode(double[]);
     method public static int hashCode(java.lang.Object[]);
-    method public static void parallelPrefix(T[], java.util.function.BinaryOperator<T>);
-    method public static void parallelPrefix(T[], int, int, java.util.function.BinaryOperator<T>);
+    method public static <T> void parallelPrefix(T[], java.util.function.BinaryOperator<T>);
+    method public static <T> void parallelPrefix(T[], int, int, java.util.function.BinaryOperator<T>);
     method public static void parallelPrefix(long[], java.util.function.LongBinaryOperator);
     method public static void parallelPrefix(long[], int, int, java.util.function.LongBinaryOperator);
     method public static void parallelPrefix(double[], java.util.function.DoubleBinaryOperator);
     method public static void parallelPrefix(double[], int, int, java.util.function.DoubleBinaryOperator);
     method public static void parallelPrefix(int[], java.util.function.IntBinaryOperator);
     method public static void parallelPrefix(int[], int, int, java.util.function.IntBinaryOperator);
-    method public static void parallelSetAll(T[], java.util.function.IntFunction<? extends T>);
+    method public static <T> void parallelSetAll(T[], java.util.function.IntFunction<? extends T>);
     method public static void parallelSetAll(int[], java.util.function.IntUnaryOperator);
     method public static void parallelSetAll(long[], java.util.function.IntToLongFunction);
     method public static void parallelSetAll(double[], java.util.function.IntToDoubleFunction);
@@ -58608,11 +58602,11 @@
     method public static void parallelSort(float[], int, int);
     method public static void parallelSort(double[]);
     method public static void parallelSort(double[], int, int);
-    method public static void parallelSort(T[]);
-    method public static void parallelSort(T[], int, int);
-    method public static void parallelSort(T[], java.util.Comparator<? super T>);
-    method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>);
-    method public static void setAll(T[], java.util.function.IntFunction<? extends T>);
+    method public static <T extends java.lang.Comparable<? super T>> void parallelSort(T[]);
+    method public static <T extends java.lang.Comparable<? super T>> void parallelSort(T[], int, int);
+    method public static <T> void parallelSort(T[], java.util.Comparator<? super T>);
+    method public static <T> void parallelSort(T[], int, int, java.util.Comparator<? super T>);
+    method public static <T> void setAll(T[], java.util.function.IntFunction<? extends T>);
     method public static void setAll(int[], java.util.function.IntUnaryOperator);
     method public static void setAll(long[], java.util.function.IntToLongFunction);
     method public static void setAll(double[], java.util.function.IntToDoubleFunction);
@@ -58632,18 +58626,18 @@
     method public static void sort(double[], int, int);
     method public static void sort(java.lang.Object[]);
     method public static void sort(java.lang.Object[], int, int);
-    method public static void sort(T[], java.util.Comparator<? super T>);
-    method public static void sort(T[], int, int, java.util.Comparator<? super T>);
-    method public static java.util.Spliterator<T> spliterator(T[]);
-    method public static java.util.Spliterator<T> spliterator(T[], int, int);
+    method public static <T> void sort(T[], java.util.Comparator<? super T>);
+    method public static <T> void sort(T[], int, int, java.util.Comparator<? super T>);
+    method public static <T> java.util.Spliterator<T> spliterator(T[]);
+    method public static <T> java.util.Spliterator<T> spliterator(T[], int, int);
     method public static java.util.Spliterator.OfInt spliterator(int[]);
     method public static java.util.Spliterator.OfInt spliterator(int[], int, int);
     method public static java.util.Spliterator.OfLong spliterator(long[]);
     method public static java.util.Spliterator.OfLong spliterator(long[], int, int);
     method public static java.util.Spliterator.OfDouble spliterator(double[]);
     method public static java.util.Spliterator.OfDouble spliterator(double[], int, int);
-    method public static java.util.stream.Stream<T> stream(T[]);
-    method public static java.util.stream.Stream<T> stream(T[], int, int);
+    method public static <T> java.util.stream.Stream<T> stream(T[]);
+    method public static <T> java.util.stream.Stream<T> stream(T[], int, int);
     method public static java.util.stream.IntStream stream(int[]);
     method public static java.util.stream.IntStream stream(int[], int, int);
     method public static java.util.stream.LongStream stream(long[]);
@@ -58827,7 +58821,7 @@
     field protected long time;
   }
 
-  public abstract interface Collection implements java.lang.Iterable {
+  public abstract interface Collection<E> implements java.lang.Iterable {
     method public abstract boolean add(E);
     method public abstract boolean addAll(java.util.Collection<? extends E>);
     method public abstract void clear();
@@ -58845,86 +58839,86 @@
     method public abstract int size();
     method public default java.util.stream.Stream<E> stream();
     method public abstract java.lang.Object[] toArray();
-    method public abstract T[] toArray(T[]);
+    method public abstract <T> T[] toArray(T[]);
   }
 
   public class Collections {
-    method public static boolean addAll(java.util.Collection<? super T>, T...);
-    method public static java.util.Queue<T> asLifoQueue(java.util.Deque<T>);
-    method public static int binarySearch(java.util.List<? extends java.lang.Comparable<? super T>>, T);
-    method public static int binarySearch(java.util.List<? extends T>, T, java.util.Comparator<? super T>);
-    method public static java.util.Collection<E> checkedCollection(java.util.Collection<E>, java.lang.Class<E>);
-    method public static java.util.List<E> checkedList(java.util.List<E>, java.lang.Class<E>);
-    method public static java.util.Map<K, V> checkedMap(java.util.Map<K, V>, java.lang.Class<K>, java.lang.Class<V>);
-    method public static java.util.Set<E> checkedSet(java.util.Set<E>, java.lang.Class<E>);
-    method public static java.util.SortedMap<K, V> checkedSortedMap(java.util.SortedMap<K, V>, java.lang.Class<K>, java.lang.Class<V>);
-    method public static java.util.SortedSet<E> checkedSortedSet(java.util.SortedSet<E>, java.lang.Class<E>);
-    method public static void copy(java.util.List<? super T>, java.util.List<? extends T>);
+    method public static <T> boolean addAll(java.util.Collection<? super T>, T...);
+    method public static <T> java.util.Queue<T> asLifoQueue(java.util.Deque<T>);
+    method public static <T> int binarySearch(java.util.List<? extends java.lang.Comparable<? super T>>, T);
+    method public static <T> int binarySearch(java.util.List<? extends T>, T, java.util.Comparator<? super T>);
+    method public static <E> java.util.Collection<E> checkedCollection(java.util.Collection<E>, java.lang.Class<E>);
+    method public static <E> java.util.List<E> checkedList(java.util.List<E>, java.lang.Class<E>);
+    method public static <K, V> java.util.Map<K, V> checkedMap(java.util.Map<K, V>, java.lang.Class<K>, java.lang.Class<V>);
+    method public static <E> java.util.Set<E> checkedSet(java.util.Set<E>, java.lang.Class<E>);
+    method public static <K, V> java.util.SortedMap<K, V> checkedSortedMap(java.util.SortedMap<K, V>, java.lang.Class<K>, java.lang.Class<V>);
+    method public static <E> java.util.SortedSet<E> checkedSortedSet(java.util.SortedSet<E>, java.lang.Class<E>);
+    method public static <T> void copy(java.util.List<? super T>, java.util.List<? extends T>);
     method public static boolean disjoint(java.util.Collection<?>, java.util.Collection<?>);
-    method public static java.util.Enumeration<T> emptyEnumeration();
-    method public static java.util.Iterator<T> emptyIterator();
-    method public static final java.util.List<T> emptyList();
-    method public static java.util.ListIterator<T> emptyListIterator();
-    method public static final java.util.Map<K, V> emptyMap();
-    method public static final java.util.Set<T> emptySet();
-    method public static java.util.Enumeration<T> enumeration(java.util.Collection<T>);
-    method public static void fill(java.util.List<? super T>, T);
+    method public static <T> java.util.Enumeration<T> emptyEnumeration();
+    method public static <T> java.util.Iterator<T> emptyIterator();
+    method public static final <T> java.util.List<T> emptyList();
+    method public static <T> java.util.ListIterator<T> emptyListIterator();
+    method public static final <K, V> java.util.Map<K, V> emptyMap();
+    method public static final <T> java.util.Set<T> emptySet();
+    method public static <T> java.util.Enumeration<T> enumeration(java.util.Collection<T>);
+    method public static <T> void fill(java.util.List<? super T>, T);
     method public static int frequency(java.util.Collection<?>, java.lang.Object);
     method public static int indexOfSubList(java.util.List<?>, java.util.List<?>);
     method public static int lastIndexOfSubList(java.util.List<?>, java.util.List<?>);
-    method public static java.util.ArrayList<T> list(java.util.Enumeration<T>);
-    method public static T max(java.util.Collection<? extends T>);
-    method public static T max(java.util.Collection<? extends T>, java.util.Comparator<? super T>);
-    method public static T min(java.util.Collection<? extends T>);
-    method public static T min(java.util.Collection<? extends T>, java.util.Comparator<? super T>);
-    method public static java.util.List<T> nCopies(int, T);
-    method public static java.util.Set<E> newSetFromMap(java.util.Map<E, java.lang.Boolean>);
-    method public static boolean replaceAll(java.util.List<T>, T, T);
+    method public static <T> java.util.ArrayList<T> list(java.util.Enumeration<T>);
+    method public static <T extends java.lang.Object & java.lang.Comparable<? super T>> T max(java.util.Collection<? extends T>);
+    method public static <T> T max(java.util.Collection<? extends T>, java.util.Comparator<? super T>);
+    method public static <T extends java.lang.Object & java.lang.Comparable<? super T>> T min(java.util.Collection<? extends T>);
+    method public static <T> T min(java.util.Collection<? extends T>, java.util.Comparator<? super T>);
+    method public static <T> java.util.List<T> nCopies(int, T);
+    method public static <E> java.util.Set<E> newSetFromMap(java.util.Map<E, java.lang.Boolean>);
+    method public static <T> boolean replaceAll(java.util.List<T>, T, T);
     method public static void reverse(java.util.List<?>);
-    method public static java.util.Comparator<T> reverseOrder();
-    method public static java.util.Comparator<T> reverseOrder(java.util.Comparator<T>);
+    method public static <T> java.util.Comparator<T> reverseOrder();
+    method public static <T> java.util.Comparator<T> reverseOrder(java.util.Comparator<T>);
     method public static void rotate(java.util.List<?>, int);
     method public static void shuffle(java.util.List<?>);
     method public static void shuffle(java.util.List<?>, java.util.Random);
-    method public static java.util.Set<E> singleton(E);
-    method public static java.util.List<E> singletonList(E);
-    method public static java.util.Map<K, V> singletonMap(K, V);
-    method public static void sort(java.util.List<T>);
-    method public static void sort(java.util.List<T>, java.util.Comparator<? super T>);
+    method public static <E> java.util.Set<E> singleton(E);
+    method public static <E> java.util.List<E> singletonList(E);
+    method public static <K, V> java.util.Map<K, V> singletonMap(K, V);
+    method public static <T extends java.lang.Comparable<? super T>> void sort(java.util.List<T>);
+    method public static <T> void sort(java.util.List<T>, java.util.Comparator<? super T>);
     method public static void swap(java.util.List<?>, int, int);
-    method public static java.util.Collection<T> synchronizedCollection(java.util.Collection<T>);
-    method public static java.util.List<T> synchronizedList(java.util.List<T>);
-    method public static java.util.Map<K, V> synchronizedMap(java.util.Map<K, V>);
-    method public static java.util.Set<T> synchronizedSet(java.util.Set<T>);
-    method public static java.util.SortedMap<K, V> synchronizedSortedMap(java.util.SortedMap<K, V>);
-    method public static java.util.SortedSet<T> synchronizedSortedSet(java.util.SortedSet<T>);
-    method public static java.util.Collection<T> unmodifiableCollection(java.util.Collection<? extends T>);
-    method public static java.util.List<T> unmodifiableList(java.util.List<? extends T>);
-    method public static java.util.Map<K, V> unmodifiableMap(java.util.Map<? extends K, ? extends V>);
-    method public static java.util.Set<T> unmodifiableSet(java.util.Set<? extends T>);
-    method public static java.util.SortedMap<K, V> unmodifiableSortedMap(java.util.SortedMap<K, ? extends V>);
-    method public static java.util.SortedSet<T> unmodifiableSortedSet(java.util.SortedSet<T>);
+    method public static <T> java.util.Collection<T> synchronizedCollection(java.util.Collection<T>);
+    method public static <T> java.util.List<T> synchronizedList(java.util.List<T>);
+    method public static <K, V> java.util.Map<K, V> synchronizedMap(java.util.Map<K, V>);
+    method public static <T> java.util.Set<T> synchronizedSet(java.util.Set<T>);
+    method public static <K, V> java.util.SortedMap<K, V> synchronizedSortedMap(java.util.SortedMap<K, V>);
+    method public static <T> java.util.SortedSet<T> synchronizedSortedSet(java.util.SortedSet<T>);
+    method public static <T> java.util.Collection<T> unmodifiableCollection(java.util.Collection<? extends T>);
+    method public static <T> java.util.List<T> unmodifiableList(java.util.List<? extends T>);
+    method public static <K, V> java.util.Map<K, V> unmodifiableMap(java.util.Map<? extends K, ? extends V>);
+    method public static <T> java.util.Set<T> unmodifiableSet(java.util.Set<? extends T>);
+    method public static <K, V> java.util.SortedMap<K, V> unmodifiableSortedMap(java.util.SortedMap<K, ? extends V>);
+    method public static <T> java.util.SortedSet<T> unmodifiableSortedSet(java.util.SortedSet<T>);
     field public static final java.util.List EMPTY_LIST;
     field public static final java.util.Map EMPTY_MAP;
     field public static final java.util.Set EMPTY_SET;
   }
 
-  public abstract interface Comparator {
+  public abstract interface Comparator<T> {
     method public abstract int compare(T, T);
-    method public static java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
-    method public static java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>);
-    method public static java.util.Comparator<T> comparingDouble(java.util.function.ToDoubleFunction<? super T>);
-    method public static java.util.Comparator<T> comparingInt(java.util.function.ToIntFunction<? super T>);
-    method public static java.util.Comparator<T> comparingLong(java.util.function.ToLongFunction<? super T>);
+    method public static <T, U> java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
+    method public static <T, U extends java.lang.Comparable<? super U>> java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>);
+    method public static <T> java.util.Comparator<T> comparingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static <T> java.util.Comparator<T> comparingInt(java.util.function.ToIntFunction<? super T>);
+    method public static <T> java.util.Comparator<T> comparingLong(java.util.function.ToLongFunction<? super T>);
     method public abstract boolean equals(java.lang.Object);
-    method public static java.util.Comparator<T> naturalOrder();
-    method public static java.util.Comparator<T> nullsFirst(java.util.Comparator<? super T>);
-    method public static java.util.Comparator<T> nullsLast(java.util.Comparator<? super T>);
-    method public static java.util.Comparator<T> reverseOrder();
+    method public static <T extends java.lang.Comparable<? super T>> java.util.Comparator<T> naturalOrder();
+    method public static <T> java.util.Comparator<T> nullsFirst(java.util.Comparator<? super T>);
+    method public static <T> java.util.Comparator<T> nullsLast(java.util.Comparator<? super T>);
+    method public static <T extends java.lang.Comparable<? super T>> java.util.Comparator<T> reverseOrder();
     method public default java.util.Comparator<T> reversed();
     method public default java.util.Comparator<T> thenComparing(java.util.Comparator<? super T>);
-    method public default java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
-    method public default java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>);
+    method public default <U> java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
+    method public default <U extends java.lang.Comparable<? super U>> java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>);
     method public default java.util.Comparator<T> thenComparingDouble(java.util.function.ToDoubleFunction<? super T>);
     method public default java.util.Comparator<T> thenComparingInt(java.util.function.ToIntFunction<? super T>);
     method public default java.util.Comparator<T> thenComparingLong(java.util.function.ToLongFunction<? super T>);
@@ -58983,7 +58977,7 @@
     method public deprecated java.lang.String toLocaleString();
   }
 
-  public abstract interface Deque implements java.util.Queue {
+  public abstract interface Deque<E> implements java.util.Queue {
     method public abstract boolean add(E);
     method public abstract void addFirst(E);
     method public abstract void addLast(E);
@@ -59013,7 +59007,7 @@
     method public abstract int size();
   }
 
-  public abstract class Dictionary {
+  public abstract class Dictionary<K, V> {
     ctor public Dictionary();
     method public abstract java.util.Enumeration<V> elements();
     method public abstract V get(java.lang.Object);
@@ -59044,7 +59038,7 @@
     ctor public EmptyStackException();
   }
 
-  public class EnumMap extends java.util.AbstractMap implements java.lang.Cloneable java.io.Serializable {
+  public class EnumMap<K extends java.lang.Enum<K>, V> extends java.util.AbstractMap implements java.lang.Cloneable java.io.Serializable {
     ctor public EnumMap(java.lang.Class<K>);
     ctor public EnumMap(java.util.EnumMap<K, ? extends V>);
     ctor public EnumMap(java.util.Map<K, ? extends V>);
@@ -59052,23 +59046,23 @@
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
   }
 
-  public abstract class EnumSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable {
-    method public static java.util.EnumSet<E> allOf(java.lang.Class<E>);
+  public abstract class EnumSet<E extends java.lang.Enum<E>> extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable {
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> allOf(java.lang.Class<E>);
     method public java.util.EnumSet<E> clone();
-    method public static java.util.EnumSet<E> complementOf(java.util.EnumSet<E>);
-    method public static java.util.EnumSet<E> copyOf(java.util.EnumSet<E>);
-    method public static java.util.EnumSet<E> copyOf(java.util.Collection<E>);
-    method public static java.util.EnumSet<E> noneOf(java.lang.Class<E>);
-    method public static java.util.EnumSet<E> of(E);
-    method public static java.util.EnumSet<E> of(E, E);
-    method public static java.util.EnumSet<E> of(E, E, E);
-    method public static java.util.EnumSet<E> of(E, E, E, E);
-    method public static java.util.EnumSet<E> of(E, E, E, E, E);
-    method public static java.util.EnumSet<E> of(E, E...);
-    method public static java.util.EnumSet<E> range(E, E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> complementOf(java.util.EnumSet<E>);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> copyOf(java.util.EnumSet<E>);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> copyOf(java.util.Collection<E>);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> noneOf(java.lang.Class<E>);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E, E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E, E, E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E, E, E, E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E, E, E, E, E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E, E...);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> range(E, E);
   }
 
-  public abstract interface Enumeration {
+  public abstract interface Enumeration<E> {
     method public abstract boolean hasMoreElements();
     method public abstract E nextElement();
   }
@@ -59076,7 +59070,7 @@
   public abstract interface EventListener {
   }
 
-  public abstract class EventListenerProxy implements java.util.EventListener {
+  public abstract class EventListenerProxy<T extends java.util.EventListener> implements java.util.EventListener {
     ctor public EventListenerProxy(T);
     method public T getListener();
   }
@@ -59162,7 +59156,7 @@
     field public static final int BC = 0; // 0x0
   }
 
-  public class HashMap extends java.util.AbstractMap implements java.lang.Cloneable java.util.Map java.io.Serializable {
+  public class HashMap<K, V> extends java.util.AbstractMap implements java.lang.Cloneable java.util.Map java.io.Serializable {
     ctor public HashMap(int, float);
     ctor public HashMap(int);
     ctor public HashMap();
@@ -59182,7 +59176,7 @@
     method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
   }
 
-  public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
+  public class HashSet<E> extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
     ctor public HashSet();
     ctor public HashSet(java.util.Collection<? extends E>);
     ctor public HashSet(int, float);
@@ -59193,7 +59187,7 @@
     method public java.util.Spliterator<E> spliterator();
   }
 
-  public class Hashtable extends java.util.Dictionary implements java.lang.Cloneable java.util.Map java.io.Serializable {
+  public class Hashtable<K, V> extends java.util.Dictionary implements java.lang.Cloneable java.util.Map java.io.Serializable {
     ctor public Hashtable(int, float);
     ctor public Hashtable(int);
     ctor public Hashtable();
@@ -59228,7 +59222,7 @@
     method public java.util.Collection<V> values();
   }
 
-  public class IdentityHashMap extends java.util.AbstractMap implements java.lang.Cloneable java.util.Map java.io.Serializable {
+  public class IdentityHashMap<K, V> extends java.util.AbstractMap implements java.lang.Cloneable java.util.Map java.io.Serializable {
     ctor public IdentityHashMap();
     ctor public IdentityHashMap(int);
     ctor public IdentityHashMap(java.util.Map<? extends K, ? extends V>);
@@ -59295,14 +59289,14 @@
     ctor public InvalidPropertiesFormatException(java.lang.String);
   }
 
-  public abstract interface Iterator {
+  public abstract interface Iterator<E> {
     method public default void forEachRemaining(java.util.function.Consumer<? super E>);
     method public abstract boolean hasNext();
     method public abstract E next();
     method public default void remove();
   }
 
-  public class LinkedHashMap extends java.util.HashMap implements java.util.Map {
+  public class LinkedHashMap<K, V> extends java.util.HashMap implements java.util.Map {
     ctor public LinkedHashMap(int, float);
     ctor public LinkedHashMap(int);
     ctor public LinkedHashMap();
@@ -59311,14 +59305,14 @@
     method protected boolean removeEldestEntry(java.util.Map.Entry<K, V>);
   }
 
-  public class LinkedHashSet extends java.util.HashSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
+  public class LinkedHashSet<E> extends java.util.HashSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
     ctor public LinkedHashSet(int, float);
     ctor public LinkedHashSet(int);
     ctor public LinkedHashSet();
     ctor public LinkedHashSet(java.util.Collection<? extends E>);
   }
 
-  public class LinkedList extends java.util.AbstractSequentialList implements java.lang.Cloneable java.util.Deque java.util.List java.io.Serializable {
+  public class LinkedList<E> extends java.util.AbstractSequentialList implements java.lang.Cloneable java.util.Deque java.util.List java.io.Serializable {
     ctor public LinkedList();
     ctor public LinkedList(java.util.Collection<? extends E>);
     method public void addFirst(E);
@@ -59349,7 +59343,7 @@
     method public java.util.Spliterator<E> spliterator();
   }
 
-  public abstract interface List implements java.util.Collection {
+  public abstract interface List<E> implements java.util.Collection {
     method public abstract boolean add(E);
     method public abstract void add(int, E);
     method public abstract boolean addAll(java.util.Collection<? extends E>);
@@ -59376,10 +59370,10 @@
     method public default void sort(java.util.Comparator<? super E>);
     method public abstract java.util.List<E> subList(int, int);
     method public abstract java.lang.Object[] toArray();
-    method public abstract T[] toArray(T[]);
+    method public abstract <T> T[] toArray(T[]);
   }
 
-  public abstract interface ListIterator implements java.util.Iterator {
+  public abstract interface ListIterator<E> implements java.util.Iterator {
     method public abstract void add(E);
     method public abstract boolean hasNext();
     method public abstract boolean hasPrevious();
@@ -59496,7 +59490,7 @@
     method public final long getSum();
   }
 
-  public abstract interface Map {
+  public abstract interface Map<K, V> {
     method public abstract void clear();
     method public default V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public default V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
@@ -59524,11 +59518,11 @@
     method public abstract java.util.Collection<V> values();
   }
 
-  public static abstract interface Map.Entry {
-    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey();
-    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>);
-    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue();
-    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(java.util.Comparator<? super V>);
+  public static abstract interface Map.Entry<K, V> {
+    method public static <K extends java.lang.Comparable<? super K>, V> java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey();
+    method public static <K, V> java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>);
+    method public static <K, V extends java.lang.Comparable<? super V>> java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue();
+    method public static <K, V> java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(java.util.Comparator<? super V>);
     method public abstract boolean equals(java.lang.Object);
     method public abstract K getKey();
     method public abstract V getValue();
@@ -59552,7 +59546,7 @@
     method public java.lang.String getKey();
   }
 
-  public abstract interface NavigableMap implements java.util.SortedMap {
+  public abstract interface NavigableMap<K, V> implements java.util.SortedMap {
     method public abstract java.util.Map.Entry<K, V> ceilingEntry(K);
     method public abstract K ceilingKey(K);
     method public abstract java.util.NavigableSet<K> descendingKeySet();
@@ -59576,7 +59570,7 @@
     method public abstract java.util.SortedMap<K, V> tailMap(K);
   }
 
-  public abstract interface NavigableSet implements java.util.SortedSet {
+  public abstract interface NavigableSet<E> implements java.util.SortedSet {
     method public abstract E ceiling(E);
     method public abstract java.util.Iterator<E> descendingIterator();
     method public abstract java.util.NavigableSet<E> descendingSet();
@@ -59600,16 +59594,16 @@
   }
 
   public final class Objects {
-    method public static int compare(T, T, java.util.Comparator<? super T>);
+    method public static <T> int compare(T, T, java.util.Comparator<? super T>);
     method public static boolean deepEquals(java.lang.Object, java.lang.Object);
     method public static boolean equals(java.lang.Object, java.lang.Object);
     method public static int hash(java.lang.Object...);
     method public static int hashCode(java.lang.Object);
     method public static boolean isNull(java.lang.Object);
     method public static boolean nonNull(java.lang.Object);
-    method public static T requireNonNull(T);
-    method public static T requireNonNull(T, java.lang.String);
-    method public static T requireNonNull(T, java.util.function.Supplier<java.lang.String>);
+    method public static <T> T requireNonNull(T);
+    method public static <T> T requireNonNull(T, java.lang.String);
+    method public static <T> T requireNonNull(T, java.util.function.Supplier<java.lang.String>);
     method public static java.lang.String toString(java.lang.Object);
     method public static java.lang.String toString(java.lang.Object, java.lang.String);
   }
@@ -59631,19 +59625,19 @@
     method public abstract void update(java.util.Observable, java.lang.Object);
   }
 
-  public final class Optional {
-    method public static java.util.Optional<T> empty();
+  public final class Optional<T> {
+    method public static <T> java.util.Optional<T> empty();
     method public java.util.Optional<T> filter(java.util.function.Predicate<? super T>);
-    method public java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
+    method public <U> java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
     method public T get();
     method public void ifPresent(java.util.function.Consumer<? super T>);
     method public boolean isPresent();
-    method public java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
-    method public static java.util.Optional<T> of(T);
-    method public static java.util.Optional<T> ofNullable(T);
+    method public <U> java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
+    method public static <T> java.util.Optional<T> of(T);
+    method public static <T> java.util.Optional<T> ofNullable(T);
     method public T orElse(T);
     method public T orElseGet(java.util.function.Supplier<? extends T>);
-    method public T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
+    method public <X extends java.lang.Throwable> T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
   }
 
   public final class OptionalDouble {
@@ -59654,7 +59648,7 @@
     method public static java.util.OptionalDouble of(double);
     method public double orElse(double);
     method public double orElseGet(java.util.function.DoubleSupplier);
-    method public double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+    method public <X extends java.lang.Throwable> double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
   }
 
   public final class OptionalInt {
@@ -59665,7 +59659,7 @@
     method public static java.util.OptionalInt of(int);
     method public int orElse(int);
     method public int orElseGet(java.util.function.IntSupplier);
-    method public int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+    method public <X extends java.lang.Throwable> int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
   }
 
   public final class OptionalLong {
@@ -59676,10 +59670,10 @@
     method public static java.util.OptionalLong of(long);
     method public long orElse(long);
     method public long orElseGet(java.util.function.LongSupplier);
-    method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+    method public <X extends java.lang.Throwable> long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
   }
 
-  public abstract interface PrimitiveIterator implements java.util.Iterator {
+  public abstract interface PrimitiveIterator<T, T_CONS> implements java.util.Iterator {
     method public abstract void forEachRemaining(T_CONS);
   }
 
@@ -59704,7 +59698,7 @@
     method public abstract long nextLong();
   }
 
-  public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
+  public class PriorityQueue<E> extends java.util.AbstractQueue implements java.io.Serializable {
     ctor public PriorityQueue();
     ctor public PriorityQueue(int);
     ctor public PriorityQueue(java.util.Comparator<? super E>);
@@ -59753,7 +59747,7 @@
     method public java.lang.Object handleGetObject(java.lang.String);
   }
 
-  public abstract interface Queue implements java.util.Collection {
+  public abstract interface Queue<E> implements java.util.Collection {
     method public abstract boolean add(E);
     method public abstract E element();
     method public abstract boolean offer(E);
@@ -59797,6 +59791,7 @@
     method public static final void clearCache();
     method public static final void clearCache(java.lang.ClassLoader);
     method public boolean containsKey(java.lang.String);
+    method public java.lang.String getBaseBundleName();
     method public static final java.util.ResourceBundle getBundle(java.lang.String);
     method public static final java.util.ResourceBundle getBundle(java.lang.String, java.util.ResourceBundle.Control);
     method public static final java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale);
@@ -59905,15 +59900,15 @@
     ctor public ServiceConfigurationError(java.lang.String, java.lang.Throwable);
   }
 
-  public final class ServiceLoader implements java.lang.Iterable {
+  public final class ServiceLoader<S> implements java.lang.Iterable {
     method public java.util.Iterator<S> iterator();
-    method public static java.util.ServiceLoader<S> load(java.lang.Class<S>, java.lang.ClassLoader);
-    method public static java.util.ServiceLoader<S> load(java.lang.Class<S>);
-    method public static java.util.ServiceLoader<S> loadInstalled(java.lang.Class<S>);
+    method public static <S> java.util.ServiceLoader<S> load(java.lang.Class<S>, java.lang.ClassLoader);
+    method public static <S> java.util.ServiceLoader<S> load(java.lang.Class<S>);
+    method public static <S> java.util.ServiceLoader<S> loadInstalled(java.lang.Class<S>);
     method public void reload();
   }
 
-  public abstract interface Set implements java.util.Collection {
+  public abstract interface Set<E> implements java.util.Collection {
     method public abstract boolean add(E);
     method public abstract boolean addAll(java.util.Collection<? extends E>);
     method public abstract void clear();
@@ -59928,7 +59923,7 @@
     method public abstract boolean retainAll(java.util.Collection<?>);
     method public abstract int size();
     method public abstract java.lang.Object[] toArray();
-    method public abstract T[] toArray(T[]);
+    method public abstract <T> T[] toArray(T[]);
   }
 
   public class SimpleTimeZone extends java.util.TimeZone {
@@ -59954,7 +59949,7 @@
     field public static final int WALL_TIME = 0; // 0x0
   }
 
-  public abstract interface SortedMap implements java.util.Map {
+  public abstract interface SortedMap<K, V> implements java.util.Map {
     method public abstract java.util.Comparator<? super K> comparator();
     method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public abstract K firstKey();
@@ -59966,7 +59961,7 @@
     method public abstract java.util.Collection<V> values();
   }
 
-  public abstract interface SortedSet implements java.util.Set {
+  public abstract interface SortedSet<E> implements java.util.Set {
     method public abstract java.util.Comparator<? super E> comparator();
     method public abstract E first();
     method public abstract java.util.SortedSet<E> headSet(E);
@@ -59975,7 +59970,7 @@
     method public abstract java.util.SortedSet<E> tailSet(E);
   }
 
-  public abstract interface Spliterator {
+  public abstract interface Spliterator<T> {
     method public abstract int characteristics();
     method public abstract long estimateSize();
     method public default void forEachRemaining(java.util.function.Consumer<? super T>);
@@ -60018,7 +60013,7 @@
     method public abstract java.util.Spliterator.OfLong trySplit();
   }
 
-  public static abstract interface Spliterator.OfPrimitive implements java.util.Spliterator {
+  public static abstract interface Spliterator.OfPrimitive<T, T_CONS, T_SPLITR extends java.util.Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>> implements java.util.Spliterator {
     method public default void forEachRemaining(T_CONS);
     method public abstract boolean tryAdvance(T_CONS);
     method public abstract T_SPLITR trySplit();
@@ -60028,25 +60023,25 @@
     method public static java.util.Spliterator.OfDouble emptyDoubleSpliterator();
     method public static java.util.Spliterator.OfInt emptyIntSpliterator();
     method public static java.util.Spliterator.OfLong emptyLongSpliterator();
-    method public static java.util.Spliterator<T> emptySpliterator();
-    method public static java.util.Iterator<T> iterator(java.util.Spliterator<? extends T>);
+    method public static <T> java.util.Spliterator<T> emptySpliterator();
+    method public static <T> java.util.Iterator<T> iterator(java.util.Spliterator<? extends T>);
     method public static java.util.PrimitiveIterator.OfInt iterator(java.util.Spliterator.OfInt);
     method public static java.util.PrimitiveIterator.OfLong iterator(java.util.Spliterator.OfLong);
     method public static java.util.PrimitiveIterator.OfDouble iterator(java.util.Spliterator.OfDouble);
-    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int);
-    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int, int, int);
+    method public static <T> java.util.Spliterator<T> spliterator(java.lang.Object[], int);
+    method public static <T> java.util.Spliterator<T> spliterator(java.lang.Object[], int, int, int);
     method public static java.util.Spliterator.OfInt spliterator(int[], int);
     method public static java.util.Spliterator.OfInt spliterator(int[], int, int, int);
     method public static java.util.Spliterator.OfLong spliterator(long[], int);
     method public static java.util.Spliterator.OfLong spliterator(long[], int, int, int);
     method public static java.util.Spliterator.OfDouble spliterator(double[], int);
     method public static java.util.Spliterator.OfDouble spliterator(double[], int, int, int);
-    method public static java.util.Spliterator<T> spliterator(java.util.Collection<? extends T>, int);
-    method public static java.util.Spliterator<T> spliterator(java.util.Iterator<? extends T>, long, int);
+    method public static <T> java.util.Spliterator<T> spliterator(java.util.Collection<? extends T>, int);
+    method public static <T> java.util.Spliterator<T> spliterator(java.util.Iterator<? extends T>, long, int);
     method public static java.util.Spliterator.OfInt spliterator(java.util.PrimitiveIterator.OfInt, long, int);
     method public static java.util.Spliterator.OfLong spliterator(java.util.PrimitiveIterator.OfLong, long, int);
     method public static java.util.Spliterator.OfDouble spliterator(java.util.PrimitiveIterator.OfDouble, long, int);
-    method public static java.util.Spliterator<T> spliteratorUnknownSize(java.util.Iterator<? extends T>, int);
+    method public static <T> java.util.Spliterator<T> spliteratorUnknownSize(java.util.Iterator<? extends T>, int);
     method public static java.util.Spliterator.OfInt spliteratorUnknownSize(java.util.PrimitiveIterator.OfInt, int);
     method public static java.util.Spliterator.OfLong spliteratorUnknownSize(java.util.PrimitiveIterator.OfLong, int);
     method public static java.util.Spliterator.OfDouble spliteratorUnknownSize(java.util.PrimitiveIterator.OfDouble, int);
@@ -60073,7 +60068,7 @@
     method public java.util.Spliterator.OfLong trySplit();
   }
 
-  public static abstract class Spliterators.AbstractSpliterator implements java.util.Spliterator {
+  public static abstract class Spliterators.AbstractSpliterator<T> implements java.util.Spliterator {
     ctor protected Spliterators.AbstractSpliterator(long, int);
     method public int characteristics();
     method public long estimateSize();
@@ -60108,7 +60103,7 @@
     method public java.util.SplittableRandom split();
   }
 
-  public class Stack extends java.util.Vector {
+  public class Stack<E> extends java.util.Vector {
     ctor public Stack();
     method public boolean empty();
     method public synchronized E peek();
@@ -60192,7 +60187,7 @@
     ctor public TooManyListenersException(java.lang.String);
   }
 
-  public class TreeMap extends java.util.AbstractMap implements java.lang.Cloneable java.util.NavigableMap java.io.Serializable {
+  public class TreeMap<K, V> extends java.util.AbstractMap implements java.lang.Cloneable java.util.NavigableMap java.io.Serializable {
     ctor public TreeMap();
     ctor public TreeMap(java.util.Comparator<? super K>);
     ctor public TreeMap(java.util.Map<? extends K, ? extends V>);
@@ -60229,7 +60224,7 @@
     method public java.util.SortedMap<K, V> tailMap(K);
   }
 
-  public class TreeSet extends java.util.AbstractSet implements java.lang.Cloneable java.util.NavigableSet java.io.Serializable {
+  public class TreeSet<E> extends java.util.AbstractSet implements java.lang.Cloneable java.util.NavigableSet java.io.Serializable {
     ctor public TreeSet();
     ctor public TreeSet(java.util.Comparator<? super E>);
     ctor public TreeSet(java.util.Collection<? extends E>);
@@ -60282,7 +60277,7 @@
     method public java.lang.String getFlags();
   }
 
-  public class Vector extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
+  public class Vector<E> extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
     ctor public Vector(int, int);
     ctor public Vector(int);
     ctor public Vector();
@@ -60317,7 +60312,7 @@
     field protected java.lang.Object[] elementData;
   }
 
-  public class WeakHashMap extends java.util.AbstractMap implements java.util.Map {
+  public class WeakHashMap<K, V> extends java.util.AbstractMap implements java.util.Map {
     ctor public WeakHashMap(int, float);
     ctor public WeakHashMap(int);
     ctor public WeakHashMap();
@@ -60333,18 +60328,18 @@
 
   public abstract class AbstractExecutorService implements java.util.concurrent.ExecutorService {
     ctor public AbstractExecutorService();
-    method public java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.lang.InterruptedException;
-    method public java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
-    method public T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
-    method public T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
-    method protected java.util.concurrent.RunnableFuture<T> newTaskFor(java.lang.Runnable, T);
-    method protected java.util.concurrent.RunnableFuture<T> newTaskFor(java.util.concurrent.Callable<T>);
+    method public <T> java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.lang.InterruptedException;
+    method public <T> java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public <T> T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public <T> T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method protected <T> java.util.concurrent.RunnableFuture<T> newTaskFor(java.lang.Runnable, T);
+    method protected <T> java.util.concurrent.RunnableFuture<T> newTaskFor(java.util.concurrent.Callable<T>);
     method public java.util.concurrent.Future<?> submit(java.lang.Runnable);
-    method public java.util.concurrent.Future<T> submit(java.lang.Runnable, T);
-    method public java.util.concurrent.Future<T> submit(java.util.concurrent.Callable<T>);
+    method public <T> java.util.concurrent.Future<T> submit(java.lang.Runnable, T);
+    method public <T> java.util.concurrent.Future<T> submit(java.util.concurrent.Callable<T>);
   }
 
-  public class ArrayBlockingQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
+  public class ArrayBlockingQueue<E> extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
     ctor public ArrayBlockingQueue(int);
     ctor public ArrayBlockingQueue(int, boolean);
     ctor public ArrayBlockingQueue(int, boolean, java.util.Collection<? extends E>);
@@ -60363,7 +60358,7 @@
     method public E take() throws java.lang.InterruptedException;
   }
 
-  public abstract interface BlockingDeque implements java.util.concurrent.BlockingQueue java.util.Deque {
+  public abstract interface BlockingDeque<E> implements java.util.concurrent.BlockingQueue java.util.Deque {
     method public abstract boolean add(E);
     method public abstract void addFirst(E);
     method public abstract void addLast(E);
@@ -60395,7 +60390,7 @@
     method public abstract E takeLast() throws java.lang.InterruptedException;
   }
 
-  public abstract interface BlockingQueue implements java.util.Queue {
+  public abstract interface BlockingQueue<E> implements java.util.Queue {
     method public abstract boolean add(E);
     method public abstract boolean contains(java.lang.Object);
     method public abstract int drainTo(java.util.Collection<? super E>);
@@ -60414,7 +60409,7 @@
     ctor public BrokenBarrierException(java.lang.String);
   }
 
-  public abstract interface Callable {
+  public abstract interface Callable<V> {
     method public abstract V call() throws java.lang.Exception;
   }
 
@@ -60423,28 +60418,28 @@
     ctor public CancellationException(java.lang.String);
   }
 
-  public class CompletableFuture implements java.util.concurrent.CompletionStage java.util.concurrent.Future {
+  public class CompletableFuture<T> implements java.util.concurrent.CompletionStage java.util.concurrent.Future {
     ctor public CompletableFuture();
     method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
     method public static java.util.concurrent.CompletableFuture<java.lang.Void> allOf(java.util.concurrent.CompletableFuture<?>...);
     method public static java.util.concurrent.CompletableFuture<java.lang.Object> anyOf(java.util.concurrent.CompletableFuture<?>...);
-    method public java.util.concurrent.CompletableFuture<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
-    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
-    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public <U> java.util.concurrent.CompletableFuture<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
     method public boolean cancel(boolean);
     method public boolean complete(T);
     method public boolean completeExceptionally(java.lang.Throwable);
-    method public static java.util.concurrent.CompletableFuture<U> completedFuture(U);
+    method public static <U> java.util.concurrent.CompletableFuture<U> completedFuture(U);
     method public java.util.concurrent.CompletableFuture<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
     method public T get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
     method public T get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
     method public T getNow(T);
     method public int getNumberOfDependents();
-    method public java.util.concurrent.CompletableFuture<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
-    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
-    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public <U> java.util.concurrent.CompletableFuture<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
     method public boolean isCancelled();
     method public boolean isCompletedExceptionally();
     method public boolean isDone();
@@ -60459,23 +60454,23 @@
     method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
     method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable);
     method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable, java.util.concurrent.Executor);
-    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>);
-    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>, java.util.concurrent.Executor);
+    method public static <U> java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>);
+    method public static <U> java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>, java.util.concurrent.Executor);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
-    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
-    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
-    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
-    method public java.util.concurrent.CompletableFuture<U> thenApply(java.util.function.Function<? super T, ? extends U>);
-    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
-    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
-    method public java.util.concurrent.CompletableFuture<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
-    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
-    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
-    method public java.util.concurrent.CompletableFuture<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
-    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
-    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public <U> java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public <U> java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public <U> java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public <U, V> java.util.concurrent.CompletableFuture<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public <U, V> java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public <U, V> java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRun(java.lang.Runnable);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
@@ -60495,7 +60490,7 @@
     ctor public CompletionException(java.lang.Throwable);
   }
 
-  public abstract interface CompletionService {
+  public abstract interface CompletionService<V> {
     method public abstract java.util.concurrent.Future<V> poll();
     method public abstract java.util.concurrent.Future<V> poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
     method public abstract java.util.concurrent.Future<V> submit(java.util.concurrent.Callable<V>);
@@ -60503,17 +60498,17 @@
     method public abstract java.util.concurrent.Future<V> take() throws java.lang.InterruptedException;
   }
 
-  public abstract interface CompletionStage {
+  public abstract interface CompletionStage<T> {
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
-    method public abstract java.util.concurrent.CompletionStage<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
-    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
-    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
     method public abstract java.util.concurrent.CompletionStage<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
-    method public abstract java.util.concurrent.CompletionStage<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
-    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
-    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
@@ -60523,18 +60518,18 @@
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
-    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
-    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
-    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
-    method public abstract java.util.concurrent.CompletionStage<U> thenApply(java.util.function.Function<? super T, ? extends U>);
-    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
-    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
-    method public abstract java.util.concurrent.CompletionStage<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
-    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
-    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
-    method public abstract java.util.concurrent.CompletionStage<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
-    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
-    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public abstract <U> java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public abstract <U, V> java.util.concurrent.CompletionStage<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract <U, V> java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract <U, V> java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRun(java.lang.Runnable);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
@@ -60544,7 +60539,7 @@
     method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor);
   }
 
-  public class ConcurrentHashMap extends java.util.AbstractMap implements java.util.concurrent.ConcurrentMap java.io.Serializable {
+  public class ConcurrentHashMap<K, V> extends java.util.AbstractMap implements java.util.concurrent.ConcurrentMap java.io.Serializable {
     ctor public ConcurrentHashMap();
     ctor public ConcurrentHashMap(int);
     ctor public ConcurrentHashMap(java.util.Map<? extends K, ? extends V>);
@@ -60558,29 +60553,29 @@
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public void forEach(long, java.util.function.BiConsumer<? super K, ? super V>);
-    method public void forEach(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public <U> void forEach(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.Consumer<? super U>);
     method public void forEachEntry(long, java.util.function.Consumer<? super java.util.Map.Entry<K, V>>);
-    method public void forEachEntry(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.Consumer<? super U>);
+    method public <U> void forEachEntry(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.Consumer<? super U>);
     method public void forEachKey(long, java.util.function.Consumer<? super K>);
-    method public void forEachKey(long, java.util.function.Function<? super K, ? extends U>, java.util.function.Consumer<? super U>);
+    method public <U> void forEachKey(long, java.util.function.Function<? super K, ? extends U>, java.util.function.Consumer<? super U>);
     method public void forEachValue(long, java.util.function.Consumer<? super V>);
-    method public void forEachValue(long, java.util.function.Function<? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public <U> void forEachValue(long, java.util.function.Function<? super V, ? extends U>, java.util.function.Consumer<? super U>);
     method public V getOrDefault(java.lang.Object, V);
     method public java.util.concurrent.ConcurrentHashMap.KeySetView<K, V> keySet(V);
     method public java.util.Enumeration<K> keys();
     method public long mappingCount();
     method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
-    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet();
-    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(int);
+    method public static <K> java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet();
+    method public static <K> java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(int);
     method public V putIfAbsent(K, V);
-    method public U reduce(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public <U> U reduce(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
     method public java.util.Map.Entry<K, V> reduceEntries(long, java.util.function.BiFunction<java.util.Map.Entry<K, V>, java.util.Map.Entry<K, V>, ? extends java.util.Map.Entry<K, V>>);
-    method public U reduceEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public <U> U reduceEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
     method public double reduceEntriesToDouble(long, java.util.function.ToDoubleFunction<java.util.Map.Entry<K, V>>, double, java.util.function.DoubleBinaryOperator);
     method public int reduceEntriesToInt(long, java.util.function.ToIntFunction<java.util.Map.Entry<K, V>>, int, java.util.function.IntBinaryOperator);
     method public long reduceEntriesToLong(long, java.util.function.ToLongFunction<java.util.Map.Entry<K, V>>, long, java.util.function.LongBinaryOperator);
     method public K reduceKeys(long, java.util.function.BiFunction<? super K, ? super K, ? extends K>);
-    method public U reduceKeys(long, java.util.function.Function<? super K, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public <U> U reduceKeys(long, java.util.function.Function<? super K, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
     method public double reduceKeysToDouble(long, java.util.function.ToDoubleFunction<? super K>, double, java.util.function.DoubleBinaryOperator);
     method public int reduceKeysToInt(long, java.util.function.ToIntFunction<? super K>, int, java.util.function.IntBinaryOperator);
     method public long reduceKeysToLong(long, java.util.function.ToLongFunction<? super K>, long, java.util.function.LongBinaryOperator);
@@ -60588,7 +60583,7 @@
     method public int reduceToInt(long, java.util.function.ToIntBiFunction<? super K, ? super V>, int, java.util.function.IntBinaryOperator);
     method public long reduceToLong(long, java.util.function.ToLongBiFunction<? super K, ? super V>, long, java.util.function.LongBinaryOperator);
     method public V reduceValues(long, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
-    method public U reduceValues(long, java.util.function.Function<? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public <U> U reduceValues(long, java.util.function.Function<? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
     method public double reduceValuesToDouble(long, java.util.function.ToDoubleFunction<? super V>, double, java.util.function.DoubleBinaryOperator);
     method public int reduceValuesToInt(long, java.util.function.ToIntFunction<? super V>, int, java.util.function.IntBinaryOperator);
     method public long reduceValuesToLong(long, java.util.function.ToLongFunction<? super V>, long, java.util.function.LongBinaryOperator);
@@ -60596,13 +60591,13 @@
     method public boolean replace(K, V, V);
     method public V replace(K, V);
     method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
-    method public U search(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>);
-    method public U searchEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>);
-    method public U searchKeys(long, java.util.function.Function<? super K, ? extends U>);
-    method public U searchValues(long, java.util.function.Function<? super V, ? extends U>);
+    method public <U> U search(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>);
+    method public <U> U searchEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>);
+    method public <U> U searchKeys(long, java.util.function.Function<? super K, ? extends U>);
+    method public <U> U searchValues(long, java.util.function.Function<? super V, ? extends U>);
   }
 
-   static abstract class ConcurrentHashMap.CollectionView implements java.util.Collection java.io.Serializable {
+   static abstract class ConcurrentHashMap.CollectionView<K, V, E> implements java.util.Collection java.io.Serializable {
     method public final void clear();
     method public abstract boolean contains(java.lang.Object);
     method public final boolean containsAll(java.util.Collection<?>);
@@ -60614,11 +60609,11 @@
     method public final boolean retainAll(java.util.Collection<?>);
     method public final int size();
     method public final java.lang.Object[] toArray();
-    method public final T[] toArray(T[]);
+    method public final <T> T[] toArray(T[]);
     method public final java.lang.String toString();
   }
 
-  public static class ConcurrentHashMap.KeySetView extends java.util.concurrent.ConcurrentHashMap.CollectionView implements java.io.Serializable java.util.Set {
+  public static class ConcurrentHashMap.KeySetView<K, V> extends java.util.concurrent.ConcurrentHashMap.CollectionView implements java.io.Serializable java.util.Set {
     method public boolean add(K);
     method public boolean addAll(java.util.Collection<? extends K>);
     method public boolean contains(java.lang.Object);
@@ -60629,7 +60624,7 @@
     method public java.util.Spliterator<K> spliterator();
   }
 
-  public class ConcurrentLinkedDeque extends java.util.AbstractCollection implements java.util.Deque java.io.Serializable {
+  public class ConcurrentLinkedDeque<E> extends java.util.AbstractCollection implements java.util.Deque java.io.Serializable {
     ctor public ConcurrentLinkedDeque();
     ctor public ConcurrentLinkedDeque(java.util.Collection<? extends E>);
     method public void addFirst(E);
@@ -60659,7 +60654,7 @@
     method public java.util.Spliterator<E> spliterator();
   }
 
-  public class ConcurrentLinkedQueue extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable {
+  public class ConcurrentLinkedQueue<E> extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable {
     ctor public ConcurrentLinkedQueue();
     ctor public ConcurrentLinkedQueue(java.util.Collection<? extends E>);
     method public java.util.Iterator<E> iterator();
@@ -60670,14 +60665,14 @@
     method public java.util.Spliterator<E> spliterator();
   }
 
-  public abstract interface ConcurrentMap implements java.util.Map {
+  public abstract interface ConcurrentMap<K, V> implements java.util.Map {
     method public abstract V putIfAbsent(K, V);
     method public abstract boolean remove(java.lang.Object, java.lang.Object);
     method public abstract boolean replace(K, V, V);
     method public abstract V replace(K, V);
   }
 
-  public abstract interface ConcurrentNavigableMap implements java.util.concurrent.ConcurrentMap java.util.NavigableMap {
+  public abstract interface ConcurrentNavigableMap<K, V> implements java.util.concurrent.ConcurrentMap java.util.NavigableMap {
     method public abstract java.util.NavigableSet<K> descendingKeySet();
     method public abstract java.util.concurrent.ConcurrentNavigableMap<K, V> descendingMap();
     method public abstract java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K, boolean);
@@ -60690,7 +60685,7 @@
     method public abstract java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K);
   }
 
-  public class ConcurrentSkipListMap extends java.util.AbstractMap implements java.lang.Cloneable java.util.concurrent.ConcurrentNavigableMap java.io.Serializable {
+  public class ConcurrentSkipListMap<K, V> extends java.util.AbstractMap implements java.lang.Cloneable java.util.concurrent.ConcurrentNavigableMap java.io.Serializable {
     ctor public ConcurrentSkipListMap();
     ctor public ConcurrentSkipListMap(java.util.Comparator<? super K>);
     ctor public ConcurrentSkipListMap(java.util.Map<? extends K, ? extends V>);
@@ -60734,7 +60729,7 @@
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K);
   }
 
-  public class ConcurrentSkipListSet extends java.util.AbstractSet implements java.lang.Cloneable java.util.NavigableSet java.io.Serializable {
+  public class ConcurrentSkipListSet<E> extends java.util.AbstractSet implements java.lang.Cloneable java.util.NavigableSet java.io.Serializable {
     ctor public ConcurrentSkipListSet();
     ctor public ConcurrentSkipListSet(java.util.Comparator<? super E>);
     ctor public ConcurrentSkipListSet(java.util.Collection<? extends E>);
@@ -60762,7 +60757,7 @@
     method public java.util.NavigableSet<E> tailSet(E);
   }
 
-  public class CopyOnWriteArrayList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
+  public class CopyOnWriteArrayList<E> implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
     ctor public CopyOnWriteArrayList();
     ctor public CopyOnWriteArrayList(java.util.Collection<? extends E>);
     ctor public CopyOnWriteArrayList(E[]);
@@ -60794,10 +60789,10 @@
     method public int size();
     method public java.util.List<E> subList(int, int);
     method public java.lang.Object[] toArray();
-    method public T[] toArray(T[]);
+    method public <T> T[] toArray(T[]);
   }
 
-  public class CopyOnWriteArraySet extends java.util.AbstractSet implements java.io.Serializable {
+  public class CopyOnWriteArraySet<E> extends java.util.AbstractSet implements java.io.Serializable {
     ctor public CopyOnWriteArraySet();
     ctor public CopyOnWriteArraySet(java.util.Collection<? extends E>);
     method public void forEach(java.util.function.Consumer<? super E>);
@@ -60815,7 +60810,7 @@
     method public long getCount();
   }
 
-  public abstract class CountedCompleter extends java.util.concurrent.ForkJoinTask {
+  public abstract class CountedCompleter<T> extends java.util.concurrent.ForkJoinTask {
     ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>, int);
     ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>);
     ctor protected CountedCompleter();
@@ -60852,7 +60847,7 @@
     method public void reset();
   }
 
-  public class DelayQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue {
+  public class DelayQueue<E extends java.util.concurrent.Delayed> extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue {
     ctor public DelayQueue();
     ctor public DelayQueue(java.util.Collection<? extends E>);
     method public int drainTo(java.util.Collection<? super E>);
@@ -60873,7 +60868,7 @@
     method public abstract long getDelay(java.util.concurrent.TimeUnit);
   }
 
-  public class Exchanger {
+  public class Exchanger<V> {
     ctor public Exchanger();
     method public V exchange(V) throws java.lang.InterruptedException;
     method public V exchange(V, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException, java.util.concurrent.TimeoutException;
@@ -60890,7 +60885,7 @@
     method public abstract void execute(java.lang.Runnable);
   }
 
-  public class ExecutorCompletionService implements java.util.concurrent.CompletionService {
+  public class ExecutorCompletionService<V> implements java.util.concurrent.CompletionService {
     ctor public ExecutorCompletionService(java.util.concurrent.Executor);
     ctor public ExecutorCompletionService(java.util.concurrent.Executor, java.util.concurrent.BlockingQueue<java.util.concurrent.Future<V>>);
     method public java.util.concurrent.Future<V> poll();
@@ -60902,21 +60897,21 @@
 
   public abstract interface ExecutorService implements java.util.concurrent.Executor {
     method public abstract boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
-    method public abstract java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.lang.InterruptedException;
-    method public abstract java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
-    method public abstract T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
-    method public abstract T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method public abstract <T> java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.lang.InterruptedException;
+    method public abstract <T> java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public abstract <T> T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public abstract <T> T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
     method public abstract boolean isShutdown();
     method public abstract boolean isTerminated();
     method public abstract void shutdown();
     method public abstract java.util.List<java.lang.Runnable> shutdownNow();
-    method public abstract java.util.concurrent.Future<T> submit(java.util.concurrent.Callable<T>);
-    method public abstract java.util.concurrent.Future<T> submit(java.lang.Runnable, T);
+    method public abstract <T> java.util.concurrent.Future<T> submit(java.util.concurrent.Callable<T>);
+    method public abstract <T> java.util.concurrent.Future<T> submit(java.lang.Runnable, T);
     method public abstract java.util.concurrent.Future<?> submit(java.lang.Runnable);
   }
 
   public class Executors {
-    method public static java.util.concurrent.Callable<T> callable(java.lang.Runnable, T);
+    method public static <T> java.util.concurrent.Callable<T> callable(java.lang.Runnable, T);
     method public static java.util.concurrent.Callable<java.lang.Object> callable(java.lang.Runnable);
     method public static java.util.concurrent.Callable<java.lang.Object> callable(java.security.PrivilegedAction<?>);
     method public static java.util.concurrent.Callable<java.lang.Object> callable(java.security.PrivilegedExceptionAction<?>);
@@ -60933,8 +60928,8 @@
     method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor(java.util.concurrent.ThreadFactory);
     method public static java.util.concurrent.ExecutorService newWorkStealingPool(int);
     method public static java.util.concurrent.ExecutorService newWorkStealingPool();
-    method public static java.util.concurrent.Callable<T> privilegedCallable(java.util.concurrent.Callable<T>);
-    method public static java.util.concurrent.Callable<T> privilegedCallableUsingCurrentClassLoader(java.util.concurrent.Callable<T>);
+    method public static <T> java.util.concurrent.Callable<T> privilegedCallable(java.util.concurrent.Callable<T>);
+    method public static <T> java.util.concurrent.Callable<T> privilegedCallableUsingCurrentClassLoader(java.util.concurrent.Callable<T>);
     method public static java.util.concurrent.ThreadFactory privilegedThreadFactory();
     method public static java.util.concurrent.ExecutorService unconfigurableExecutorService(java.util.concurrent.ExecutorService);
     method public static java.util.concurrent.ScheduledExecutorService unconfigurableScheduledExecutorService(java.util.concurrent.ScheduledExecutorService);
@@ -60962,7 +60957,7 @@
     method public long getStealCount();
     method public java.lang.Thread.UncaughtExceptionHandler getUncaughtExceptionHandler();
     method public boolean hasQueuedSubmissions();
-    method public T invoke(java.util.concurrent.ForkJoinTask<T>);
+    method public <T> T invoke(java.util.concurrent.ForkJoinTask<T>);
     method public boolean isQuiescent();
     method public boolean isShutdown();
     method public boolean isTerminated();
@@ -60971,7 +60966,7 @@
     method protected java.util.concurrent.ForkJoinTask<?> pollSubmission();
     method public void shutdown();
     method public java.util.List<java.lang.Runnable> shutdownNow();
-    method public java.util.concurrent.ForkJoinTask<T> submit(java.util.concurrent.ForkJoinTask<T>);
+    method public <T> java.util.concurrent.ForkJoinTask<T> submit(java.util.concurrent.ForkJoinTask<T>);
     field public static final java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory defaultForkJoinWorkerThreadFactory;
   }
 
@@ -60984,11 +60979,11 @@
     method public abstract boolean isReleasable();
   }
 
-  public abstract class ForkJoinTask implements java.util.concurrent.Future java.io.Serializable {
+  public abstract class ForkJoinTask<V> implements java.util.concurrent.Future java.io.Serializable {
     ctor public ForkJoinTask();
     method public static java.util.concurrent.ForkJoinTask<?> adapt(java.lang.Runnable);
-    method public static java.util.concurrent.ForkJoinTask<T> adapt(java.lang.Runnable, T);
-    method public static java.util.concurrent.ForkJoinTask<T> adapt(java.util.concurrent.Callable<? extends T>);
+    method public static <T> java.util.concurrent.ForkJoinTask<T> adapt(java.lang.Runnable, T);
+    method public static <T> java.util.concurrent.ForkJoinTask<T> adapt(java.util.concurrent.Callable<? extends T>);
     method public boolean cancel(boolean);
     method public final boolean compareAndSetForkJoinTaskTag(short, short);
     method public void complete(V);
@@ -61008,7 +61003,7 @@
     method public final V invoke();
     method public static void invokeAll(java.util.concurrent.ForkJoinTask<?>, java.util.concurrent.ForkJoinTask<?>);
     method public static void invokeAll(java.util.concurrent.ForkJoinTask<?>...);
-    method public static java.util.Collection<T> invokeAll(java.util.Collection<T>);
+    method public static <T extends java.util.concurrent.ForkJoinTask<?>> java.util.Collection<T> invokeAll(java.util.Collection<T>);
     method public final boolean isCancelled();
     method public final boolean isCompletedAbnormally();
     method public final boolean isCompletedNormally();
@@ -61034,7 +61029,7 @@
     method protected void onTermination(java.lang.Throwable);
   }
 
-  public abstract interface Future {
+  public abstract interface Future<V> {
     method public abstract boolean cancel(boolean);
     method public abstract V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
     method public abstract V get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
@@ -61042,7 +61037,7 @@
     method public abstract boolean isDone();
   }
 
-  public class FutureTask implements java.util.concurrent.RunnableFuture {
+  public class FutureTask<V> implements java.util.concurrent.RunnableFuture {
     ctor public FutureTask(java.util.concurrent.Callable<V>);
     ctor public FutureTask(java.lang.Runnable, V);
     method public boolean cancel(boolean);
@@ -61057,7 +61052,7 @@
     method protected void setException(java.lang.Throwable);
   }
 
-  public class LinkedBlockingDeque extends java.util.AbstractQueue implements java.util.concurrent.BlockingDeque java.io.Serializable {
+  public class LinkedBlockingDeque<E> extends java.util.AbstractQueue implements java.util.concurrent.BlockingDeque java.io.Serializable {
     ctor public LinkedBlockingDeque();
     ctor public LinkedBlockingDeque(int);
     ctor public LinkedBlockingDeque(java.util.Collection<? extends E>);
@@ -61101,7 +61096,7 @@
     method public E takeLast() throws java.lang.InterruptedException;
   }
 
-  public class LinkedBlockingQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
+  public class LinkedBlockingQueue<E> extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
     ctor public LinkedBlockingQueue();
     ctor public LinkedBlockingQueue(int);
     ctor public LinkedBlockingQueue(java.util.Collection<? extends E>);
@@ -61120,7 +61115,7 @@
     method public E take() throws java.lang.InterruptedException;
   }
 
-  public class LinkedTransferQueue extends java.util.AbstractQueue implements java.io.Serializable java.util.concurrent.TransferQueue {
+  public class LinkedTransferQueue<E> extends java.util.AbstractQueue implements java.io.Serializable java.util.concurrent.TransferQueue {
     ctor public LinkedTransferQueue();
     ctor public LinkedTransferQueue(java.util.Collection<? extends E>);
     method public int drainTo(java.util.Collection<? super E>);
@@ -61167,7 +61162,7 @@
     method public int register();
   }
 
-  public class PriorityBlockingQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
+  public class PriorityBlockingQueue<E> extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
     ctor public PriorityBlockingQueue();
     ctor public PriorityBlockingQueue(int);
     ctor public PriorityBlockingQueue(int, java.util.Comparator<? super E>);
@@ -61196,7 +61191,7 @@
     method protected final void setRawResult(java.lang.Void);
   }
 
-  public abstract class RecursiveTask extends java.util.concurrent.ForkJoinTask {
+  public abstract class RecursiveTask<V> extends java.util.concurrent.ForkJoinTask {
     ctor public RecursiveTask();
     method protected abstract V compute();
     method protected final boolean exec();
@@ -61215,22 +61210,22 @@
     method public abstract void rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor);
   }
 
-  public abstract interface RunnableFuture implements java.util.concurrent.Future java.lang.Runnable {
+  public abstract interface RunnableFuture<V> implements java.util.concurrent.Future java.lang.Runnable {
     method public abstract void run();
   }
 
-  public abstract interface RunnableScheduledFuture implements java.util.concurrent.RunnableFuture java.util.concurrent.ScheduledFuture {
+  public abstract interface RunnableScheduledFuture<V> implements java.util.concurrent.RunnableFuture java.util.concurrent.ScheduledFuture {
     method public abstract boolean isPeriodic();
   }
 
   public abstract interface ScheduledExecutorService implements java.util.concurrent.ExecutorService {
     method public abstract java.util.concurrent.ScheduledFuture<?> schedule(java.lang.Runnable, long, java.util.concurrent.TimeUnit);
-    method public abstract java.util.concurrent.ScheduledFuture<V> schedule(java.util.concurrent.Callable<V>, long, java.util.concurrent.TimeUnit);
+    method public abstract <V> java.util.concurrent.ScheduledFuture<V> schedule(java.util.concurrent.Callable<V>, long, java.util.concurrent.TimeUnit);
     method public abstract java.util.concurrent.ScheduledFuture<?> scheduleAtFixedRate(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
     method public abstract java.util.concurrent.ScheduledFuture<?> scheduleWithFixedDelay(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
   }
 
-  public abstract interface ScheduledFuture implements java.util.concurrent.Delayed java.util.concurrent.Future {
+  public abstract interface ScheduledFuture<V> implements java.util.concurrent.Delayed java.util.concurrent.Future {
   }
 
   public class ScheduledThreadPoolExecutor extends java.util.concurrent.ThreadPoolExecutor implements java.util.concurrent.ScheduledExecutorService {
@@ -61238,13 +61233,13 @@
     ctor public ScheduledThreadPoolExecutor(int, java.util.concurrent.ThreadFactory);
     ctor public ScheduledThreadPoolExecutor(int, java.util.concurrent.RejectedExecutionHandler);
     ctor public ScheduledThreadPoolExecutor(int, java.util.concurrent.ThreadFactory, java.util.concurrent.RejectedExecutionHandler);
-    method protected java.util.concurrent.RunnableScheduledFuture<V> decorateTask(java.lang.Runnable, java.util.concurrent.RunnableScheduledFuture<V>);
-    method protected java.util.concurrent.RunnableScheduledFuture<V> decorateTask(java.util.concurrent.Callable<V>, java.util.concurrent.RunnableScheduledFuture<V>);
+    method protected <V> java.util.concurrent.RunnableScheduledFuture<V> decorateTask(java.lang.Runnable, java.util.concurrent.RunnableScheduledFuture<V>);
+    method protected <V> java.util.concurrent.RunnableScheduledFuture<V> decorateTask(java.util.concurrent.Callable<V>, java.util.concurrent.RunnableScheduledFuture<V>);
     method public boolean getContinueExistingPeriodicTasksAfterShutdownPolicy();
     method public boolean getExecuteExistingDelayedTasksAfterShutdownPolicy();
     method public boolean getRemoveOnCancelPolicy();
     method public java.util.concurrent.ScheduledFuture<?> schedule(java.lang.Runnable, long, java.util.concurrent.TimeUnit);
-    method public java.util.concurrent.ScheduledFuture<V> schedule(java.util.concurrent.Callable<V>, long, java.util.concurrent.TimeUnit);
+    method public <V> java.util.concurrent.ScheduledFuture<V> schedule(java.util.concurrent.Callable<V>, long, java.util.concurrent.TimeUnit);
     method public java.util.concurrent.ScheduledFuture<?> scheduleAtFixedRate(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
     method public java.util.concurrent.ScheduledFuture<?> scheduleWithFixedDelay(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
     method public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean);
@@ -61274,7 +61269,7 @@
     method public boolean tryAcquire(int, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
   }
 
-  public class SynchronousQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
+  public class SynchronousQueue<E> extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
     ctor public SynchronousQueue();
     ctor public SynchronousQueue(boolean);
     method public int drainTo(java.util.Collection<? super E>);
@@ -61392,7 +61387,7 @@
     ctor public TimeoutException(java.lang.String);
   }
 
-  public abstract interface TransferQueue implements java.util.concurrent.BlockingQueue {
+  public abstract interface TransferQueue<E> implements java.util.concurrent.BlockingQueue {
     method public abstract int getWaitingConsumerCount();
     method public abstract boolean hasWaitingConsumer();
     method public abstract void transfer(E) throws java.lang.InterruptedException;
@@ -61462,7 +61457,7 @@
     method public final boolean weakCompareAndSet(int, int, int);
   }
 
-  public abstract class AtomicIntegerFieldUpdater {
+  public abstract class AtomicIntegerFieldUpdater<T> {
     ctor protected AtomicIntegerFieldUpdater();
     method public final int accumulateAndGet(T, int, java.util.function.IntBinaryOperator);
     method public int addAndGet(T, int);
@@ -61477,7 +61472,7 @@
     method public final int getAndUpdate(T, java.util.function.IntUnaryOperator);
     method public int incrementAndGet(T);
     method public abstract void lazySet(T, int);
-    method public static java.util.concurrent.atomic.AtomicIntegerFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
+    method public static <U> java.util.concurrent.atomic.AtomicIntegerFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, int);
     method public final int updateAndGet(T, java.util.function.IntUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, int, int);
@@ -61530,7 +61525,7 @@
     method public final boolean weakCompareAndSet(int, long, long);
   }
 
-  public abstract class AtomicLongFieldUpdater {
+  public abstract class AtomicLongFieldUpdater<T> {
     ctor protected AtomicLongFieldUpdater();
     method public final long accumulateAndGet(T, long, java.util.function.LongBinaryOperator);
     method public long addAndGet(T, long);
@@ -61545,13 +61540,13 @@
     method public final long getAndUpdate(T, java.util.function.LongUnaryOperator);
     method public long incrementAndGet(T);
     method public abstract void lazySet(T, long);
-    method public static java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
+    method public static <U> java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, long);
     method public final long updateAndGet(T, java.util.function.LongUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, long, long);
   }
 
-  public class AtomicMarkableReference {
+  public class AtomicMarkableReference<V> {
     ctor public AtomicMarkableReference(V, boolean);
     method public boolean attemptMark(V, boolean);
     method public boolean compareAndSet(V, V, boolean, boolean);
@@ -61562,7 +61557,7 @@
     method public boolean weakCompareAndSet(V, V, boolean, boolean);
   }
 
-  public class AtomicReference implements java.io.Serializable {
+  public class AtomicReference<V> implements java.io.Serializable {
     ctor public AtomicReference(V);
     ctor public AtomicReference();
     method public final V accumulateAndGet(V, java.util.function.BinaryOperator<V>);
@@ -61577,7 +61572,7 @@
     method public final boolean weakCompareAndSet(V, V);
   }
 
-  public class AtomicReferenceArray implements java.io.Serializable {
+  public class AtomicReferenceArray<E> implements java.io.Serializable {
     ctor public AtomicReferenceArray(int);
     ctor public AtomicReferenceArray(E[]);
     method public final E accumulateAndGet(int, E, java.util.function.BinaryOperator<E>);
@@ -61593,7 +61588,7 @@
     method public final boolean weakCompareAndSet(int, E, E);
   }
 
-  public abstract class AtomicReferenceFieldUpdater {
+  public abstract class AtomicReferenceFieldUpdater<T, V> {
     ctor protected AtomicReferenceFieldUpdater();
     method public final V accumulateAndGet(T, V, java.util.function.BinaryOperator<V>);
     method public abstract boolean compareAndSet(T, V, V);
@@ -61602,13 +61597,13 @@
     method public V getAndSet(T, V);
     method public final V getAndUpdate(T, java.util.function.UnaryOperator<V>);
     method public abstract void lazySet(T, V);
-    method public static java.util.concurrent.atomic.AtomicReferenceFieldUpdater<U, W> newUpdater(java.lang.Class<U>, java.lang.Class<W>, java.lang.String);
+    method public static <U, W> java.util.concurrent.atomic.AtomicReferenceFieldUpdater<U, W> newUpdater(java.lang.Class<U>, java.lang.Class<W>, java.lang.String);
     method public abstract void set(T, V);
     method public final V updateAndGet(T, java.util.function.UnaryOperator<V>);
     method public abstract boolean weakCompareAndSet(T, V, V);
   }
 
-  public class AtomicStampedReference {
+  public class AtomicStampedReference<V> {
     ctor public AtomicStampedReference(V, int);
     method public boolean attemptStamp(V, int);
     method public boolean compareAndSet(V, V, int, int);
@@ -61911,33 +61906,33 @@
 
 package java.util.function {
 
-  public abstract interface BiConsumer {
+  public abstract interface BiConsumer<T, U> {
     method public abstract void accept(T, U);
     method public default java.util.function.BiConsumer<T, U> andThen(java.util.function.BiConsumer<? super T, ? super U>);
   }
 
-  public abstract interface BiFunction {
-    method public default java.util.function.BiFunction<T, U, V> andThen(java.util.function.Function<? super R, ? extends V>);
+  public abstract interface BiFunction<T, U, R> {
+    method public default <V> java.util.function.BiFunction<T, U, V> andThen(java.util.function.Function<? super R, ? extends V>);
     method public abstract R apply(T, U);
   }
 
-  public abstract interface BiPredicate {
+  public abstract interface BiPredicate<T, U> {
     method public default java.util.function.BiPredicate<T, U> and(java.util.function.BiPredicate<? super T, ? super U>);
     method public default java.util.function.BiPredicate<T, U> negate();
     method public default java.util.function.BiPredicate<T, U> or(java.util.function.BiPredicate<? super T, ? super U>);
     method public abstract boolean test(T, U);
   }
 
-  public abstract interface BinaryOperator implements java.util.function.BiFunction {
-    method public static java.util.function.BinaryOperator<T> maxBy(java.util.Comparator<? super T>);
-    method public static java.util.function.BinaryOperator<T> minBy(java.util.Comparator<? super T>);
+  public abstract interface BinaryOperator<T> implements java.util.function.BiFunction {
+    method public static <T> java.util.function.BinaryOperator<T> maxBy(java.util.Comparator<? super T>);
+    method public static <T> java.util.function.BinaryOperator<T> minBy(java.util.Comparator<? super T>);
   }
 
   public abstract interface BooleanSupplier {
     method public abstract boolean getAsBoolean();
   }
 
-  public abstract interface Consumer {
+  public abstract interface Consumer<T> {
     method public abstract void accept(T);
     method public default java.util.function.Consumer<T> andThen(java.util.function.Consumer<? super T>);
   }
@@ -61951,7 +61946,7 @@
     method public default java.util.function.DoubleConsumer andThen(java.util.function.DoubleConsumer);
   }
 
-  public abstract interface DoubleFunction {
+  public abstract interface DoubleFunction<R> {
     method public abstract R apply(double);
   }
 
@@ -61981,11 +61976,11 @@
     method public static java.util.function.DoubleUnaryOperator identity();
   }
 
-  public abstract interface Function {
-    method public default java.util.function.Function<T, V> andThen(java.util.function.Function<? super R, ? extends V>);
+  public abstract interface Function<T, R> {
+    method public default <V> java.util.function.Function<T, V> andThen(java.util.function.Function<? super R, ? extends V>);
     method public abstract R apply(T);
-    method public default java.util.function.Function<V, R> compose(java.util.function.Function<? super V, ? extends T>);
-    method public static java.util.function.Function<T, T> identity();
+    method public default <V> java.util.function.Function<V, R> compose(java.util.function.Function<? super V, ? extends T>);
+    method public static <T> java.util.function.Function<T, T> identity();
   }
 
   public abstract interface IntBinaryOperator {
@@ -61997,7 +61992,7 @@
     method public default java.util.function.IntConsumer andThen(java.util.function.IntConsumer);
   }
 
-  public abstract interface IntFunction {
+  public abstract interface IntFunction<R> {
     method public abstract R apply(int);
   }
 
@@ -62036,7 +62031,7 @@
     method public default java.util.function.LongConsumer andThen(java.util.function.LongConsumer);
   }
 
-  public abstract interface LongFunction {
+  public abstract interface LongFunction<R> {
     method public abstract R apply(long);
   }
 
@@ -62066,56 +62061,56 @@
     method public static java.util.function.LongUnaryOperator identity();
   }
 
-  public abstract interface ObjDoubleConsumer {
+  public abstract interface ObjDoubleConsumer<T> {
     method public abstract void accept(T, double);
   }
 
-  public abstract interface ObjIntConsumer {
+  public abstract interface ObjIntConsumer<T> {
     method public abstract void accept(T, int);
   }
 
-  public abstract interface ObjLongConsumer {
+  public abstract interface ObjLongConsumer<T> {
     method public abstract void accept(T, long);
   }
 
-  public abstract interface Predicate {
+  public abstract interface Predicate<T> {
     method public default java.util.function.Predicate<T> and(java.util.function.Predicate<? super T>);
-    method public static java.util.function.Predicate<T> isEqual(java.lang.Object);
+    method public static <T> java.util.function.Predicate<T> isEqual(java.lang.Object);
     method public default java.util.function.Predicate<T> negate();
     method public default java.util.function.Predicate<T> or(java.util.function.Predicate<? super T>);
     method public abstract boolean test(T);
   }
 
-  public abstract interface Supplier {
+  public abstract interface Supplier<T> {
     method public abstract T get();
   }
 
-  public abstract interface ToDoubleBiFunction {
+  public abstract interface ToDoubleBiFunction<T, U> {
     method public abstract double applyAsDouble(T, U);
   }
 
-  public abstract interface ToDoubleFunction {
+  public abstract interface ToDoubleFunction<T> {
     method public abstract double applyAsDouble(T);
   }
 
-  public abstract interface ToIntBiFunction {
+  public abstract interface ToIntBiFunction<T, U> {
     method public abstract int applyAsInt(T, U);
   }
 
-  public abstract interface ToIntFunction {
+  public abstract interface ToIntFunction<T> {
     method public abstract int applyAsInt(T);
   }
 
-  public abstract interface ToLongBiFunction {
+  public abstract interface ToLongBiFunction<T, U> {
     method public abstract long applyAsLong(T, U);
   }
 
-  public abstract interface ToLongFunction {
+  public abstract interface ToLongFunction<T> {
     method public abstract long applyAsLong(T);
   }
 
-  public abstract interface UnaryOperator implements java.util.function.Function {
-    method public static java.util.function.UnaryOperator<T> identity();
+  public abstract interface UnaryOperator<T> implements java.util.function.Function {
+    method public static <T> java.util.function.UnaryOperator<T> identity();
   }
 
 }
@@ -62703,7 +62698,7 @@
 
 package java.util.stream {
 
-  public abstract interface BaseStream implements java.lang.AutoCloseable {
+  public abstract interface BaseStream<T, S extends java.util.stream.BaseStream<T, S>> implements java.lang.AutoCloseable {
     method public abstract void close();
     method public abstract boolean isParallel();
     method public abstract java.util.Iterator<T> iterator();
@@ -62714,13 +62709,13 @@
     method public abstract S unordered();
   }
 
-  public abstract interface Collector {
+  public abstract interface Collector<T, A, R> {
     method public abstract java.util.function.BiConsumer<A, T> accumulator();
     method public abstract java.util.Set<java.util.stream.Collector.Characteristics> characteristics();
     method public abstract java.util.function.BinaryOperator<A> combiner();
     method public abstract java.util.function.Function<A, R> finisher();
-    method public static java.util.stream.Collector<T, R, R> of(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, T>, java.util.function.BinaryOperator<R>, java.util.stream.Collector.Characteristics...);
-    method public static java.util.stream.Collector<T, A, R> of(java.util.function.Supplier<A>, java.util.function.BiConsumer<A, T>, java.util.function.BinaryOperator<A>, java.util.function.Function<A, R>, java.util.stream.Collector.Characteristics...);
+    method public static <T, R> java.util.stream.Collector<T, R, R> of(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, T>, java.util.function.BinaryOperator<R>, java.util.stream.Collector.Characteristics...);
+    method public static <T, A, R> java.util.stream.Collector<T, A, R> of(java.util.function.Supplier<A>, java.util.function.BiConsumer<A, T>, java.util.function.BinaryOperator<A>, java.util.function.Function<A, R>, java.util.stream.Collector.Characteristics...);
     method public abstract java.util.function.Supplier<A> supplier();
   }
 
@@ -62733,43 +62728,43 @@
   }
 
   public final class Collectors {
-    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingDouble(java.util.function.ToDoubleFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingInt(java.util.function.ToIntFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingLong(java.util.function.ToLongFunction<? super T>);
-    method public static java.util.stream.Collector<T, A, RR> collectingAndThen(java.util.stream.Collector<T, A, R>, java.util.function.Function<R, RR>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Long> counting();
-    method public static java.util.stream.Collector<T, ?, java.util.Map<K, java.util.List<T>>> groupingBy(java.util.function.Function<? super T, ? extends K>);
-    method public static java.util.stream.Collector<T, ?, java.util.Map<K, D>> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
-    method public static java.util.stream.Collector<T, ?, M> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
-    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, java.util.List<T>>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>);
-    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, D>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
-    method public static java.util.stream.Collector<T, ?, M> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Double> averagingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Double> averagingInt(java.util.function.ToIntFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Double> averagingLong(java.util.function.ToLongFunction<? super T>);
+    method public static <T, A, R, RR> java.util.stream.Collector<T, A, RR> collectingAndThen(java.util.stream.Collector<T, A, R>, java.util.function.Function<R, RR>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Long> counting();
+    method public static <T, K> java.util.stream.Collector<T, ?, java.util.Map<K, java.util.List<T>>> groupingBy(java.util.function.Function<? super T, ? extends K>);
+    method public static <T, K, A, D> java.util.stream.Collector<T, ?, java.util.Map<K, D>> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
+    method public static <T, K, D, A, M extends java.util.Map<K, D>> java.util.stream.Collector<T, ?, M> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
+    method public static <T, K> java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, java.util.List<T>>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>);
+    method public static <T, K, A, D> java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, D>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
+    method public static <T, K, A, D, M extends java.util.concurrent.ConcurrentMap<K, D>> java.util.stream.Collector<T, ?, M> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
     method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining();
     method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining(java.lang.CharSequence);
     method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining(java.lang.CharSequence, java.lang.CharSequence, java.lang.CharSequence);
-    method public static java.util.stream.Collector<T, ?, R> mapping(java.util.function.Function<? super T, ? extends U>, java.util.stream.Collector<? super U, A, R>);
-    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> maxBy(java.util.Comparator<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> minBy(java.util.Comparator<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, java.util.List<T>>> partitioningBy(java.util.function.Predicate<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, D>> partitioningBy(java.util.function.Predicate<? super T>, java.util.stream.Collector<? super T, A, D>);
-    method public static java.util.stream.Collector<T, ?, T> reducing(T, java.util.function.BinaryOperator<T>);
-    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> reducing(java.util.function.BinaryOperator<T>);
-    method public static java.util.stream.Collector<T, ?, U> reducing(U, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
-    method public static java.util.stream.Collector<T, ?, java.util.DoubleSummaryStatistics> summarizingDouble(java.util.function.ToDoubleFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.util.IntSummaryStatistics> summarizingInt(java.util.function.ToIntFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.util.LongSummaryStatistics> summarizingLong(java.util.function.ToLongFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Double> summingDouble(java.util.function.ToDoubleFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Integer> summingInt(java.util.function.ToIntFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Long> summingLong(java.util.function.ToLongFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, C> toCollection(java.util.function.Supplier<C>);
-    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
-    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
-    method public static java.util.stream.Collector<T, ?, M> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
-    method public static java.util.stream.Collector<T, ?, java.util.List<T>> toList();
-    method public static java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
-    method public static java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
-    method public static java.util.stream.Collector<T, ?, M> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
-    method public static java.util.stream.Collector<T, ?, java.util.Set<T>> toSet();
+    method public static <T, U, A, R> java.util.stream.Collector<T, ?, R> mapping(java.util.function.Function<? super T, ? extends U>, java.util.stream.Collector<? super U, A, R>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.Optional<T>> maxBy(java.util.Comparator<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.Optional<T>> minBy(java.util.Comparator<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, java.util.List<T>>> partitioningBy(java.util.function.Predicate<? super T>);
+    method public static <T, D, A> java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, D>> partitioningBy(java.util.function.Predicate<? super T>, java.util.stream.Collector<? super T, A, D>);
+    method public static <T> java.util.stream.Collector<T, ?, T> reducing(T, java.util.function.BinaryOperator<T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.Optional<T>> reducing(java.util.function.BinaryOperator<T>);
+    method public static <T, U> java.util.stream.Collector<T, ?, U> reducing(U, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.DoubleSummaryStatistics> summarizingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.IntSummaryStatistics> summarizingInt(java.util.function.ToIntFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.LongSummaryStatistics> summarizingLong(java.util.function.ToLongFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Double> summingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Integer> summingInt(java.util.function.ToIntFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Long> summingLong(java.util.function.ToLongFunction<? super T>);
+    method public static <T, C extends java.util.Collection<T>> java.util.stream.Collector<T, ?, C> toCollection(java.util.function.Supplier<C>);
+    method public static <T, K, U> java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
+    method public static <T, K, U> java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static <T, K, U, M extends java.util.concurrent.ConcurrentMap<K, U>> java.util.stream.Collector<T, ?, M> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.List<T>> toList();
+    method public static <T, K, U> java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
+    method public static <T, K, U> java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static <T, K, U, M extends java.util.Map<K, U>> java.util.stream.Collector<T, ?, M> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.Set<T>> toSet();
   }
 
   public abstract interface DoubleStream implements java.util.stream.BaseStream {
@@ -62778,7 +62773,7 @@
     method public abstract java.util.OptionalDouble average();
     method public abstract java.util.stream.Stream<java.lang.Double> boxed();
     method public static java.util.stream.DoubleStream.Builder builder();
-    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjDoubleConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public abstract <R> R collect(java.util.function.Supplier<R>, java.util.function.ObjDoubleConsumer<R>, java.util.function.BiConsumer<R, R>);
     method public static java.util.stream.DoubleStream concat(java.util.stream.DoubleStream, java.util.stream.DoubleStream);
     method public abstract long count();
     method public abstract java.util.stream.DoubleStream distinct();
@@ -62796,7 +62791,7 @@
     method public abstract java.util.stream.DoubleStream map(java.util.function.DoubleUnaryOperator);
     method public abstract java.util.stream.IntStream mapToInt(java.util.function.DoubleToIntFunction);
     method public abstract java.util.stream.LongStream mapToLong(java.util.function.DoubleToLongFunction);
-    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.DoubleFunction<? extends U>);
+    method public abstract <U> java.util.stream.Stream<U> mapToObj(java.util.function.DoubleFunction<? extends U>);
     method public abstract java.util.OptionalDouble max();
     method public abstract java.util.OptionalDouble min();
     method public abstract boolean noneMatch(java.util.function.DoublePredicate);
@@ -62829,7 +62824,7 @@
     method public abstract java.util.OptionalDouble average();
     method public abstract java.util.stream.Stream<java.lang.Integer> boxed();
     method public static java.util.stream.IntStream.Builder builder();
-    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjIntConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public abstract <R> R collect(java.util.function.Supplier<R>, java.util.function.ObjIntConsumer<R>, java.util.function.BiConsumer<R, R>);
     method public static java.util.stream.IntStream concat(java.util.stream.IntStream, java.util.stream.IntStream);
     method public abstract long count();
     method public abstract java.util.stream.IntStream distinct();
@@ -62847,7 +62842,7 @@
     method public abstract java.util.stream.IntStream map(java.util.function.IntUnaryOperator);
     method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.IntToDoubleFunction);
     method public abstract java.util.stream.LongStream mapToLong(java.util.function.IntToLongFunction);
-    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.IntFunction<? extends U>);
+    method public abstract <U> java.util.stream.Stream<U> mapToObj(java.util.function.IntFunction<? extends U>);
     method public abstract java.util.OptionalInt max();
     method public abstract java.util.OptionalInt min();
     method public abstract boolean noneMatch(java.util.function.IntPredicate);
@@ -62881,7 +62876,7 @@
     method public abstract java.util.OptionalDouble average();
     method public abstract java.util.stream.Stream<java.lang.Long> boxed();
     method public static java.util.stream.LongStream.Builder builder();
-    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjLongConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public abstract <R> R collect(java.util.function.Supplier<R>, java.util.function.ObjLongConsumer<R>, java.util.function.BiConsumer<R, R>);
     method public static java.util.stream.LongStream concat(java.util.stream.LongStream, java.util.stream.LongStream);
     method public abstract long count();
     method public abstract java.util.stream.LongStream distinct();
@@ -62899,7 +62894,7 @@
     method public abstract java.util.stream.LongStream map(java.util.function.LongUnaryOperator);
     method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.LongToDoubleFunction);
     method public abstract java.util.stream.IntStream mapToInt(java.util.function.LongToIntFunction);
-    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.LongFunction<? extends U>);
+    method public abstract <U> java.util.stream.Stream<U> mapToObj(java.util.function.LongFunction<? extends U>);
     method public abstract java.util.OptionalLong max();
     method public abstract java.util.OptionalLong min();
     method public abstract boolean noneMatch(java.util.function.LongPredicate);
@@ -62926,49 +62921,49 @@
     method public abstract java.util.stream.LongStream build();
   }
 
-  public abstract interface Stream implements java.util.stream.BaseStream {
+  public abstract interface Stream<T> implements java.util.stream.BaseStream {
     method public abstract boolean allMatch(java.util.function.Predicate<? super T>);
     method public abstract boolean anyMatch(java.util.function.Predicate<? super T>);
-    method public static java.util.stream.Stream.Builder<T> builder();
-    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, ? super T>, java.util.function.BiConsumer<R, R>);
-    method public abstract R collect(java.util.stream.Collector<? super T, A, R>);
-    method public static java.util.stream.Stream<T> concat(java.util.stream.Stream<? extends T>, java.util.stream.Stream<? extends T>);
+    method public static <T> java.util.stream.Stream.Builder<T> builder();
+    method public abstract <R> R collect(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, ? super T>, java.util.function.BiConsumer<R, R>);
+    method public abstract <R, A> R collect(java.util.stream.Collector<? super T, A, R>);
+    method public static <T> java.util.stream.Stream<T> concat(java.util.stream.Stream<? extends T>, java.util.stream.Stream<? extends T>);
     method public abstract long count();
     method public abstract java.util.stream.Stream<T> distinct();
-    method public static java.util.stream.Stream<T> empty();
+    method public static <T> java.util.stream.Stream<T> empty();
     method public abstract java.util.stream.Stream<T> filter(java.util.function.Predicate<? super T>);
     method public abstract java.util.Optional<T> findAny();
     method public abstract java.util.Optional<T> findFirst();
-    method public abstract java.util.stream.Stream<R> flatMap(java.util.function.Function<? super T, ? extends java.util.stream.Stream<? extends R>>);
+    method public abstract <R> java.util.stream.Stream<R> flatMap(java.util.function.Function<? super T, ? extends java.util.stream.Stream<? extends R>>);
     method public abstract java.util.stream.DoubleStream flatMapToDouble(java.util.function.Function<? super T, ? extends java.util.stream.DoubleStream>);
     method public abstract java.util.stream.IntStream flatMapToInt(java.util.function.Function<? super T, ? extends java.util.stream.IntStream>);
     method public abstract java.util.stream.LongStream flatMapToLong(java.util.function.Function<? super T, ? extends java.util.stream.LongStream>);
     method public abstract void forEach(java.util.function.Consumer<? super T>);
     method public abstract void forEachOrdered(java.util.function.Consumer<? super T>);
-    method public static java.util.stream.Stream<T> generate(java.util.function.Supplier<T>);
-    method public static java.util.stream.Stream<T> iterate(T, java.util.function.UnaryOperator<T>);
+    method public static <T> java.util.stream.Stream<T> generate(java.util.function.Supplier<T>);
+    method public static <T> java.util.stream.Stream<T> iterate(T, java.util.function.UnaryOperator<T>);
     method public abstract java.util.stream.Stream<T> limit(long);
-    method public abstract java.util.stream.Stream<R> map(java.util.function.Function<? super T, ? extends R>);
+    method public abstract <R> java.util.stream.Stream<R> map(java.util.function.Function<? super T, ? extends R>);
     method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.ToDoubleFunction<? super T>);
     method public abstract java.util.stream.IntStream mapToInt(java.util.function.ToIntFunction<? super T>);
     method public abstract java.util.stream.LongStream mapToLong(java.util.function.ToLongFunction<? super T>);
     method public abstract java.util.Optional<T> max(java.util.Comparator<? super T>);
     method public abstract java.util.Optional<T> min(java.util.Comparator<? super T>);
     method public abstract boolean noneMatch(java.util.function.Predicate<? super T>);
-    method public static java.util.stream.Stream<T> of(T);
-    method public static java.util.stream.Stream<T> of(T...);
+    method public static <T> java.util.stream.Stream<T> of(T);
+    method public static <T> java.util.stream.Stream<T> of(T...);
     method public abstract java.util.stream.Stream<T> peek(java.util.function.Consumer<? super T>);
     method public abstract T reduce(T, java.util.function.BinaryOperator<T>);
     method public abstract java.util.Optional<T> reduce(java.util.function.BinaryOperator<T>);
-    method public abstract U reduce(U, java.util.function.BiFunction<U, ? super T, U>, java.util.function.BinaryOperator<U>);
+    method public abstract <U> U reduce(U, java.util.function.BiFunction<U, ? super T, U>, java.util.function.BinaryOperator<U>);
     method public abstract java.util.stream.Stream<T> skip(long);
     method public abstract java.util.stream.Stream<T> sorted();
     method public abstract java.util.stream.Stream<T> sorted(java.util.Comparator<? super T>);
     method public abstract java.lang.Object[] toArray();
-    method public abstract A[] toArray(java.util.function.IntFunction<A[]>);
+    method public abstract <A> A[] toArray(java.util.function.IntFunction<A[]>);
   }
 
-  public static abstract interface Stream.Builder implements java.util.function.Consumer {
+  public static abstract interface Stream.Builder<T> implements java.util.function.Consumer {
     method public abstract void accept(T);
     method public default java.util.stream.Stream.Builder<T> add(T);
     method public abstract java.util.stream.Stream<T> build();
@@ -62981,8 +62976,8 @@
     method public static java.util.stream.IntStream intStream(java.util.function.Supplier<? extends java.util.Spliterator.OfInt>, int, boolean);
     method public static java.util.stream.LongStream longStream(java.util.Spliterator.OfLong, boolean);
     method public static java.util.stream.LongStream longStream(java.util.function.Supplier<? extends java.util.Spliterator.OfLong>, int, boolean);
-    method public static java.util.stream.Stream<T> stream(java.util.Spliterator<T>, boolean);
-    method public static java.util.stream.Stream<T> stream(java.util.function.Supplier<? extends java.util.Spliterator<T>>, int, boolean);
+    method public static <T> java.util.stream.Stream<T> stream(java.util.Spliterator<T>, boolean);
+    method public static <T> java.util.stream.Stream<T> stream(java.util.function.Supplier<? extends java.util.Spliterator<T>>, int, boolean);
   }
 
 }
@@ -65155,16 +65150,16 @@
   public final class Subject implements java.io.Serializable {
     ctor public Subject();
     ctor public Subject(boolean, java.util.Set<? extends java.security.Principal>, java.util.Set<?>, java.util.Set<?>);
-    method public static T doAs(javax.security.auth.Subject, java.security.PrivilegedAction<T>);
-    method public static T doAs(javax.security.auth.Subject, java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
-    method public static T doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedAction<T>, java.security.AccessControlContext);
-    method public static T doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedExceptionAction<T>, java.security.AccessControlContext) throws java.security.PrivilegedActionException;
+    method public static <T> T doAs(javax.security.auth.Subject, java.security.PrivilegedAction<T>);
+    method public static <T> T doAs(javax.security.auth.Subject, java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
+    method public static <T> T doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedAction<T>, java.security.AccessControlContext);
+    method public static <T> T doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedExceptionAction<T>, java.security.AccessControlContext) throws java.security.PrivilegedActionException;
     method public java.util.Set<java.security.Principal> getPrincipals();
-    method public java.util.Set<T> getPrincipals(java.lang.Class<T>);
+    method public <T extends java.security.Principal> java.util.Set<T> getPrincipals(java.lang.Class<T>);
     method public java.util.Set<java.lang.Object> getPrivateCredentials();
-    method public java.util.Set<T> getPrivateCredentials(java.lang.Class<T>);
+    method public <T> java.util.Set<T> getPrivateCredentials(java.lang.Class<T>);
     method public java.util.Set<java.lang.Object> getPublicCredentials();
-    method public java.util.Set<T> getPublicCredentials(java.lang.Class<T>);
+    method public <T> java.util.Set<T> getPublicCredentials(java.lang.Class<T>);
     method public static javax.security.auth.Subject getSubject(java.security.AccessControlContext);
     method public boolean isReadOnly();
     method public void setReadOnly();
diff --git a/api/removed.txt b/api/removed.txt
index 239eab6..683a695 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -167,6 +167,13 @@
 
 package android.net {
 
+  public abstract class PskKeyManager {
+    ctor public PskKeyManager();
+    field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
+    field public static final int MAX_IDENTITY_LENGTH_BYTES = 128; // 0x80
+    field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100
+  }
+
   public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
     method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index ca1c61d..1ab4884 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3036,11 +3036,11 @@
     field public static final java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
   }
 
-  public abstract interface AccountManagerCallback {
+  public abstract interface AccountManagerCallback<V> {
     method public abstract void run(android.accounts.AccountManagerFuture<V>);
   }
 
-  public abstract interface AccountManagerFuture {
+  public abstract interface AccountManagerFuture<V> {
     method public abstract boolean cancel(boolean);
     method public abstract V getResult() throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
     method public abstract V getResult(long, java.util.concurrent.TimeUnit) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
@@ -3186,7 +3186,7 @@
     method public java.lang.Object evaluate(float, java.lang.Object, java.lang.Object);
   }
 
-  public abstract class BidirectionalTypeConverter extends android.animation.TypeConverter {
+  public abstract class BidirectionalTypeConverter<T, V> extends android.animation.TypeConverter {
     ctor public BidirectionalTypeConverter(java.lang.Class<T>, java.lang.Class<V>);
     method public abstract T convertBack(V);
     method public android.animation.BidirectionalTypeConverter<V, T> invert();
@@ -3278,26 +3278,26 @@
     method public java.lang.String getPropertyName();
     method public java.lang.Object getTarget();
     method public static android.animation.ObjectAnimator ofArgb(java.lang.Object, java.lang.String, int...);
-    method public static android.animation.ObjectAnimator ofArgb(T, android.util.Property<T, java.lang.Integer>, int...);
+    method public static <T> android.animation.ObjectAnimator ofArgb(T, android.util.Property<T, java.lang.Integer>, int...);
     method public static android.animation.ObjectAnimator ofFloat(java.lang.Object, java.lang.String, float...);
     method public static android.animation.ObjectAnimator ofFloat(java.lang.Object, java.lang.String, java.lang.String, android.graphics.Path);
-    method public static android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, float...);
-    method public static android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, android.util.Property<T, java.lang.Float>, android.graphics.Path);
+    method public static <T> android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, float...);
+    method public static <T> android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, android.util.Property<T, java.lang.Float>, android.graphics.Path);
     method public static android.animation.ObjectAnimator ofInt(java.lang.Object, java.lang.String, int...);
     method public static android.animation.ObjectAnimator ofInt(java.lang.Object, java.lang.String, java.lang.String, android.graphics.Path);
-    method public static android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, int...);
-    method public static android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, android.util.Property<T, java.lang.Integer>, android.graphics.Path);
+    method public static <T> android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, int...);
+    method public static <T> android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, android.util.Property<T, java.lang.Integer>, android.graphics.Path);
     method public static android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, float[][]);
     method public static android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, android.graphics.Path);
-    method public static android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, android.animation.TypeConverter<T, float[]>, android.animation.TypeEvaluator<T>, T...);
+    method public static <T> android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, android.animation.TypeConverter<T, float[]>, android.animation.TypeEvaluator<T>, T...);
     method public static android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, int[][]);
     method public static android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, android.graphics.Path);
-    method public static android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, android.animation.TypeConverter<T, int[]>, android.animation.TypeEvaluator<T>, T...);
+    method public static <T> android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, android.animation.TypeConverter<T, int[]>, android.animation.TypeEvaluator<T>, T...);
     method public static android.animation.ObjectAnimator ofObject(java.lang.Object, java.lang.String, android.animation.TypeEvaluator, java.lang.Object...);
     method public static android.animation.ObjectAnimator ofObject(java.lang.Object, java.lang.String, android.animation.TypeConverter<android.graphics.PointF, ?>, android.graphics.Path);
-    method public static android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeEvaluator<V>, V...);
-    method public static android.animation.ObjectAnimator ofObject(T, android.util.Property<T, P>, android.animation.TypeConverter<V, P>, android.animation.TypeEvaluator<V>, V...);
-    method public static android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeConverter<android.graphics.PointF, V>, android.graphics.Path);
+    method public static <T, V> android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeEvaluator<V>, V...);
+    method public static <T, V, P> android.animation.ObjectAnimator ofObject(T, android.util.Property<T, P>, android.animation.TypeConverter<V, P>, android.animation.TypeEvaluator<V>, V...);
+    method public static <T, V> android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeConverter<android.graphics.PointF, V>, android.graphics.Path);
     method public static android.animation.ObjectAnimator ofPropertyValuesHolder(java.lang.Object, android.animation.PropertyValuesHolder...);
     method public void setAutoCancel(boolean);
     method public void setProperty(android.util.Property);
@@ -3321,17 +3321,17 @@
     method public static android.animation.PropertyValuesHolder ofKeyframe(android.util.Property, android.animation.Keyframe...);
     method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, float[][]);
     method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.graphics.Path);
-    method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter<V, float[]>, android.animation.TypeEvaluator<V>, V...);
-    method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter<T, float[]>, android.animation.TypeEvaluator<T>, android.animation.Keyframe...);
+    method public static <V> android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter<V, float[]>, android.animation.TypeEvaluator<V>, V...);
+    method public static <T> android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter<T, float[]>, android.animation.TypeEvaluator<T>, android.animation.Keyframe...);
     method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, int[][]);
     method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.graphics.Path);
-    method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter<V, int[]>, android.animation.TypeEvaluator<V>, V...);
-    method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter<T, int[]>, android.animation.TypeEvaluator<T>, android.animation.Keyframe...);
+    method public static <V> android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter<V, int[]>, android.animation.TypeEvaluator<V>, V...);
+    method public static <T> android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter<T, int[]>, android.animation.TypeEvaluator<T>, android.animation.Keyframe...);
     method public static android.animation.PropertyValuesHolder ofObject(java.lang.String, android.animation.TypeEvaluator, java.lang.Object...);
     method public static android.animation.PropertyValuesHolder ofObject(java.lang.String, android.animation.TypeConverter<android.graphics.PointF, ?>, android.graphics.Path);
-    method public static android.animation.PropertyValuesHolder ofObject(android.util.Property, android.animation.TypeEvaluator<V>, V...);
-    method public static android.animation.PropertyValuesHolder ofObject(android.util.Property<?, V>, android.animation.TypeConverter<T, V>, android.animation.TypeEvaluator<T>, T...);
-    method public static android.animation.PropertyValuesHolder ofObject(android.util.Property<?, V>, android.animation.TypeConverter<android.graphics.PointF, V>, android.graphics.Path);
+    method public static <V> android.animation.PropertyValuesHolder ofObject(android.util.Property, android.animation.TypeEvaluator<V>, V...);
+    method public static <T, V> android.animation.PropertyValuesHolder ofObject(android.util.Property<?, V>, android.animation.TypeConverter<T, V>, android.animation.TypeEvaluator<T>, T...);
+    method public static <V> android.animation.PropertyValuesHolder ofObject(android.util.Property<?, V>, android.animation.TypeConverter<android.graphics.PointF, V>, android.graphics.Path);
     method public void setConverter(android.animation.TypeConverter);
     method public void setEvaluator(android.animation.TypeEvaluator);
     method public void setFloatValues(float...);
@@ -3368,12 +3368,12 @@
     method public abstract float getInterpolation(float);
   }
 
-  public abstract class TypeConverter {
+  public abstract class TypeConverter<T, V> {
     ctor public TypeConverter(java.lang.Class<T>, java.lang.Class<V>);
     method public abstract V convert(T);
   }
 
-  public abstract interface TypeEvaluator {
+  public abstract interface TypeEvaluator<T> {
     method public abstract T evaluate(float, T, T);
   }
 
@@ -4172,6 +4172,7 @@
     field public static final java.lang.String OPSTR_MOCK_LOCATION = "android:mock_location";
     field public static final java.lang.String OPSTR_MONITOR_HIGH_POWER_LOCATION = "android:monitor_location_high_power";
     field public static final java.lang.String OPSTR_MONITOR_LOCATION = "android:monitor_location";
+    field public static final java.lang.String OPSTR_PROCESS_OUTGOING_CALLS = "android:process_outgoing_calls";
     field public static final java.lang.String OPSTR_READ_CALENDAR = "android:read_calendar";
     field public static final java.lang.String OPSTR_READ_CALL_LOG = "android:read_call_log";
     field public static final java.lang.String OPSTR_READ_CELL_BROADCASTS = "android:read_cell_broadcasts";
@@ -4733,7 +4734,7 @@
     method public android.os.Parcelable saveAllState();
   }
 
-  public abstract class FragmentHostCallback extends android.app.FragmentContainer {
+  public abstract class FragmentHostCallback<E> extends android.app.FragmentContainer {
     ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
     method public void onAttachFragment(android.app.Fragment);
     method public void onDump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
@@ -5000,12 +5001,12 @@
     method public abstract void destroyLoader(int);
     method public abstract void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
     method public static void enableDebugLogging(boolean);
-    method public abstract android.content.Loader<D> getLoader(int);
-    method public abstract android.content.Loader<D> initLoader(int, android.os.Bundle, android.app.LoaderManager.LoaderCallbacks<D>);
-    method public abstract android.content.Loader<D> restartLoader(int, android.os.Bundle, android.app.LoaderManager.LoaderCallbacks<D>);
+    method public abstract <D> android.content.Loader<D> getLoader(int);
+    method public abstract <D> android.content.Loader<D> initLoader(int, android.os.Bundle, android.app.LoaderManager.LoaderCallbacks<D>);
+    method public abstract <D> android.content.Loader<D> restartLoader(int, android.os.Bundle, android.app.LoaderManager.LoaderCallbacks<D>);
   }
 
-  public static abstract interface LoaderManager.LoaderCallbacks {
+  public static abstract interface LoaderManager.LoaderCallbacks<D> {
     method public abstract android.content.Loader<D> onCreateLoader(int, android.os.Bundle);
     method public abstract void onLoadFinished(android.content.Loader<D>, D);
     method public abstract void onLoaderReset(android.content.Loader<D>);
@@ -7998,7 +7999,7 @@
     ctor public AsyncQueryHandler.WorkerHandler(android.os.Looper);
   }
 
-  public abstract class AsyncTaskLoader extends android.content.Loader {
+  public abstract class AsyncTaskLoader<D> extends android.content.Loader {
     ctor public AsyncTaskLoader(android.content.Context);
     method public void cancelLoadInBackground();
     method public boolean isLoadInBackgroundCanceled();
@@ -8180,7 +8181,7 @@
     method public android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
     method public android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method protected final android.os.ParcelFileDescriptor openFileHelper(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
-    method public android.os.ParcelFileDescriptor openPipeHelper(android.net.Uri, java.lang.String, android.os.Bundle, T, android.content.ContentProvider.PipeDataWriter<T>) throws java.io.FileNotFoundException;
+    method public <T> android.os.ParcelFileDescriptor openPipeHelper(android.net.Uri, java.lang.String, android.os.Bundle, T, android.content.ContentProvider.PipeDataWriter<T>) throws java.io.FileNotFoundException;
     method public android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle) throws java.io.FileNotFoundException;
     method public android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public abstract android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
@@ -8193,7 +8194,7 @@
     method public abstract int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
   }
 
-  public static abstract interface ContentProvider.PipeDataWriter {
+  public static abstract interface ContentProvider.PipeDataWriter<T> {
     method public abstract void writeDataToPipe(android.os.ParcelFileDescriptor, android.net.Uri, java.lang.String, android.os.Bundle, T);
   }
 
@@ -8466,7 +8467,7 @@
     method public final java.lang.String getString(int);
     method public final java.lang.String getString(int, java.lang.Object...);
     method public abstract java.lang.Object getSystemService(java.lang.String);
-    method public final T getSystemService(java.lang.Class<T>);
+    method public final <T> T getSystemService(java.lang.Class<T>);
     method public abstract java.lang.String getSystemServiceName(java.lang.Class<?>);
     method public final java.lang.CharSequence getText(int);
     method public abstract android.content.res.Resources.Theme getTheme();
@@ -8837,8 +8838,8 @@
     method public long getLongExtra(java.lang.String, long);
     method public java.lang.String getPackage();
     method public android.os.Parcelable[] getParcelableArrayExtra(java.lang.String);
-    method public java.util.ArrayList<T> getParcelableArrayListExtra(java.lang.String);
-    method public T getParcelableExtra(java.lang.String);
+    method public <T extends android.os.Parcelable> java.util.ArrayList<T> getParcelableArrayListExtra(java.lang.String);
+    method public <T extends android.os.Parcelable> T getParcelableExtra(java.lang.String);
     method public java.lang.String getScheme();
     method public android.content.Intent getSelector();
     method public java.io.Serializable getSerializableExtra(java.lang.String);
@@ -9325,7 +9326,7 @@
     ctor public IntentSender.SendIntentException(java.lang.Exception);
   }
 
-  public class Loader {
+  public class Loader<D> {
     ctor public Loader(android.content.Context);
     method public void abandon();
     method public boolean cancelLoad();
@@ -9362,11 +9363,11 @@
     ctor public Loader.ForceLoadContentObserver();
   }
 
-  public static abstract interface Loader.OnLoadCanceledListener {
+  public static abstract interface Loader.OnLoadCanceledListener<D> {
     method public abstract void onLoadCanceled(android.content.Loader<D>);
   }
 
-  public static abstract interface Loader.OnLoadCompleteListener {
+  public static abstract interface Loader.OnLoadCompleteListener<D> {
     method public abstract void onLoadComplete(android.content.Loader<D>, D);
   }
 
@@ -11335,7 +11336,7 @@
     method public boolean isNull(int);
   }
 
-  public abstract class Observable {
+  public abstract class Observable<T> {
     ctor public Observable();
     method public void registerObserver(T);
     method public void unregisterAll();
@@ -13140,6 +13141,7 @@
   public class SurfaceTexture {
     ctor public SurfaceTexture(int);
     ctor public SurfaceTexture(int, boolean);
+    ctor public SurfaceTexture(boolean);
     method public void attachToGLContext(int);
     method public void detachFromGLContext();
     method public long getTimestamp();
@@ -13226,7 +13228,7 @@
   public class AnimatedStateListDrawable extends android.graphics.drawable.StateListDrawable {
     ctor public AnimatedStateListDrawable();
     method public void addState(int[], android.graphics.drawable.Drawable, int);
-    method public void addTransition(int, int, T, boolean);
+    method public <T extends android.graphics.drawable.Drawable & android.graphics.drawable.Animatable> void addTransition(int, int, T, boolean);
   }
 
   public class AnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable2 {
@@ -14359,7 +14361,7 @@
   }
 
   public final class CameraCharacteristics extends android.hardware.camera2.CameraMetadata {
-    method public T get(android.hardware.camera2.CameraCharacteristics.Key<T>);
+    method public <T> T get(android.hardware.camera2.CameraCharacteristics.Key<T>);
     method public java.util.List<android.hardware.camera2.CaptureRequest.Key<?>> getAvailableCaptureRequestKeys();
     method public java.util.List<android.hardware.camera2.CaptureResult.Key<?>> getAvailableCaptureResultKeys();
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES;
@@ -14444,7 +14446,7 @@
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> TONEMAP_MAX_CURVE_POINTS;
   }
 
-  public static final class CameraCharacteristics.Key {
+  public static final class CameraCharacteristics.Key<T> {
     method public final boolean equals(java.lang.Object);
     method public java.lang.String getName();
     method public final int hashCode();
@@ -14509,7 +14511,7 @@
     method public void onTorchModeUnavailable(java.lang.String);
   }
 
-  public abstract class CameraMetadata {
+  public abstract class CameraMetadata<TKey> {
     method public java.util.List<TKey> getKeys();
     field public static final int COLOR_CORRECTION_ABERRATION_MODE_FAST = 1; // 0x1
     field public static final int COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY = 2; // 0x2
@@ -14717,7 +14719,7 @@
 
   public final class CaptureRequest extends android.hardware.camera2.CameraMetadata implements android.os.Parcelable {
     method public int describeContents();
-    method public T get(android.hardware.camera2.CaptureRequest.Key<T>);
+    method public <T> T get(android.hardware.camera2.CaptureRequest.Key<T>);
     method public java.lang.Object getTag();
     method public boolean isReprocess();
     method public void writeToParcel(android.os.Parcel, int);
@@ -14780,20 +14782,20 @@
   public static final class CaptureRequest.Builder {
     method public void addTarget(android.view.Surface);
     method public android.hardware.camera2.CaptureRequest build();
-    method public T get(android.hardware.camera2.CaptureRequest.Key<T>);
+    method public <T> T get(android.hardware.camera2.CaptureRequest.Key<T>);
     method public void removeTarget(android.view.Surface);
-    method public void set(android.hardware.camera2.CaptureRequest.Key<T>, T);
+    method public <T> void set(android.hardware.camera2.CaptureRequest.Key<T>, T);
     method public void setTag(java.lang.Object);
   }
 
-  public static final class CaptureRequest.Key {
+  public static final class CaptureRequest.Key<T> {
     method public final boolean equals(java.lang.Object);
     method public java.lang.String getName();
     method public final int hashCode();
   }
 
   public class CaptureResult extends android.hardware.camera2.CameraMetadata {
-    method public T get(android.hardware.camera2.CaptureResult.Key<T>);
+    method public <T> T get(android.hardware.camera2.CaptureResult.Key<T>);
     method public long getFrameNumber();
     method public android.hardware.camera2.CaptureRequest getRequest();
     method public int getSequenceId();
@@ -14874,7 +14876,7 @@
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> TONEMAP_PRESET_CURVE;
   }
 
-  public static final class CaptureResult.Key {
+  public static final class CaptureResult.Key<T> {
     method public final boolean equals(java.lang.Object);
     method public java.lang.String getName();
     method public final int hashCode();
@@ -15008,14 +15010,14 @@
     method public android.util.Size[] getInputSizes(int);
     method public final int[] getOutputFormats();
     method public long getOutputMinFrameDuration(int, android.util.Size);
-    method public long getOutputMinFrameDuration(java.lang.Class<T>, android.util.Size);
-    method public android.util.Size[] getOutputSizes(java.lang.Class<T>);
+    method public <T> long getOutputMinFrameDuration(java.lang.Class<T>, android.util.Size);
+    method public <T> android.util.Size[] getOutputSizes(java.lang.Class<T>);
     method public android.util.Size[] getOutputSizes(int);
     method public long getOutputStallDuration(int, android.util.Size);
-    method public long getOutputStallDuration(java.lang.Class<T>, android.util.Size);
+    method public <T> long getOutputStallDuration(java.lang.Class<T>, android.util.Size);
     method public final int[] getValidOutputFormatsForInput(int);
     method public boolean isOutputSupportedFor(int);
-    method public static boolean isOutputSupportedFor(java.lang.Class<T>);
+    method public static <T> boolean isOutputSupportedFor(java.lang.Class<T>);
     method public boolean isOutputSupportedFor(android.view.Surface);
   }
 
@@ -17464,7 +17466,7 @@
 
 package android.icu.text {
 
-  public final class AlphabeticIndex implements java.lang.Iterable {
+  public final class AlphabeticIndex<V> implements java.lang.Iterable {
     ctor public AlphabeticIndex(android.icu.util.ULocale);
     ctor public AlphabeticIndex(java.util.Locale);
     ctor public AlphabeticIndex(android.icu.text.RuleBasedCollator);
@@ -17490,7 +17492,7 @@
     method public android.icu.text.AlphabeticIndex<V> setUnderflowLabel(java.lang.String);
   }
 
-  public static class AlphabeticIndex.Bucket implements java.lang.Iterable {
+  public static class AlphabeticIndex.Bucket<V> implements java.lang.Iterable {
     method public java.lang.String getLabel();
     method public android.icu.text.AlphabeticIndex.Bucket.LabelType getLabelType();
     method public java.util.Iterator<android.icu.text.AlphabeticIndex.Record<V>> iterator();
@@ -17506,14 +17508,14 @@
     enum_constant public static final android.icu.text.AlphabeticIndex.Bucket.LabelType UNDERFLOW;
   }
 
-  public static final class AlphabeticIndex.ImmutableIndex implements java.lang.Iterable {
+  public static final class AlphabeticIndex.ImmutableIndex<V> implements java.lang.Iterable {
     method public android.icu.text.AlphabeticIndex.Bucket<V> getBucket(int);
     method public int getBucketCount();
     method public int getBucketIndex(java.lang.CharSequence);
     method public java.util.Iterator<android.icu.text.AlphabeticIndex.Bucket<V>> iterator();
   }
 
-  public static class AlphabeticIndex.Record {
+  public static class AlphabeticIndex.Record<V> {
     method public V getData();
     method public java.lang.CharSequence getName();
   }
@@ -19026,8 +19028,8 @@
     method public final android.icu.text.UnicodeSet addAll(java.lang.CharSequence);
     method public android.icu.text.UnicodeSet addAll(android.icu.text.UnicodeSet);
     method public android.icu.text.UnicodeSet addAll(java.lang.Iterable<?>);
-    method public android.icu.text.UnicodeSet addAll(T...);
-    method public T addAllTo(T);
+    method public <T extends java.lang.CharSequence> android.icu.text.UnicodeSet addAll(T...);
+    method public <T extends java.util.Collection<java.lang.String>> T addAllTo(T);
     method public void addMatchSetTo(android.icu.text.UnicodeSet);
     method public android.icu.text.UnicodeSet applyIntPropertyValue(int, int);
     method public final android.icu.text.UnicodeSet applyPattern(java.lang.String);
@@ -19055,15 +19057,15 @@
     method public final boolean contains(java.lang.CharSequence);
     method public boolean containsAll(android.icu.text.UnicodeSet);
     method public boolean containsAll(java.lang.String);
-    method public boolean containsAll(java.lang.Iterable<T>);
+    method public <T extends java.lang.CharSequence> boolean containsAll(java.lang.Iterable<T>);
     method public boolean containsNone(int, int);
     method public boolean containsNone(android.icu.text.UnicodeSet);
     method public boolean containsNone(java.lang.CharSequence);
-    method public boolean containsNone(java.lang.Iterable<T>);
+    method public <T extends java.lang.CharSequence> boolean containsNone(java.lang.Iterable<T>);
     method public final boolean containsSome(int, int);
     method public final boolean containsSome(android.icu.text.UnicodeSet);
     method public final boolean containsSome(java.lang.CharSequence);
-    method public final boolean containsSome(java.lang.Iterable<T>);
+    method public final <T extends java.lang.CharSequence> boolean containsSome(java.lang.Iterable<T>);
     method public android.icu.text.UnicodeSet freeze();
     method public static android.icu.text.UnicodeSet from(java.lang.CharSequence);
     method public static android.icu.text.UnicodeSet fromAll(java.lang.CharSequence);
@@ -19081,14 +19083,14 @@
     method public final android.icu.text.UnicodeSet remove(java.lang.CharSequence);
     method public final android.icu.text.UnicodeSet removeAll(java.lang.CharSequence);
     method public android.icu.text.UnicodeSet removeAll(android.icu.text.UnicodeSet);
-    method public android.icu.text.UnicodeSet removeAll(java.lang.Iterable<T>);
+    method public <T extends java.lang.CharSequence> android.icu.text.UnicodeSet removeAll(java.lang.Iterable<T>);
     method public final android.icu.text.UnicodeSet removeAllStrings();
     method public android.icu.text.UnicodeSet retain(int, int);
     method public final android.icu.text.UnicodeSet retain(int);
     method public final android.icu.text.UnicodeSet retain(java.lang.CharSequence);
     method public final android.icu.text.UnicodeSet retainAll(java.lang.CharSequence);
     method public android.icu.text.UnicodeSet retainAll(android.icu.text.UnicodeSet);
-    method public android.icu.text.UnicodeSet retainAll(java.lang.Iterable<T>);
+    method public <T extends java.lang.CharSequence> android.icu.text.UnicodeSet retainAll(java.lang.Iterable<T>);
     method public android.icu.text.UnicodeSet set(int, int);
     method public android.icu.text.UnicodeSet set(android.icu.text.UnicodeSet);
     method public int size();
@@ -19498,7 +19500,7 @@
     method public long getToDate();
   }
 
-  public abstract interface Freezable implements java.lang.Cloneable {
+  public abstract interface Freezable<T> implements java.lang.Cloneable {
     method public abstract T cloneAsThawed();
     method public abstract T freeze();
     method public abstract boolean isFrozen();
@@ -19780,7 +19782,7 @@
     field public static final android.icu.util.TimeUnit YEAR;
   }
 
-  public class Output {
+  public class Output<T> {
     ctor public Output();
     ctor public Output(T);
     field public T value;
@@ -25756,19 +25758,6 @@
     field public static final android.os.Parcelable.Creator<android.net.ProxyInfo> CREATOR;
   }
 
-  public abstract class PskKeyManager {
-    ctor public PskKeyManager();
-    method public java.lang.String chooseClientKeyIdentity(java.lang.String, java.net.Socket);
-    method public java.lang.String chooseClientKeyIdentity(java.lang.String, javax.net.ssl.SSLEngine);
-    method public java.lang.String chooseServerKeyIdentityHint(java.net.Socket);
-    method public java.lang.String chooseServerKeyIdentityHint(javax.net.ssl.SSLEngine);
-    method public javax.crypto.SecretKey getKey(java.lang.String, java.lang.String, java.net.Socket);
-    method public javax.crypto.SecretKey getKey(java.lang.String, java.lang.String, javax.net.ssl.SSLEngine);
-    field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
-    field public static final int MAX_IDENTITY_LENGTH_BYTES = 128; // 0x80
-    field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100
-  }
-
   public final class RouteInfo implements android.os.Parcelable {
     method public int describeContents();
     method public android.net.IpPrefix getDestination();
@@ -30754,7 +30743,7 @@
 
 package android.os {
 
-  public abstract class AsyncTask {
+  public abstract class AsyncTask<Params, Progress, Result> {
     ctor public AsyncTask();
     method public final boolean cancel(boolean);
     method protected abstract Result doInBackground(Params...);
@@ -30984,16 +30973,16 @@
     method public float getFloat(java.lang.String, float);
     method public float[] getFloatArray(java.lang.String);
     method public java.util.ArrayList<java.lang.Integer> getIntegerArrayList(java.lang.String);
-    method public T getParcelable(java.lang.String);
+    method public <T extends android.os.Parcelable> T getParcelable(java.lang.String);
     method public android.os.Parcelable[] getParcelableArray(java.lang.String);
-    method public java.util.ArrayList<T> getParcelableArrayList(java.lang.String);
+    method public <T extends android.os.Parcelable> java.util.ArrayList<T> getParcelableArrayList(java.lang.String);
     method public java.io.Serializable getSerializable(java.lang.String);
     method public short getShort(java.lang.String);
     method public short getShort(java.lang.String, short);
     method public short[] getShortArray(java.lang.String);
     method public android.util.Size getSize(java.lang.String);
     method public android.util.SizeF getSizeF(java.lang.String);
-    method public android.util.SparseArray<T> getSparseParcelableArray(java.lang.String);
+    method public <T extends android.os.Parcelable> android.util.SparseArray<T> getSparseParcelableArray(java.lang.String);
     method public java.util.ArrayList<java.lang.String> getStringArrayList(java.lang.String);
     method public boolean hasFileDescriptors();
     method public void putAll(android.os.Bundle);
@@ -31498,8 +31487,8 @@
     method public final long[] createLongArray();
     method public final java.lang.String[] createStringArray();
     method public final java.util.ArrayList<java.lang.String> createStringArrayList();
-    method public final T[] createTypedArray(android.os.Parcelable.Creator<T>);
-    method public final java.util.ArrayList<T> createTypedArrayList(android.os.Parcelable.Creator<T>);
+    method public final <T> T[] createTypedArray(android.os.Parcelable.Creator<T>);
+    method public final <T> java.util.ArrayList<T> createTypedArrayList(android.os.Parcelable.Creator<T>);
     method public final int dataAvail();
     method public final int dataCapacity();
     method public final int dataPosition();
@@ -31532,7 +31521,7 @@
     method public final long readLong();
     method public final void readLongArray(long[]);
     method public final void readMap(java.util.Map, java.lang.ClassLoader);
-    method public final T readParcelable(java.lang.ClassLoader);
+    method public final <T extends android.os.Parcelable> T readParcelable(java.lang.ClassLoader);
     method public final android.os.Parcelable[] readParcelableArray(java.lang.ClassLoader);
     method public final android.os.PersistableBundle readPersistableBundle();
     method public final android.os.PersistableBundle readPersistableBundle(java.lang.ClassLoader);
@@ -31545,9 +31534,9 @@
     method public final void readStringArray(java.lang.String[]);
     method public final void readStringList(java.util.List<java.lang.String>);
     method public final android.os.IBinder readStrongBinder();
-    method public final void readTypedArray(T[], android.os.Parcelable.Creator<T>);
-    method public final void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>);
-    method public final T readTypedObject(android.os.Parcelable.Creator<T>);
+    method public final <T> void readTypedArray(T[], android.os.Parcelable.Creator<T>);
+    method public final <T> void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>);
+    method public final <T> T readTypedObject(android.os.Parcelable.Creator<T>);
     method public final java.lang.Object readValue(java.lang.ClassLoader);
     method public final void recycle();
     method public final void setDataCapacity(int);
@@ -31578,7 +31567,7 @@
     method public final void writeMap(java.util.Map);
     method public final void writeNoException();
     method public final void writeParcelable(android.os.Parcelable, int);
-    method public final void writeParcelableArray(T[], int);
+    method public final <T extends android.os.Parcelable> void writeParcelableArray(T[], int);
     method public final void writePersistableBundle(android.os.PersistableBundle);
     method public final void writeSerializable(java.io.Serializable);
     method public final void writeSize(android.util.Size);
@@ -31590,9 +31579,9 @@
     method public final void writeStringList(java.util.List<java.lang.String>);
     method public final void writeStrongBinder(android.os.IBinder);
     method public final void writeStrongInterface(android.os.IInterface);
-    method public final void writeTypedArray(T[], int);
-    method public final void writeTypedList(java.util.List<T>);
-    method public final void writeTypedObject(T, int);
+    method public final <T extends android.os.Parcelable> void writeTypedArray(T[], int);
+    method public final <T extends android.os.Parcelable> void writeTypedList(java.util.List<T>);
+    method public final <T extends android.os.Parcelable> void writeTypedObject(T, int);
     method public final void writeValue(java.lang.Object);
     field public static final android.os.Parcelable.Creator<java.lang.String> STRING_CREATOR;
   }
@@ -31670,11 +31659,11 @@
     field public static final int PARCELABLE_WRITE_RETURN_VALUE = 1; // 0x1
   }
 
-  public static abstract interface Parcelable.ClassLoaderCreator implements android.os.Parcelable.Creator {
+  public static abstract interface Parcelable.ClassLoaderCreator<T> implements android.os.Parcelable.Creator {
     method public abstract T createFromParcel(android.os.Parcel, java.lang.ClassLoader);
   }
 
-  public static abstract interface Parcelable.Creator {
+  public static abstract interface Parcelable.Creator<T> {
     method public abstract T createFromParcel(android.os.Parcel);
     method public abstract T[] newArray(int);
   }
@@ -31817,7 +31806,7 @@
     method public abstract void onResult(android.os.Bundle);
   }
 
-  public class RemoteCallbackList {
+  public class RemoteCallbackList<E extends android.os.IInterface> {
     ctor public RemoteCallbackList();
     method public int beginBroadcast();
     method public void finishBroadcast();
@@ -37384,7 +37373,7 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.carrier.CarrierMessagingService";
   }
 
-  public static abstract interface CarrierMessagingService.ResultCallback {
+  public static abstract interface CarrierMessagingService.ResultCallback<T> {
     method public abstract void onReceiveResult(T) throws android.os.RemoteException;
   }
 
@@ -37536,7 +37525,7 @@
     field public static final java.lang.String EXTRA_SUGGESTION_KEYWORDS = "android.service.media.extra.SUGGESTION_KEYWORDS";
   }
 
-  public class MediaBrowserService.Result {
+  public class MediaBrowserService.Result<T> {
     method public void detach();
     method public void sendResult(T);
   }
@@ -40018,6 +40007,7 @@
     field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
     field public static final java.lang.String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT = "duration_blocking_disabled_after_emergency_int";
     field public static final java.lang.String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool";
+    field public static final java.lang.String KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL = "editable_voicemail_number_bool";
     field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_key_vibration_bool";
     field public static final java.lang.String KEY_FORCE_HOME_NETWORK_BOOL = "force_home_network_bool";
     field public static final java.lang.String KEY_GSM_DTMF_TONE_DELAY_INT = "gsm_dtmf_tone_delay_int";
@@ -40872,14 +40862,14 @@
 
 package android.test {
 
-  public abstract deprecated class ActivityInstrumentationTestCase extends android.test.ActivityTestCase {
+  public abstract deprecated class ActivityInstrumentationTestCase<T extends android.app.Activity> extends android.test.ActivityTestCase {
     ctor public ActivityInstrumentationTestCase(java.lang.String, java.lang.Class<T>);
     ctor public ActivityInstrumentationTestCase(java.lang.String, java.lang.Class<T>, boolean);
     method public T getActivity();
     method public void testActivityTestCaseSetUpProperly() throws java.lang.Exception;
   }
 
-  public abstract deprecated class ActivityInstrumentationTestCase2 extends android.test.ActivityTestCase {
+  public abstract deprecated class ActivityInstrumentationTestCase2<T extends android.app.Activity> extends android.test.ActivityTestCase {
     ctor public deprecated ActivityInstrumentationTestCase2(java.lang.String, java.lang.Class<T>);
     ctor public ActivityInstrumentationTestCase2(java.lang.Class<T>);
     method public T getActivity();
@@ -40894,7 +40884,7 @@
     method protected void setActivity(android.app.Activity);
   }
 
-  public abstract deprecated class ActivityUnitTestCase extends android.test.ActivityTestCase {
+  public abstract deprecated class ActivityUnitTestCase<T extends android.app.Activity> extends android.test.ActivityTestCase {
     ctor public ActivityUnitTestCase(java.lang.Class<T>);
     method public T getActivity();
     method public int getFinishedActivityRequest();
@@ -40940,7 +40930,7 @@
     method public void testStarted(java.lang.String);
   }
 
-  public abstract deprecated class ApplicationTestCase extends android.test.AndroidTestCase {
+  public abstract deprecated class ApplicationTestCase<T extends android.app.Application> extends android.test.AndroidTestCase {
     ctor public ApplicationTestCase(java.lang.Class<T>);
     method protected final void createApplication();
     method public T getApplication();
@@ -40966,8 +40956,8 @@
     method public android.app.Instrumentation getInstrumentation();
     method public deprecated void injectInsrumentation(android.app.Instrumentation);
     method public void injectInstrumentation(android.app.Instrumentation);
-    method public final T launchActivity(java.lang.String, java.lang.Class<T>, android.os.Bundle);
-    method public final T launchActivityWithIntent(java.lang.String, java.lang.Class<T>, android.content.Intent);
+    method public final <T extends android.app.Activity> T launchActivity(java.lang.String, java.lang.Class<T>, android.os.Bundle);
+    method public final <T extends android.app.Activity> T launchActivityWithIntent(java.lang.String, java.lang.Class<T>, android.content.Intent);
     method public void runTestOnUiThread(java.lang.Runnable) throws java.lang.Throwable;
     method public void sendKeys(java.lang.String);
     method public void sendKeys(int...);
@@ -41007,7 +40997,7 @@
 
   public class LoaderTestCase extends android.test.AndroidTestCase {
     ctor public LoaderTestCase();
-    method public T getLoaderResultSynchronously(android.content.Loader<T>);
+    method public <T> T getLoaderResultSynchronously(android.content.Loader<T>);
   }
 
   public final deprecated class MoreAsserts {
@@ -41062,20 +41052,20 @@
     method public abstract void startTiming(boolean);
   }
 
-  public abstract deprecated class ProviderTestCase extends android.test.InstrumentationTestCase {
+  public abstract deprecated class ProviderTestCase<T extends android.content.ContentProvider> extends android.test.InstrumentationTestCase {
     ctor public ProviderTestCase(java.lang.Class<T>, java.lang.String);
     method public android.test.mock.MockContentResolver getMockContentResolver();
     method public android.test.IsolatedContext getMockContext();
     method public T getProvider();
-    method public static android.content.ContentResolver newResolverWithContentProviderFromSql(android.content.Context, java.lang.Class<T>, java.lang.String, java.lang.String, int, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public static <T extends android.content.ContentProvider> android.content.ContentResolver newResolverWithContentProviderFromSql(android.content.Context, java.lang.Class<T>, java.lang.String, java.lang.String, int, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
   }
 
-  public abstract class ProviderTestCase2 extends android.test.AndroidTestCase {
+  public abstract class ProviderTestCase2<T extends android.content.ContentProvider> extends android.test.AndroidTestCase {
     ctor public ProviderTestCase2(java.lang.Class<T>, java.lang.String);
     method public android.test.mock.MockContentResolver getMockContentResolver();
     method public android.test.IsolatedContext getMockContext();
     method public T getProvider();
-    method public static android.content.ContentResolver newResolverWithContentProviderFromSql(android.content.Context, java.lang.String, java.lang.Class<T>, java.lang.String, java.lang.String, int, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public static <T extends android.content.ContentProvider> android.content.ContentResolver newResolverWithContentProviderFromSql(android.content.Context, java.lang.String, java.lang.Class<T>, java.lang.String, java.lang.String, int, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
   }
 
   public deprecated class RenamingDelegatingContext extends android.content.ContextWrapper {
@@ -41083,11 +41073,11 @@
     ctor public RenamingDelegatingContext(android.content.Context, android.content.Context, java.lang.String);
     method public java.lang.String getDatabasePrefix();
     method public void makeExistingFilesAndDbsAccessible();
-    method public static T providerWithRenamedContext(java.lang.Class<T>, android.content.Context, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
-    method public static T providerWithRenamedContext(java.lang.Class<T>, android.content.Context, java.lang.String, boolean) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public static <T extends android.content.ContentProvider> T providerWithRenamedContext(java.lang.Class<T>, android.content.Context, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public static <T extends android.content.ContentProvider> T providerWithRenamedContext(java.lang.Class<T>, android.content.Context, java.lang.String, boolean) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
   }
 
-  public abstract deprecated class ServiceTestCase extends android.test.AndroidTestCase {
+  public abstract deprecated class ServiceTestCase<T extends android.app.Service> extends android.test.AndroidTestCase {
     ctor public ServiceTestCase(java.lang.Class<T>);
     method protected android.os.IBinder bindService(android.content.Intent);
     method public android.app.Application getApplication();
@@ -41100,7 +41090,7 @@
     method public void testServiceTestCaseSetUpProperly() throws java.lang.Exception;
   }
 
-  public abstract deprecated class SingleLaunchActivityTestCase extends android.test.InstrumentationTestCase {
+  public abstract deprecated class SingleLaunchActivityTestCase<T extends android.app.Activity> extends android.test.InstrumentationTestCase {
     ctor public SingleLaunchActivityTestCase(java.lang.String, java.lang.Class<T>);
     method public T getActivity();
     method public void testActivityTestCaseSetUpProperly() throws java.lang.Exception;
@@ -41468,7 +41458,7 @@
     ctor public TestMethod(java.lang.String, java.lang.Class<? extends junit.framework.TestCase>);
     ctor public TestMethod(junit.framework.TestCase);
     method public junit.framework.TestCase createTest() throws java.lang.IllegalAccessException, java.lang.InstantiationException, java.lang.reflect.InvocationTargetException;
-    method public T getAnnotation(java.lang.Class<T>);
+    method public <T extends java.lang.annotation.Annotation> T getAnnotation(java.lang.Class<T>);
     method public java.lang.Class<? extends junit.framework.TestCase> getEnclosingClass();
     method public java.lang.String getEnclosingClassname();
     method public java.lang.String getName();
@@ -41916,7 +41906,7 @@
     method public int getSpanEnd(java.lang.Object);
     method public int getSpanFlags(java.lang.Object);
     method public int getSpanStart(java.lang.Object);
-    method public T[] getSpans(int, int, java.lang.Class<T>);
+    method public <T> T[] getSpans(int, int, java.lang.Class<T>);
     method public deprecated int getTextRunCursor(int, int, int, int, int, android.graphics.Paint);
     method public int getTextWatcherDepth();
     method public android.text.SpannableStringBuilder insert(int, java.lang.CharSequence, int, int);
@@ -41938,7 +41928,7 @@
     method public int getSpanEnd(java.lang.Object);
     method public int getSpanFlags(java.lang.Object);
     method public int getSpanStart(java.lang.Object);
-    method public T[] getSpans(int, int, java.lang.Class<T>);
+    method public <T> T[] getSpans(int, int, java.lang.Class<T>);
     method public final int length();
     method public int nextSpanTransition(int, int, java.lang.Class);
     method public final java.lang.String toString();
@@ -41948,7 +41938,7 @@
     method public abstract int getSpanEnd(java.lang.Object);
     method public abstract int getSpanFlags(java.lang.Object);
     method public abstract int getSpanStart(java.lang.Object);
-    method public abstract T[] getSpans(int, int, java.lang.Class<T>);
+    method public abstract <T> T[] getSpans(int, int, java.lang.Class<T>);
     method public abstract int nextSpanTransition(int, int, java.lang.Class);
     field public static final int SPAN_COMPOSING = 256; // 0x100
     field public static final int SPAN_EXCLUSIVE_EXCLUSIVE = 33; // 0x21
@@ -42926,7 +42916,7 @@
     field public static final int WEEKDAY_WEDNESDAY = 4; // 0x4
   }
 
-  public static class TtsSpan.Builder {
+  public static class TtsSpan.Builder<C extends android.text.style.TtsSpan.Builder<?>> {
     ctor public TtsSpan.Builder(java.lang.String);
     method public android.text.style.TtsSpan build();
     method public C setIntArgument(java.lang.String, int);
@@ -43022,7 +43012,7 @@
     method public android.text.style.TtsSpan.OrdinalBuilder setNumber(java.lang.String);
   }
 
-  public static class TtsSpan.SemioticClassBuilder extends android.text.style.TtsSpan.Builder {
+  public static class TtsSpan.SemioticClassBuilder<C extends android.text.style.TtsSpan.SemioticClassBuilder<?>> extends android.text.style.TtsSpan.Builder {
     ctor public TtsSpan.SemioticClassBuilder(java.lang.String);
     method public C setAnimacy(java.lang.String);
     method public C setCase(java.lang.String);
@@ -43429,7 +43419,7 @@
     ctor public AndroidRuntimeException(java.lang.Exception);
   }
 
-  public final class ArrayMap implements java.util.Map {
+  public final class ArrayMap<K, V> implements java.util.Map {
     ctor public ArrayMap();
     ctor public ArrayMap(int);
     ctor public ArrayMap(android.util.ArrayMap<K, V>);
@@ -43457,7 +43447,7 @@
     method public java.util.Collection<V> values();
   }
 
-  public final class ArraySet implements java.util.Collection java.util.Set {
+  public final class ArraySet<E> implements java.util.Collection java.util.Set {
     ctor public ArraySet();
     ctor public ArraySet(int);
     ctor public ArraySet(android.util.ArraySet<E>);
@@ -43478,7 +43468,7 @@
     method public boolean retainAll(java.util.Collection<?>);
     method public int size();
     method public java.lang.Object[] toArray();
-    method public T[] toArray(T[]);
+    method public <T> T[] toArray(T[]);
     method public E valueAt(int);
   }
 
@@ -43623,13 +43613,13 @@
   public deprecated class FloatMath {
   }
 
-  public abstract class FloatProperty extends android.util.Property {
+  public abstract class FloatProperty<T> extends android.util.Property {
     ctor public FloatProperty(java.lang.String);
     method public final void set(T, java.lang.Float);
     method public abstract void setValue(T, float);
   }
 
-  public abstract class IntProperty extends android.util.Property {
+  public abstract class IntProperty<T> extends android.util.Property {
     ctor public IntProperty(java.lang.String);
     method public final void set(T, java.lang.Integer);
     method public abstract void setValue(T, int);
@@ -43729,7 +43719,7 @@
     method public void println(java.lang.String);
   }
 
-  public class LongSparseArray implements java.lang.Cloneable {
+  public class LongSparseArray<E> implements java.lang.Cloneable {
     ctor public LongSparseArray();
     ctor public LongSparseArray(int);
     method public void append(long, E);
@@ -43750,7 +43740,7 @@
     method public E valueAt(int);
   }
 
-  public class LruCache {
+  public class LruCache<K, V> {
     ctor public LruCache(int);
     method protected V create(K);
     method public final synchronized int createCount();
@@ -43838,9 +43828,9 @@
     ctor public NoSuchPropertyException(java.lang.String);
   }
 
-  public class Pair {
+  public class Pair<F, S> {
     ctor public Pair(F, S);
-    method public static android.util.Pair<A, B> create(A, B);
+    method public static <A, B> android.util.Pair<A, B> create(A, B);
     field public final F first;
     field public final S second;
   }
@@ -43873,22 +43863,22 @@
     method public abstract void println(java.lang.String);
   }
 
-  public abstract class Property {
+  public abstract class Property<T, V> {
     ctor public Property(java.lang.Class<V>, java.lang.String);
     method public abstract V get(T);
     method public java.lang.String getName();
     method public java.lang.Class<V> getType();
     method public boolean isReadOnly();
-    method public static android.util.Property<T, V> of(java.lang.Class<T>, java.lang.Class<V>, java.lang.String);
+    method public static <T, V> android.util.Property<T, V> of(java.lang.Class<T>, java.lang.Class<V>, java.lang.String);
     method public void set(T, V);
   }
 
-  public final class Range {
+  public final class Range<T extends java.lang.Comparable<? super T>> {
     ctor public Range(T, T);
     method public T clamp(T);
     method public boolean contains(T);
     method public boolean contains(android.util.Range<T>);
-    method public static android.util.Range<T> create(T, T);
+    method public static <T extends java.lang.Comparable<? super T>> android.util.Range<T> create(T, T);
     method public android.util.Range<T> extend(android.util.Range<T>);
     method public android.util.Range<T> extend(T, T);
     method public android.util.Range<T> extend(T);
@@ -43932,7 +43922,7 @@
     method public static android.util.SizeF parseSizeF(java.lang.String) throws java.lang.NumberFormatException;
   }
 
-  public class SparseArray implements java.lang.Cloneable {
+  public class SparseArray<E> implements java.lang.Cloneable {
     ctor public SparseArray();
     ctor public SparseArray(int);
     method public void append(int, E);
@@ -48743,7 +48733,7 @@
     method public static java.lang.String stripAnchor(java.lang.String);
   }
 
-  public abstract interface ValueCallback {
+  public abstract interface ValueCallback<T> {
     method public abstract void onReceiveValue(T);
   }
 
@@ -49124,7 +49114,7 @@
     method public int getContentHeight();
     method public android.graphics.Bitmap getFavicon();
     method public android.webkit.WebView.HitTestResult getHitTestResult();
-    method public java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
+    method public deprecated java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
     method public java.lang.String getOriginalUrl();
     method public int getProgress();
     method public deprecated float getScale();
@@ -49168,7 +49158,7 @@
     method public void setDownloadListener(android.webkit.DownloadListener);
     method public void setFindListener(android.webkit.WebView.FindListener);
     method public deprecated void setHorizontalScrollbarOverlay(boolean);
-    method public void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public deprecated void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
     method public void setInitialScale(int);
     method public deprecated void setMapTrackballToArrowKeys(boolean);
     method public void setNetworkAvailable(boolean);
@@ -49297,10 +49287,12 @@
     method public abstract void clearFormData();
     method public abstract void clearHttpAuthUsernamePassword();
     method public abstract deprecated void clearUsernamePassword();
+    method public abstract java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
     method public static android.webkit.WebViewDatabase getInstance(android.content.Context);
     method public abstract boolean hasFormData();
     method public abstract boolean hasHttpAuthUsernamePassword();
     method public abstract deprecated boolean hasUsernamePassword();
+    method public abstract void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
   }
 
   public final class WebViewDelegate {
@@ -49758,7 +49750,7 @@
     field public static final int NO_SELECTION = -2147483648; // 0x80000000
   }
 
-  public abstract class AdapterView extends android.view.ViewGroup {
+  public abstract class AdapterView<T extends android.widget.Adapter> extends android.view.ViewGroup {
     ctor public AdapterView(android.content.Context);
     ctor public AdapterView(android.content.Context, android.util.AttributeSet);
     ctor public AdapterView(android.content.Context, android.util.AttributeSet, int);
@@ -49881,7 +49873,7 @@
     ctor public AnalogClock(android.content.Context, android.util.AttributeSet, int, int);
   }
 
-  public class ArrayAdapter extends android.widget.BaseAdapter implements android.widget.Filterable android.widget.ThemedSpinnerAdapter {
+  public class ArrayAdapter<T> extends android.widget.BaseAdapter implements android.widget.Filterable android.widget.ThemedSpinnerAdapter {
     ctor public ArrayAdapter(android.content.Context, int);
     ctor public ArrayAdapter(android.content.Context, int, int);
     ctor public ArrayAdapter(android.content.Context, int, T[]);
@@ -49942,7 +49934,7 @@
     method protected void performFiltering(java.lang.CharSequence, int);
     method public void performValidation();
     method protected void replaceText(java.lang.CharSequence);
-    method public void setAdapter(T);
+    method public <T extends android.widget.ListAdapter & android.widget.Filterable> void setAdapter(T);
     method public void setCompletionHint(java.lang.CharSequence);
     method public void setDropDownAnchor(int);
     method public void setDropDownBackgroundDrawable(android.graphics.drawable.Drawable);
@@ -52228,7 +52220,7 @@
 
 package com.android.internal.util {
 
-  public abstract interface Predicate {
+  public abstract interface Predicate<T> {
     method public abstract boolean apply(T);
   }
 
@@ -54300,22 +54292,22 @@
     enum_constant public static final java.lang.Character.UnicodeScript YI;
   }
 
-  public final class Class implements java.lang.reflect.AnnotatedElement java.lang.reflect.GenericDeclaration java.io.Serializable java.lang.reflect.Type {
-    method public java.lang.Class<? extends U> asSubclass(java.lang.Class<U>);
+  public final class Class<T> implements java.lang.reflect.AnnotatedElement java.lang.reflect.GenericDeclaration java.io.Serializable java.lang.reflect.Type {
+    method public <U> java.lang.Class<? extends U> asSubclass(java.lang.Class<U>);
     method public T cast(java.lang.Object);
     method public boolean desiredAssertionStatus();
     method public static java.lang.Class<?> forName(java.lang.String) throws java.lang.ClassNotFoundException;
     method public static java.lang.Class<?> forName(java.lang.String, boolean, java.lang.ClassLoader) throws java.lang.ClassNotFoundException;
-    method public A getAnnotation(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
-    method public A[] getAnnotationsByType(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A[] getAnnotationsByType(java.lang.Class<A>);
     method public java.lang.String getCanonicalName();
     method public java.lang.ClassLoader getClassLoader();
     method public java.lang.Class<?>[] getClasses();
     method public java.lang.Class<?> getComponentType();
     method public java.lang.reflect.Constructor<T> getConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
-    method public A getDeclaredAnnotation(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A getDeclaredAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public java.lang.Class<?>[] getDeclaredClasses();
     method public java.lang.reflect.Constructor<T> getDeclaredConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
@@ -54427,7 +54419,7 @@
   public abstract interface Cloneable {
   }
 
-  public abstract interface Comparable {
+  public abstract interface Comparable<T> {
     method public abstract int compareTo(T);
   }
 
@@ -54481,7 +54473,7 @@
     field public static final java.lang.Class<java.lang.Double> TYPE;
   }
 
-  public abstract class Enum implements java.lang.Comparable java.io.Serializable {
+  public abstract class Enum<E extends java.lang.Enum<E>> implements java.lang.Comparable java.io.Serializable {
     ctor protected Enum(java.lang.String, int);
     method protected final java.lang.Object clone() throws java.lang.CloneNotSupportedException;
     method public final int compareTo(E);
@@ -54491,7 +54483,7 @@
     method public final int hashCode();
     method public final java.lang.String name();
     method public final int ordinal();
-    method public static T valueOf(java.lang.Class<T>, java.lang.String);
+    method public static <T extends java.lang.Enum<T>> T valueOf(java.lang.Class<T>, java.lang.String);
   }
 
   public class EnumConstantNotPresentException extends java.lang.RuntimeException {
@@ -54610,7 +54602,7 @@
     ctor public IndexOutOfBoundsException(java.lang.String);
   }
 
-  public class InheritableThreadLocal extends java.lang.ThreadLocal {
+  public class InheritableThreadLocal<T> extends java.lang.ThreadLocal {
     ctor public InheritableThreadLocal();
     method protected T childValue(T);
   }
@@ -54689,7 +54681,7 @@
     ctor public InterruptedException(java.lang.String);
   }
 
-  public abstract interface Iterable {
+  public abstract interface Iterable<T> {
     method public default void forEach(java.util.function.Consumer<? super T>);
     method public abstract java.util.Iterator<T> iterator();
     method public default java.util.Spliterator<T> spliterator();
@@ -54904,12 +54896,12 @@
   }
 
   public class Package implements java.lang.reflect.AnnotatedElement {
-    method public A getAnnotation(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
-    method public A[] getAnnotationsByType(java.lang.Class<A>);
-    method public A getDeclaredAnnotation(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A[] getAnnotationsByType(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A getDeclaredAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
-    method public A[] getDeclaredAnnotationsByType(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A[] getDeclaredAnnotationsByType(java.lang.Class<A>);
     method public java.lang.String getImplementationTitle();
     method public java.lang.String getImplementationVendor();
     method public java.lang.String getImplementationVersion();
@@ -55508,13 +55500,13 @@
     method public void uncaughtException(java.lang.Thread, java.lang.Throwable);
   }
 
-  public class ThreadLocal {
+  public class ThreadLocal<T> {
     ctor public ThreadLocal();
     method public T get();
     method protected T initialValue();
     method public void remove();
     method public void set(T);
-    method public static java.lang.ThreadLocal<S> withInitial(java.util.function.Supplier<? extends S>);
+    method public static <S> java.lang.ThreadLocal<S> withInitial(java.util.function.Supplier<? extends S>);
   }
 
   public class Throwable implements java.io.Serializable {
@@ -55617,6 +55609,8 @@
     enum_constant public static final java.lang.annotation.ElementType PACKAGE;
     enum_constant public static final java.lang.annotation.ElementType PARAMETER;
     enum_constant public static final java.lang.annotation.ElementType TYPE;
+    enum_constant public static final java.lang.annotation.ElementType TYPE_PARAMETER;
+    enum_constant public static final java.lang.annotation.ElementType TYPE_USE;
   }
 
   public class IncompleteAnnotationException extends java.lang.RuntimeException {
@@ -55652,30 +55646,30 @@
 
 package java.lang.ref {
 
-  public class PhantomReference extends java.lang.ref.Reference {
+  public class PhantomReference<T> extends java.lang.ref.Reference {
     ctor public PhantomReference(T, java.lang.ref.ReferenceQueue<? super T>);
   }
 
-  public abstract class Reference {
+  public abstract class Reference<T> {
     method public void clear();
     method public boolean enqueue();
     method public T get();
     method public boolean isEnqueued();
   }
 
-  public class ReferenceQueue {
+  public class ReferenceQueue<T> {
     ctor public ReferenceQueue();
     method public java.lang.ref.Reference<? extends T> poll();
     method public java.lang.ref.Reference<? extends T> remove(long) throws java.lang.IllegalArgumentException, java.lang.InterruptedException;
     method public java.lang.ref.Reference<? extends T> remove() throws java.lang.InterruptedException;
   }
 
-  public class SoftReference extends java.lang.ref.Reference {
+  public class SoftReference<T> extends java.lang.ref.Reference {
     ctor public SoftReference(T);
     ctor public SoftReference(T, java.lang.ref.ReferenceQueue<? super T>);
   }
 
-  public class WeakReference extends java.lang.ref.Reference {
+  public class WeakReference<T> extends java.lang.ref.Reference {
     ctor public WeakReference(T);
     ctor public WeakReference(T, java.lang.ref.ReferenceQueue<? super T>);
   }
@@ -55686,7 +55680,7 @@
 
   public class AccessibleObject implements java.lang.reflect.AnnotatedElement {
     ctor protected AccessibleObject();
-    method public T getAnnotation(java.lang.Class<T>);
+    method public <T extends java.lang.annotation.Annotation> T getAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getAnnotations();
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public boolean isAccessible();
@@ -55695,12 +55689,12 @@
   }
 
   public abstract interface AnnotatedElement {
-    method public abstract T getAnnotation(java.lang.Class<T>);
+    method public abstract <T extends java.lang.annotation.Annotation> T getAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getAnnotations();
-    method public default T[] getAnnotationsByType(java.lang.Class<T>);
-    method public default java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
+    method public default <T extends java.lang.annotation.Annotation> T[] getAnnotationsByType(java.lang.Class<T>);
+    method public default <T extends java.lang.annotation.Annotation> T getDeclaredAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getDeclaredAnnotations();
-    method public default T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
+    method public default <T extends java.lang.annotation.Annotation> T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public default boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
   }
 
@@ -55728,7 +55722,7 @@
     method public static void setShort(java.lang.Object, int, short) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
   }
 
-  public final class Constructor extends java.lang.reflect.Executable {
+  public final class Constructor<T> extends java.lang.reflect.Executable {
     method public java.lang.Class<T> getDeclaringClass();
     method public java.lang.Class<?>[] getExceptionTypes();
     method public int getModifiers();
@@ -55876,7 +55870,7 @@
   }
 
   public final class Parameter implements java.lang.reflect.AnnotatedElement {
-    method public T getAnnotation(java.lang.Class<T>);
+    method public <T extends java.lang.annotation.Annotation> T getAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getAnnotations();
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public java.lang.reflect.Executable getDeclaringExecutable();
@@ -55913,7 +55907,7 @@
   public abstract interface Type {
   }
 
-  public abstract interface TypeVariable implements java.lang.reflect.Type {
+  public abstract interface TypeVariable<D extends java.lang.reflect.GenericDeclaration> implements java.lang.reflect.Type {
     method public abstract java.lang.reflect.Type[] getBounds();
     method public abstract D getGenericDeclaration();
     method public abstract java.lang.String getName();
@@ -56702,7 +56696,7 @@
     method public abstract java.net.SocketImpl createSocketImpl();
   }
 
-  public abstract interface SocketOption {
+  public abstract interface SocketOption<T> {
     method public abstract java.lang.String name();
     method public abstract java.lang.Class<T> type();
   }
@@ -57234,9 +57228,9 @@
   }
 
   public abstract interface AsynchronousByteChannel implements java.nio.channels.AsynchronousChannel {
-    method public abstract void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer);
-    method public abstract void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer);
   }
 
@@ -57264,25 +57258,25 @@
   public abstract class AsynchronousFileChannel implements java.nio.channels.AsynchronousChannel {
     ctor protected AsynchronousFileChannel();
     method public abstract void force(boolean) throws java.io.IOException;
-    method public abstract void lock(long, long, boolean, A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
-    method public final void lock(A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
+    method public abstract <A> void lock(long, long, boolean, A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
+    method public final <A> void lock(A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
     method public abstract java.util.concurrent.Future<java.nio.channels.FileLock> lock(long, long, boolean);
     method public final java.util.concurrent.Future<java.nio.channels.FileLock> lock();
     method public static java.nio.channels.AsynchronousFileChannel open(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.util.concurrent.ExecutorService, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
     method public static java.nio.channels.AsynchronousFileChannel open(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public abstract void read(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void read(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer, long);
     method public abstract long size() throws java.io.IOException;
     method public abstract java.nio.channels.AsynchronousFileChannel truncate(long) throws java.io.IOException;
     method public abstract java.nio.channels.FileLock tryLock(long, long, boolean) throws java.io.IOException;
     method public final java.nio.channels.FileLock tryLock() throws java.io.IOException;
-    method public abstract void write(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void write(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer, long);
   }
 
   public abstract class AsynchronousServerSocketChannel implements java.nio.channels.AsynchronousChannel java.nio.channels.NetworkChannel {
     ctor protected AsynchronousServerSocketChannel(java.nio.channels.spi.AsynchronousChannelProvider);
-    method public abstract void accept(A, java.nio.channels.CompletionHandler<java.nio.channels.AsynchronousSocketChannel, ? super A>);
+    method public abstract <A> void accept(A, java.nio.channels.CompletionHandler<java.nio.channels.AsynchronousSocketChannel, ? super A>);
     method public abstract java.util.concurrent.Future<java.nio.channels.AsynchronousSocketChannel> accept();
     method public final java.nio.channels.AsynchronousServerSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.nio.channels.AsynchronousServerSocketChannel bind(java.net.SocketAddress, int) throws java.io.IOException;
@@ -57290,30 +57284,30 @@
     method public static java.nio.channels.AsynchronousServerSocketChannel open(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
     method public static java.nio.channels.AsynchronousServerSocketChannel open() throws java.io.IOException;
     method public final java.nio.channels.spi.AsynchronousChannelProvider provider();
-    method public abstract java.nio.channels.AsynchronousServerSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <T> java.nio.channels.AsynchronousServerSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
   }
 
   public abstract class AsynchronousSocketChannel implements java.nio.channels.AsynchronousByteChannel java.nio.channels.NetworkChannel {
     ctor protected AsynchronousSocketChannel(java.nio.channels.spi.AsynchronousChannelProvider);
     method public abstract java.nio.channels.AsynchronousSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
-    method public abstract void connect(java.net.SocketAddress, A, java.nio.channels.CompletionHandler<java.lang.Void, ? super A>);
+    method public abstract <A> void connect(java.net.SocketAddress, A, java.nio.channels.CompletionHandler<java.lang.Void, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Void> connect(java.net.SocketAddress);
     method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
     method public abstract java.net.SocketAddress getRemoteAddress() throws java.io.IOException;
     method public static java.nio.channels.AsynchronousSocketChannel open(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
     method public static java.nio.channels.AsynchronousSocketChannel open() throws java.io.IOException;
     method public final java.nio.channels.spi.AsynchronousChannelProvider provider();
-    method public abstract void read(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public final void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void read(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public final <A> void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer);
-    method public abstract void read(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
-    method public abstract java.nio.channels.AsynchronousSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <A> void read(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
+    method public abstract <T> java.nio.channels.AsynchronousSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public abstract java.nio.channels.AsynchronousSocketChannel shutdownInput() throws java.io.IOException;
     method public abstract java.nio.channels.AsynchronousSocketChannel shutdownOutput() throws java.io.IOException;
-    method public abstract void write(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public final void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void write(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public final <A> void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer);
-    method public abstract void write(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
+    method public abstract <A> void write(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
   }
 
   public abstract interface ByteChannel implements java.nio.channels.ReadableByteChannel java.nio.channels.WritableByteChannel {
@@ -57353,7 +57347,7 @@
     ctor public ClosedSelectorException();
   }
 
-  public abstract interface CompletionHandler {
+  public abstract interface CompletionHandler<V, A> {
     method public abstract void completed(V, A);
     method public abstract void failed(java.lang.Throwable, A);
   }
@@ -57377,7 +57371,7 @@
     method public final long read(java.nio.ByteBuffer[]) throws java.io.IOException;
     method public abstract java.net.SocketAddress receive(java.nio.ByteBuffer) throws java.io.IOException;
     method public abstract int send(java.nio.ByteBuffer, java.net.SocketAddress) throws java.io.IOException;
-    method public abstract java.nio.channels.DatagramChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <T> java.nio.channels.DatagramChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public abstract java.net.DatagramSocket socket();
     method public final int validOps();
     method public abstract int write(java.nio.ByteBuffer) throws java.io.IOException;
@@ -57482,8 +57476,8 @@
   public abstract interface NetworkChannel implements java.nio.channels.Channel {
     method public abstract java.nio.channels.NetworkChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
-    method public abstract T getOption(java.net.SocketOption<T>) throws java.io.IOException;
-    method public abstract java.nio.channels.NetworkChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <T> T getOption(java.net.SocketOption<T>) throws java.io.IOException;
+    method public abstract <T> java.nio.channels.NetworkChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public abstract java.util.Set<java.net.SocketOption<?>> supportedOptions();
   }
 
@@ -57605,7 +57599,7 @@
     method public abstract java.nio.channels.ServerSocketChannel bind(java.net.SocketAddress, int) throws java.io.IOException;
     method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
     method public static java.nio.channels.ServerSocketChannel open() throws java.io.IOException;
-    method public abstract java.nio.channels.ServerSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <T> java.nio.channels.ServerSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public abstract java.net.ServerSocket socket();
     method public final int validOps();
   }
@@ -57628,7 +57622,7 @@
     method public abstract int read(java.nio.ByteBuffer) throws java.io.IOException;
     method public abstract long read(java.nio.ByteBuffer[], int, int) throws java.io.IOException;
     method public final long read(java.nio.ByteBuffer[]) throws java.io.IOException;
-    method public abstract java.nio.channels.SocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <T> java.nio.channels.SocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public abstract java.nio.channels.SocketChannel shutdownInput() throws java.io.IOException;
     method public abstract java.nio.channels.SocketChannel shutdownOutput() throws java.io.IOException;
     method public abstract java.net.Socket socket();
@@ -57913,11 +57907,11 @@
     ctor public DirectoryNotEmptyException(java.lang.String);
   }
 
-  public abstract interface DirectoryStream implements java.io.Closeable java.lang.Iterable {
+  public abstract interface DirectoryStream<T> implements java.io.Closeable java.lang.Iterable {
     method public abstract java.util.Iterator<T> iterator();
   }
 
-  public static abstract interface DirectoryStream.Filter {
+  public static abstract interface DirectoryStream.Filter<T> {
     method public abstract boolean accept(T) throws java.io.IOException;
   }
 
@@ -57929,7 +57923,7 @@
   public abstract class FileStore {
     ctor protected FileStore();
     method public abstract java.lang.Object getAttribute(java.lang.String) throws java.io.IOException;
-    method public abstract V getFileStoreAttributeView(java.lang.Class<V>);
+    method public abstract <V extends java.nio.file.attribute.FileStoreAttributeView> V getFileStoreAttributeView(java.lang.Class<V>);
     method public abstract long getTotalSpace() throws java.io.IOException;
     method public abstract long getUnallocatedSpace() throws java.io.IOException;
     method public abstract long getUsableSpace() throws java.io.IOException;
@@ -58001,7 +57995,7 @@
     enum_constant public static final java.nio.file.FileVisitResult TERMINATE;
   }
 
-  public abstract interface FileVisitor {
+  public abstract interface FileVisitor<T> {
     method public abstract java.nio.file.FileVisitResult postVisitDirectory(T, java.io.IOException) throws java.io.IOException;
     method public abstract java.nio.file.FileVisitResult preVisitDirectory(T, java.nio.file.attribute.BasicFileAttributes) throws java.io.IOException;
     method public abstract java.nio.file.FileVisitResult visitFile(T, java.nio.file.attribute.BasicFileAttributes) throws java.io.IOException;
@@ -58026,7 +58020,7 @@
     method public static boolean exists(java.nio.file.Path, java.nio.file.LinkOption...);
     method public static java.util.stream.Stream<java.nio.file.Path> find(java.nio.file.Path, int, java.util.function.BiPredicate<java.nio.file.Path, java.nio.file.attribute.BasicFileAttributes>, java.nio.file.FileVisitOption...) throws java.io.IOException;
     method public static java.lang.Object getAttribute(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
+    method public static <V extends java.nio.file.attribute.FileAttributeView> V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
     method public static java.nio.file.FileStore getFileStore(java.nio.file.Path) throws java.io.IOException;
     method public static java.nio.file.attribute.FileTime getLastModifiedTime(java.nio.file.Path, java.nio.file.LinkOption...) throws java.io.IOException;
     method public static java.nio.file.attribute.UserPrincipal getOwner(java.nio.file.Path, java.nio.file.LinkOption...) throws java.io.IOException;
@@ -58059,7 +58053,7 @@
     method public static byte[] readAllBytes(java.nio.file.Path) throws java.io.IOException;
     method public static java.util.List<java.lang.String> readAllLines(java.nio.file.Path, java.nio.charset.Charset) throws java.io.IOException;
     method public static java.util.List<java.lang.String> readAllLines(java.nio.file.Path) throws java.io.IOException;
-    method public static A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
+    method public static <A extends java.nio.file.attribute.BasicFileAttributes> A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
     method public static java.util.Map<java.lang.String, java.lang.Object> readAttributes(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
     method public static java.nio.file.Path readSymbolicLink(java.nio.file.Path) throws java.io.IOException;
     method public static java.nio.file.Path setAttribute(java.nio.file.Path, java.lang.String, java.lang.Object, java.nio.file.LinkOption...) throws java.io.IOException;
@@ -58167,17 +58161,17 @@
     ctor public ReadOnlyFileSystemException();
   }
 
-  public abstract interface SecureDirectoryStream implements java.nio.file.DirectoryStream {
+  public abstract interface SecureDirectoryStream<T> implements java.nio.file.DirectoryStream {
     method public abstract void deleteDirectory(T) throws java.io.IOException;
     method public abstract void deleteFile(T) throws java.io.IOException;
-    method public abstract V getFileAttributeView(java.lang.Class<V>);
-    method public abstract V getFileAttributeView(T, java.lang.Class<V>, java.nio.file.LinkOption...);
+    method public abstract <V extends java.nio.file.attribute.FileAttributeView> V getFileAttributeView(java.lang.Class<V>);
+    method public abstract <V extends java.nio.file.attribute.FileAttributeView> V getFileAttributeView(T, java.lang.Class<V>, java.nio.file.LinkOption...);
     method public abstract void move(T, java.nio.file.SecureDirectoryStream<T>, T) throws java.io.IOException;
     method public abstract java.nio.channels.SeekableByteChannel newByteChannel(T, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
     method public abstract java.nio.file.SecureDirectoryStream<T> newDirectoryStream(T, java.nio.file.LinkOption...) throws java.io.IOException;
   }
 
-  public class SimpleFileVisitor implements java.nio.file.FileVisitor {
+  public class SimpleFileVisitor<T> implements java.nio.file.FileVisitor {
     ctor protected SimpleFileVisitor();
     method public java.nio.file.FileVisitResult postVisitDirectory(T, java.io.IOException) throws java.io.IOException;
     method public java.nio.file.FileVisitResult preVisitDirectory(T, java.nio.file.attribute.BasicFileAttributes) throws java.io.IOException;
@@ -58215,13 +58209,13 @@
     field public static final java.nio.file.WatchEvent.Kind<java.lang.Object> OVERFLOW;
   }
 
-  public abstract interface WatchEvent {
+  public abstract interface WatchEvent<T> {
     method public abstract T context();
     method public abstract int count();
     method public abstract java.nio.file.WatchEvent.Kind<T> kind();
   }
 
-  public static abstract interface WatchEvent.Kind {
+  public static abstract interface WatchEvent.Kind<T> {
     method public abstract java.lang.String name();
     method public abstract java.lang.Class<T> type();
   }
@@ -58357,7 +58351,7 @@
     method public abstract boolean isSystem();
   }
 
-  public abstract interface FileAttribute {
+  public abstract interface FileAttribute<T> {
     method public abstract java.lang.String name();
     method public abstract T value();
   }
@@ -58454,7 +58448,7 @@
     method public void createSymbolicLink(java.nio.file.Path, java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
     method public abstract void delete(java.nio.file.Path) throws java.io.IOException;
     method public boolean deleteIfExists(java.nio.file.Path) throws java.io.IOException;
-    method public abstract V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
+    method public abstract <V extends java.nio.file.attribute.FileAttributeView> V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
     method public abstract java.nio.file.FileStore getFileStore(java.nio.file.Path) throws java.io.IOException;
     method public abstract java.nio.file.FileSystem getFileSystem(java.net.URI);
     method public abstract java.nio.file.Path getPath(java.net.URI);
@@ -58471,7 +58465,7 @@
     method public java.nio.file.FileSystem newFileSystem(java.nio.file.Path, java.util.Map<java.lang.String, ?>) throws java.io.IOException;
     method public java.io.InputStream newInputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
     method public java.io.OutputStream newOutputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public abstract A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
+    method public abstract <A extends java.nio.file.attribute.BasicFileAttributes> A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
     method public abstract java.util.Map<java.lang.String, java.lang.Object> readAttributes(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
     method public java.nio.file.Path readSymbolicLink(java.nio.file.Path) throws java.io.IOException;
     method public abstract void setAttribute(java.nio.file.Path, java.lang.String, java.lang.Object, java.nio.file.LinkOption...) throws java.io.IOException;
@@ -58501,12 +58495,12 @@
 
   public final class AccessController {
     method public static void checkPermission(java.security.Permission) throws java.security.AccessControlException;
-    method public static T doPrivileged(java.security.PrivilegedAction<T>);
-    method public static T doPrivileged(java.security.PrivilegedAction<T>, java.security.AccessControlContext);
-    method public static T doPrivileged(java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
-    method public static T doPrivileged(java.security.PrivilegedExceptionAction<T>, java.security.AccessControlContext) throws java.security.PrivilegedActionException;
-    method public static T doPrivilegedWithCombiner(java.security.PrivilegedAction<T>);
-    method public static T doPrivilegedWithCombiner(java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
+    method public static <T> T doPrivileged(java.security.PrivilegedAction<T>);
+    method public static <T> T doPrivileged(java.security.PrivilegedAction<T>, java.security.AccessControlContext);
+    method public static <T> T doPrivileged(java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
+    method public static <T> T doPrivileged(java.security.PrivilegedExceptionAction<T>, java.security.AccessControlContext) throws java.security.PrivilegedActionException;
+    method public static <T> T doPrivilegedWithCombiner(java.security.PrivilegedAction<T>);
+    method public static <T> T doPrivilegedWithCombiner(java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
     method public static java.security.AccessControlContext getContext();
   }
 
@@ -58545,7 +58539,7 @@
     method public static java.security.AlgorithmParameters getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
     method public static java.security.AlgorithmParameters getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
     method public static java.security.AlgorithmParameters getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
-    method public final T getParameterSpec(java.lang.Class<T>) throws java.security.spec.InvalidParameterSpecException;
+    method public final <T extends java.security.spec.AlgorithmParameterSpec> T getParameterSpec(java.lang.Class<T>) throws java.security.spec.InvalidParameterSpecException;
     method public final java.security.Provider getProvider();
     method public final void init(java.security.spec.AlgorithmParameterSpec) throws java.security.spec.InvalidParameterSpecException;
     method public final void init(byte[]) throws java.io.IOException;
@@ -58557,7 +58551,7 @@
     ctor public AlgorithmParametersSpi();
     method protected abstract byte[] engineGetEncoded() throws java.io.IOException;
     method protected abstract byte[] engineGetEncoded(java.lang.String) throws java.io.IOException;
-    method protected abstract T engineGetParameterSpec(java.lang.Class<T>) throws java.security.spec.InvalidParameterSpecException;
+    method protected abstract <T extends java.security.spec.AlgorithmParameterSpec> T engineGetParameterSpec(java.lang.Class<T>) throws java.security.spec.InvalidParameterSpecException;
     method protected abstract void engineInit(java.security.spec.AlgorithmParameterSpec) throws java.security.spec.InvalidParameterSpecException;
     method protected abstract void engineInit(byte[]) throws java.io.IOException;
     method protected abstract void engineInit(byte[], java.lang.String) throws java.io.IOException;
@@ -58749,7 +58743,7 @@
     method public static java.security.KeyFactory getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
     method public static java.security.KeyFactory getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
     method public static java.security.KeyFactory getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
-    method public final T getKeySpec(java.security.Key, java.lang.Class<T>) throws java.security.spec.InvalidKeySpecException;
+    method public final <T extends java.security.spec.KeySpec> T getKeySpec(java.security.Key, java.lang.Class<T>) throws java.security.spec.InvalidKeySpecException;
     method public final java.security.Provider getProvider();
     method public final java.security.Key translateKey(java.security.Key) throws java.security.InvalidKeyException;
   }
@@ -58758,7 +58752,7 @@
     ctor public KeyFactorySpi();
     method protected abstract java.security.PrivateKey engineGeneratePrivate(java.security.spec.KeySpec) throws java.security.spec.InvalidKeySpecException;
     method protected abstract java.security.PublicKey engineGeneratePublic(java.security.spec.KeySpec) throws java.security.spec.InvalidKeySpecException;
-    method protected abstract T engineGetKeySpec(java.security.Key, java.lang.Class<T>) throws java.security.spec.InvalidKeySpecException;
+    method protected abstract <T extends java.security.spec.KeySpec> T engineGetKeySpec(java.security.Key, java.lang.Class<T>) throws java.security.spec.InvalidKeySpecException;
     method protected abstract java.security.Key engineTranslateKey(java.security.Key) throws java.security.InvalidKeyException;
   }
 
@@ -59046,7 +59040,7 @@
     field public static final long serialVersionUID = 6034044314589513430L; // 0x53bd3b559a12c6d6L
   }
 
-  public abstract interface PrivilegedAction {
+  public abstract interface PrivilegedAction<T> {
     method public abstract T run();
   }
 
@@ -59055,7 +59049,7 @@
     method public java.lang.Exception getException();
   }
 
-  public abstract interface PrivilegedExceptionAction {
+  public abstract interface PrivilegedExceptionAction<T> {
     method public abstract T run() throws java.lang.Exception;
   }
 
@@ -61249,11 +61243,11 @@
     method public abstract void free() throws java.sql.SQLException;
     method public abstract java.io.InputStream getBinaryStream() throws java.sql.SQLException;
     method public abstract java.io.Reader getCharacterStream() throws java.sql.SQLException;
-    method public abstract T getSource(java.lang.Class<T>) throws java.sql.SQLException;
+    method public abstract <T extends javax.xml.transform.Source> T getSource(java.lang.Class<T>) throws java.sql.SQLException;
     method public abstract java.lang.String getString() throws java.sql.SQLException;
     method public abstract java.io.OutputStream setBinaryStream() throws java.sql.SQLException;
     method public abstract java.io.Writer setCharacterStream() throws java.sql.SQLException;
-    method public abstract T setResult(java.lang.Class<T>) throws java.sql.SQLException;
+    method public abstract <T extends javax.xml.transform.Result> T setResult(java.lang.Class<T>) throws java.sql.SQLException;
     method public abstract void setString(java.lang.String) throws java.sql.SQLException;
   }
 
@@ -61377,7 +61371,7 @@
 
   public abstract interface Wrapper {
     method public abstract boolean isWrapperFor(java.lang.Class<?>) throws java.sql.SQLException;
-    method public abstract T unwrap(java.lang.Class<T>) throws java.sql.SQLException;
+    method public abstract <T> T unwrap(java.lang.Class<T>) throws java.sql.SQLException;
   }
 
 }
@@ -61910,7 +61904,7 @@
 
 package java.util {
 
-  public abstract class AbstractCollection implements java.util.Collection {
+  public abstract class AbstractCollection<E> implements java.util.Collection {
     ctor protected AbstractCollection();
     method public boolean add(E);
     method public boolean addAll(java.util.Collection<? extends E>);
@@ -61924,10 +61918,10 @@
     method public boolean retainAll(java.util.Collection<?>);
     method public abstract int size();
     method public java.lang.Object[] toArray();
-    method public T[] toArray(T[]);
+    method public <T> T[] toArray(T[]);
   }
 
-  public abstract class AbstractList extends java.util.AbstractCollection implements java.util.List {
+  public abstract class AbstractList<E> extends java.util.AbstractCollection implements java.util.List {
     ctor protected AbstractList();
     method public void add(int, E);
     method public boolean addAll(int, java.util.Collection<? extends E>);
@@ -61944,7 +61938,7 @@
     field protected transient int modCount;
   }
 
-  public abstract class AbstractMap implements java.util.Map {
+  public abstract class AbstractMap<K, V> implements java.util.Map {
     ctor protected AbstractMap();
     method public void clear();
     method public boolean containsKey(java.lang.Object);
@@ -61960,7 +61954,7 @@
     method public java.util.Collection<V> values();
   }
 
-  public static class AbstractMap.SimpleEntry implements java.util.Map.Entry java.io.Serializable {
+  public static class AbstractMap.SimpleEntry<K, V> implements java.util.Map.Entry java.io.Serializable {
     ctor public AbstractMap.SimpleEntry(K, V);
     ctor public AbstractMap.SimpleEntry(java.util.Map.Entry<? extends K, ? extends V>);
     method public K getKey();
@@ -61968,7 +61962,7 @@
     method public V setValue(V);
   }
 
-  public static class AbstractMap.SimpleImmutableEntry implements java.util.Map.Entry java.io.Serializable {
+  public static class AbstractMap.SimpleImmutableEntry<K, V> implements java.util.Map.Entry java.io.Serializable {
     ctor public AbstractMap.SimpleImmutableEntry(K, V);
     ctor public AbstractMap.SimpleImmutableEntry(java.util.Map.Entry<? extends K, ? extends V>);
     method public K getKey();
@@ -61976,23 +61970,23 @@
     method public V setValue(V);
   }
 
-  public abstract class AbstractQueue extends java.util.AbstractCollection implements java.util.Queue {
+  public abstract class AbstractQueue<E> extends java.util.AbstractCollection implements java.util.Queue {
     ctor protected AbstractQueue();
     method public E element();
     method public E remove();
   }
 
-  public abstract class AbstractSequentialList extends java.util.AbstractList {
+  public abstract class AbstractSequentialList<E> extends java.util.AbstractList {
     ctor protected AbstractSequentialList();
     method public E get(int);
     method public abstract java.util.ListIterator<E> listIterator(int);
   }
 
-  public abstract class AbstractSet extends java.util.AbstractCollection implements java.util.Set {
+  public abstract class AbstractSet<E> extends java.util.AbstractCollection implements java.util.Set {
     ctor protected AbstractSet();
   }
 
-  public class ArrayDeque extends java.util.AbstractCollection implements java.lang.Cloneable java.util.Deque java.io.Serializable {
+  public class ArrayDeque<E> extends java.util.AbstractCollection implements java.lang.Cloneable java.util.Deque java.io.Serializable {
     ctor public ArrayDeque();
     ctor public ArrayDeque(int);
     ctor public ArrayDeque(java.util.Collection<? extends E>);
@@ -62024,7 +62018,7 @@
     method public java.util.Spliterator<E> spliterator();
   }
 
-  public class ArrayList extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
+  public class ArrayList<E> extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
     ctor public ArrayList(int);
     ctor public ArrayList();
     ctor public ArrayList(java.util.Collection<? extends E>);
@@ -62041,7 +62035,7 @@
   }
 
   public class Arrays {
-    method public static java.util.List<T> asList(T...);
+    method public static <T> java.util.List<T> asList(T...);
     method public static int binarySearch(long[], long);
     method public static int binarySearch(long[], int, int, long);
     method public static int binarySearch(int[], int);
@@ -62058,10 +62052,10 @@
     method public static int binarySearch(float[], int, int, float);
     method public static int binarySearch(java.lang.Object[], java.lang.Object);
     method public static int binarySearch(java.lang.Object[], int, int, java.lang.Object);
-    method public static int binarySearch(T[], T, java.util.Comparator<? super T>);
-    method public static int binarySearch(T[], int, int, T, java.util.Comparator<? super T>);
-    method public static T[] copyOf(T[], int);
-    method public static T[] copyOf(U[], int, java.lang.Class<? extends T[]>);
+    method public static <T> int binarySearch(T[], T, java.util.Comparator<? super T>);
+    method public static <T> int binarySearch(T[], int, int, T, java.util.Comparator<? super T>);
+    method public static <T> T[] copyOf(T[], int);
+    method public static <T, U> T[] copyOf(U[], int, java.lang.Class<? extends T[]>);
     method public static byte[] copyOf(byte[], int);
     method public static short[] copyOf(short[], int);
     method public static int[] copyOf(int[], int);
@@ -62070,8 +62064,8 @@
     method public static float[] copyOf(float[], int);
     method public static double[] copyOf(double[], int);
     method public static boolean[] copyOf(boolean[], int);
-    method public static T[] copyOfRange(T[], int, int);
-    method public static T[] copyOfRange(U[], int, int, java.lang.Class<? extends T[]>);
+    method public static <T> T[] copyOfRange(T[], int, int);
+    method public static <T, U> T[] copyOfRange(U[], int, int, java.lang.Class<? extends T[]>);
     method public static byte[] copyOfRange(byte[], int, int);
     method public static short[] copyOfRange(short[], int, int);
     method public static int[] copyOfRange(int[], int, int);
@@ -62119,15 +62113,15 @@
     method public static int hashCode(float[]);
     method public static int hashCode(double[]);
     method public static int hashCode(java.lang.Object[]);
-    method public static void parallelPrefix(T[], java.util.function.BinaryOperator<T>);
-    method public static void parallelPrefix(T[], int, int, java.util.function.BinaryOperator<T>);
+    method public static <T> void parallelPrefix(T[], java.util.function.BinaryOperator<T>);
+    method public static <T> void parallelPrefix(T[], int, int, java.util.function.BinaryOperator<T>);
     method public static void parallelPrefix(long[], java.util.function.LongBinaryOperator);
     method public static void parallelPrefix(long[], int, int, java.util.function.LongBinaryOperator);
     method public static void parallelPrefix(double[], java.util.function.DoubleBinaryOperator);
     method public static void parallelPrefix(double[], int, int, java.util.function.DoubleBinaryOperator);
     method public static void parallelPrefix(int[], java.util.function.IntBinaryOperator);
     method public static void parallelPrefix(int[], int, int, java.util.function.IntBinaryOperator);
-    method public static void parallelSetAll(T[], java.util.function.IntFunction<? extends T>);
+    method public static <T> void parallelSetAll(T[], java.util.function.IntFunction<? extends T>);
     method public static void parallelSetAll(int[], java.util.function.IntUnaryOperator);
     method public static void parallelSetAll(long[], java.util.function.IntToLongFunction);
     method public static void parallelSetAll(double[], java.util.function.IntToDoubleFunction);
@@ -62145,11 +62139,11 @@
     method public static void parallelSort(float[], int, int);
     method public static void parallelSort(double[]);
     method public static void parallelSort(double[], int, int);
-    method public static void parallelSort(T[]);
-    method public static void parallelSort(T[], int, int);
-    method public static void parallelSort(T[], java.util.Comparator<? super T>);
-    method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>);
-    method public static void setAll(T[], java.util.function.IntFunction<? extends T>);
+    method public static <T extends java.lang.Comparable<? super T>> void parallelSort(T[]);
+    method public static <T extends java.lang.Comparable<? super T>> void parallelSort(T[], int, int);
+    method public static <T> void parallelSort(T[], java.util.Comparator<? super T>);
+    method public static <T> void parallelSort(T[], int, int, java.util.Comparator<? super T>);
+    method public static <T> void setAll(T[], java.util.function.IntFunction<? extends T>);
     method public static void setAll(int[], java.util.function.IntUnaryOperator);
     method public static void setAll(long[], java.util.function.IntToLongFunction);
     method public static void setAll(double[], java.util.function.IntToDoubleFunction);
@@ -62169,18 +62163,18 @@
     method public static void sort(double[], int, int);
     method public static void sort(java.lang.Object[]);
     method public static void sort(java.lang.Object[], int, int);
-    method public static void sort(T[], java.util.Comparator<? super T>);
-    method public static void sort(T[], int, int, java.util.Comparator<? super T>);
-    method public static java.util.Spliterator<T> spliterator(T[]);
-    method public static java.util.Spliterator<T> spliterator(T[], int, int);
+    method public static <T> void sort(T[], java.util.Comparator<? super T>);
+    method public static <T> void sort(T[], int, int, java.util.Comparator<? super T>);
+    method public static <T> java.util.Spliterator<T> spliterator(T[]);
+    method public static <T> java.util.Spliterator<T> spliterator(T[], int, int);
     method public static java.util.Spliterator.OfInt spliterator(int[]);
     method public static java.util.Spliterator.OfInt spliterator(int[], int, int);
     method public static java.util.Spliterator.OfLong spliterator(long[]);
     method public static java.util.Spliterator.OfLong spliterator(long[], int, int);
     method public static java.util.Spliterator.OfDouble spliterator(double[]);
     method public static java.util.Spliterator.OfDouble spliterator(double[], int, int);
-    method public static java.util.stream.Stream<T> stream(T[]);
-    method public static java.util.stream.Stream<T> stream(T[], int, int);
+    method public static <T> java.util.stream.Stream<T> stream(T[]);
+    method public static <T> java.util.stream.Stream<T> stream(T[], int, int);
     method public static java.util.stream.IntStream stream(int[]);
     method public static java.util.stream.IntStream stream(int[], int, int);
     method public static java.util.stream.LongStream stream(long[]);
@@ -62364,7 +62358,7 @@
     field protected long time;
   }
 
-  public abstract interface Collection implements java.lang.Iterable {
+  public abstract interface Collection<E> implements java.lang.Iterable {
     method public abstract boolean add(E);
     method public abstract boolean addAll(java.util.Collection<? extends E>);
     method public abstract void clear();
@@ -62382,86 +62376,86 @@
     method public abstract int size();
     method public default java.util.stream.Stream<E> stream();
     method public abstract java.lang.Object[] toArray();
-    method public abstract T[] toArray(T[]);
+    method public abstract <T> T[] toArray(T[]);
   }
 
   public class Collections {
-    method public static boolean addAll(java.util.Collection<? super T>, T...);
-    method public static java.util.Queue<T> asLifoQueue(java.util.Deque<T>);
-    method public static int binarySearch(java.util.List<? extends java.lang.Comparable<? super T>>, T);
-    method public static int binarySearch(java.util.List<? extends T>, T, java.util.Comparator<? super T>);
-    method public static java.util.Collection<E> checkedCollection(java.util.Collection<E>, java.lang.Class<E>);
-    method public static java.util.List<E> checkedList(java.util.List<E>, java.lang.Class<E>);
-    method public static java.util.Map<K, V> checkedMap(java.util.Map<K, V>, java.lang.Class<K>, java.lang.Class<V>);
-    method public static java.util.Set<E> checkedSet(java.util.Set<E>, java.lang.Class<E>);
-    method public static java.util.SortedMap<K, V> checkedSortedMap(java.util.SortedMap<K, V>, java.lang.Class<K>, java.lang.Class<V>);
-    method public static java.util.SortedSet<E> checkedSortedSet(java.util.SortedSet<E>, java.lang.Class<E>);
-    method public static void copy(java.util.List<? super T>, java.util.List<? extends T>);
+    method public static <T> boolean addAll(java.util.Collection<? super T>, T...);
+    method public static <T> java.util.Queue<T> asLifoQueue(java.util.Deque<T>);
+    method public static <T> int binarySearch(java.util.List<? extends java.lang.Comparable<? super T>>, T);
+    method public static <T> int binarySearch(java.util.List<? extends T>, T, java.util.Comparator<? super T>);
+    method public static <E> java.util.Collection<E> checkedCollection(java.util.Collection<E>, java.lang.Class<E>);
+    method public static <E> java.util.List<E> checkedList(java.util.List<E>, java.lang.Class<E>);
+    method public static <K, V> java.util.Map<K, V> checkedMap(java.util.Map<K, V>, java.lang.Class<K>, java.lang.Class<V>);
+    method public static <E> java.util.Set<E> checkedSet(java.util.Set<E>, java.lang.Class<E>);
+    method public static <K, V> java.util.SortedMap<K, V> checkedSortedMap(java.util.SortedMap<K, V>, java.lang.Class<K>, java.lang.Class<V>);
+    method public static <E> java.util.SortedSet<E> checkedSortedSet(java.util.SortedSet<E>, java.lang.Class<E>);
+    method public static <T> void copy(java.util.List<? super T>, java.util.List<? extends T>);
     method public static boolean disjoint(java.util.Collection<?>, java.util.Collection<?>);
-    method public static java.util.Enumeration<T> emptyEnumeration();
-    method public static java.util.Iterator<T> emptyIterator();
-    method public static final java.util.List<T> emptyList();
-    method public static java.util.ListIterator<T> emptyListIterator();
-    method public static final java.util.Map<K, V> emptyMap();
-    method public static final java.util.Set<T> emptySet();
-    method public static java.util.Enumeration<T> enumeration(java.util.Collection<T>);
-    method public static void fill(java.util.List<? super T>, T);
+    method public static <T> java.util.Enumeration<T> emptyEnumeration();
+    method public static <T> java.util.Iterator<T> emptyIterator();
+    method public static final <T> java.util.List<T> emptyList();
+    method public static <T> java.util.ListIterator<T> emptyListIterator();
+    method public static final <K, V> java.util.Map<K, V> emptyMap();
+    method public static final <T> java.util.Set<T> emptySet();
+    method public static <T> java.util.Enumeration<T> enumeration(java.util.Collection<T>);
+    method public static <T> void fill(java.util.List<? super T>, T);
     method public static int frequency(java.util.Collection<?>, java.lang.Object);
     method public static int indexOfSubList(java.util.List<?>, java.util.List<?>);
     method public static int lastIndexOfSubList(java.util.List<?>, java.util.List<?>);
-    method public static java.util.ArrayList<T> list(java.util.Enumeration<T>);
-    method public static T max(java.util.Collection<? extends T>);
-    method public static T max(java.util.Collection<? extends T>, java.util.Comparator<? super T>);
-    method public static T min(java.util.Collection<? extends T>);
-    method public static T min(java.util.Collection<? extends T>, java.util.Comparator<? super T>);
-    method public static java.util.List<T> nCopies(int, T);
-    method public static java.util.Set<E> newSetFromMap(java.util.Map<E, java.lang.Boolean>);
-    method public static boolean replaceAll(java.util.List<T>, T, T);
+    method public static <T> java.util.ArrayList<T> list(java.util.Enumeration<T>);
+    method public static <T extends java.lang.Object & java.lang.Comparable<? super T>> T max(java.util.Collection<? extends T>);
+    method public static <T> T max(java.util.Collection<? extends T>, java.util.Comparator<? super T>);
+    method public static <T extends java.lang.Object & java.lang.Comparable<? super T>> T min(java.util.Collection<? extends T>);
+    method public static <T> T min(java.util.Collection<? extends T>, java.util.Comparator<? super T>);
+    method public static <T> java.util.List<T> nCopies(int, T);
+    method public static <E> java.util.Set<E> newSetFromMap(java.util.Map<E, java.lang.Boolean>);
+    method public static <T> boolean replaceAll(java.util.List<T>, T, T);
     method public static void reverse(java.util.List<?>);
-    method public static java.util.Comparator<T> reverseOrder();
-    method public static java.util.Comparator<T> reverseOrder(java.util.Comparator<T>);
+    method public static <T> java.util.Comparator<T> reverseOrder();
+    method public static <T> java.util.Comparator<T> reverseOrder(java.util.Comparator<T>);
     method public static void rotate(java.util.List<?>, int);
     method public static void shuffle(java.util.List<?>);
     method public static void shuffle(java.util.List<?>, java.util.Random);
-    method public static java.util.Set<E> singleton(E);
-    method public static java.util.List<E> singletonList(E);
-    method public static java.util.Map<K, V> singletonMap(K, V);
-    method public static void sort(java.util.List<T>);
-    method public static void sort(java.util.List<T>, java.util.Comparator<? super T>);
+    method public static <E> java.util.Set<E> singleton(E);
+    method public static <E> java.util.List<E> singletonList(E);
+    method public static <K, V> java.util.Map<K, V> singletonMap(K, V);
+    method public static <T extends java.lang.Comparable<? super T>> void sort(java.util.List<T>);
+    method public static <T> void sort(java.util.List<T>, java.util.Comparator<? super T>);
     method public static void swap(java.util.List<?>, int, int);
-    method public static java.util.Collection<T> synchronizedCollection(java.util.Collection<T>);
-    method public static java.util.List<T> synchronizedList(java.util.List<T>);
-    method public static java.util.Map<K, V> synchronizedMap(java.util.Map<K, V>);
-    method public static java.util.Set<T> synchronizedSet(java.util.Set<T>);
-    method public static java.util.SortedMap<K, V> synchronizedSortedMap(java.util.SortedMap<K, V>);
-    method public static java.util.SortedSet<T> synchronizedSortedSet(java.util.SortedSet<T>);
-    method public static java.util.Collection<T> unmodifiableCollection(java.util.Collection<? extends T>);
-    method public static java.util.List<T> unmodifiableList(java.util.List<? extends T>);
-    method public static java.util.Map<K, V> unmodifiableMap(java.util.Map<? extends K, ? extends V>);
-    method public static java.util.Set<T> unmodifiableSet(java.util.Set<? extends T>);
-    method public static java.util.SortedMap<K, V> unmodifiableSortedMap(java.util.SortedMap<K, ? extends V>);
-    method public static java.util.SortedSet<T> unmodifiableSortedSet(java.util.SortedSet<T>);
+    method public static <T> java.util.Collection<T> synchronizedCollection(java.util.Collection<T>);
+    method public static <T> java.util.List<T> synchronizedList(java.util.List<T>);
+    method public static <K, V> java.util.Map<K, V> synchronizedMap(java.util.Map<K, V>);
+    method public static <T> java.util.Set<T> synchronizedSet(java.util.Set<T>);
+    method public static <K, V> java.util.SortedMap<K, V> synchronizedSortedMap(java.util.SortedMap<K, V>);
+    method public static <T> java.util.SortedSet<T> synchronizedSortedSet(java.util.SortedSet<T>);
+    method public static <T> java.util.Collection<T> unmodifiableCollection(java.util.Collection<? extends T>);
+    method public static <T> java.util.List<T> unmodifiableList(java.util.List<? extends T>);
+    method public static <K, V> java.util.Map<K, V> unmodifiableMap(java.util.Map<? extends K, ? extends V>);
+    method public static <T> java.util.Set<T> unmodifiableSet(java.util.Set<? extends T>);
+    method public static <K, V> java.util.SortedMap<K, V> unmodifiableSortedMap(java.util.SortedMap<K, ? extends V>);
+    method public static <T> java.util.SortedSet<T> unmodifiableSortedSet(java.util.SortedSet<T>);
     field public static final java.util.List EMPTY_LIST;
     field public static final java.util.Map EMPTY_MAP;
     field public static final java.util.Set EMPTY_SET;
   }
 
-  public abstract interface Comparator {
+  public abstract interface Comparator<T> {
     method public abstract int compare(T, T);
-    method public static java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
-    method public static java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>);
-    method public static java.util.Comparator<T> comparingDouble(java.util.function.ToDoubleFunction<? super T>);
-    method public static java.util.Comparator<T> comparingInt(java.util.function.ToIntFunction<? super T>);
-    method public static java.util.Comparator<T> comparingLong(java.util.function.ToLongFunction<? super T>);
+    method public static <T, U> java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
+    method public static <T, U extends java.lang.Comparable<? super U>> java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>);
+    method public static <T> java.util.Comparator<T> comparingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static <T> java.util.Comparator<T> comparingInt(java.util.function.ToIntFunction<? super T>);
+    method public static <T> java.util.Comparator<T> comparingLong(java.util.function.ToLongFunction<? super T>);
     method public abstract boolean equals(java.lang.Object);
-    method public static java.util.Comparator<T> naturalOrder();
-    method public static java.util.Comparator<T> nullsFirst(java.util.Comparator<? super T>);
-    method public static java.util.Comparator<T> nullsLast(java.util.Comparator<? super T>);
-    method public static java.util.Comparator<T> reverseOrder();
+    method public static <T extends java.lang.Comparable<? super T>> java.util.Comparator<T> naturalOrder();
+    method public static <T> java.util.Comparator<T> nullsFirst(java.util.Comparator<? super T>);
+    method public static <T> java.util.Comparator<T> nullsLast(java.util.Comparator<? super T>);
+    method public static <T extends java.lang.Comparable<? super T>> java.util.Comparator<T> reverseOrder();
     method public default java.util.Comparator<T> reversed();
     method public default java.util.Comparator<T> thenComparing(java.util.Comparator<? super T>);
-    method public default java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
-    method public default java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>);
+    method public default <U> java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
+    method public default <U extends java.lang.Comparable<? super U>> java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>);
     method public default java.util.Comparator<T> thenComparingDouble(java.util.function.ToDoubleFunction<? super T>);
     method public default java.util.Comparator<T> thenComparingInt(java.util.function.ToIntFunction<? super T>);
     method public default java.util.Comparator<T> thenComparingLong(java.util.function.ToLongFunction<? super T>);
@@ -62520,7 +62514,7 @@
     method public deprecated java.lang.String toLocaleString();
   }
 
-  public abstract interface Deque implements java.util.Queue {
+  public abstract interface Deque<E> implements java.util.Queue {
     method public abstract boolean add(E);
     method public abstract void addFirst(E);
     method public abstract void addLast(E);
@@ -62550,7 +62544,7 @@
     method public abstract int size();
   }
 
-  public abstract class Dictionary {
+  public abstract class Dictionary<K, V> {
     ctor public Dictionary();
     method public abstract java.util.Enumeration<V> elements();
     method public abstract V get(java.lang.Object);
@@ -62581,7 +62575,7 @@
     ctor public EmptyStackException();
   }
 
-  public class EnumMap extends java.util.AbstractMap implements java.lang.Cloneable java.io.Serializable {
+  public class EnumMap<K extends java.lang.Enum<K>, V> extends java.util.AbstractMap implements java.lang.Cloneable java.io.Serializable {
     ctor public EnumMap(java.lang.Class<K>);
     ctor public EnumMap(java.util.EnumMap<K, ? extends V>);
     ctor public EnumMap(java.util.Map<K, ? extends V>);
@@ -62589,23 +62583,23 @@
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
   }
 
-  public abstract class EnumSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable {
-    method public static java.util.EnumSet<E> allOf(java.lang.Class<E>);
+  public abstract class EnumSet<E extends java.lang.Enum<E>> extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable {
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> allOf(java.lang.Class<E>);
     method public java.util.EnumSet<E> clone();
-    method public static java.util.EnumSet<E> complementOf(java.util.EnumSet<E>);
-    method public static java.util.EnumSet<E> copyOf(java.util.EnumSet<E>);
-    method public static java.util.EnumSet<E> copyOf(java.util.Collection<E>);
-    method public static java.util.EnumSet<E> noneOf(java.lang.Class<E>);
-    method public static java.util.EnumSet<E> of(E);
-    method public static java.util.EnumSet<E> of(E, E);
-    method public static java.util.EnumSet<E> of(E, E, E);
-    method public static java.util.EnumSet<E> of(E, E, E, E);
-    method public static java.util.EnumSet<E> of(E, E, E, E, E);
-    method public static java.util.EnumSet<E> of(E, E...);
-    method public static java.util.EnumSet<E> range(E, E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> complementOf(java.util.EnumSet<E>);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> copyOf(java.util.EnumSet<E>);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> copyOf(java.util.Collection<E>);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> noneOf(java.lang.Class<E>);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E, E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E, E, E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E, E, E, E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E, E, E, E, E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E, E...);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> range(E, E);
   }
 
-  public abstract interface Enumeration {
+  public abstract interface Enumeration<E> {
     method public abstract boolean hasMoreElements();
     method public abstract E nextElement();
   }
@@ -62613,7 +62607,7 @@
   public abstract interface EventListener {
   }
 
-  public abstract class EventListenerProxy implements java.util.EventListener {
+  public abstract class EventListenerProxy<T extends java.util.EventListener> implements java.util.EventListener {
     ctor public EventListenerProxy(T);
     method public T getListener();
   }
@@ -62699,7 +62693,7 @@
     field public static final int BC = 0; // 0x0
   }
 
-  public class HashMap extends java.util.AbstractMap implements java.lang.Cloneable java.util.Map java.io.Serializable {
+  public class HashMap<K, V> extends java.util.AbstractMap implements java.lang.Cloneable java.util.Map java.io.Serializable {
     ctor public HashMap(int, float);
     ctor public HashMap(int);
     ctor public HashMap();
@@ -62719,7 +62713,7 @@
     method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
   }
 
-  public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
+  public class HashSet<E> extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
     ctor public HashSet();
     ctor public HashSet(java.util.Collection<? extends E>);
     ctor public HashSet(int, float);
@@ -62730,7 +62724,7 @@
     method public java.util.Spliterator<E> spliterator();
   }
 
-  public class Hashtable extends java.util.Dictionary implements java.lang.Cloneable java.util.Map java.io.Serializable {
+  public class Hashtable<K, V> extends java.util.Dictionary implements java.lang.Cloneable java.util.Map java.io.Serializable {
     ctor public Hashtable(int, float);
     ctor public Hashtable(int);
     ctor public Hashtable();
@@ -62765,7 +62759,7 @@
     method public java.util.Collection<V> values();
   }
 
-  public class IdentityHashMap extends java.util.AbstractMap implements java.lang.Cloneable java.util.Map java.io.Serializable {
+  public class IdentityHashMap<K, V> extends java.util.AbstractMap implements java.lang.Cloneable java.util.Map java.io.Serializable {
     ctor public IdentityHashMap();
     ctor public IdentityHashMap(int);
     ctor public IdentityHashMap(java.util.Map<? extends K, ? extends V>);
@@ -62832,14 +62826,14 @@
     ctor public InvalidPropertiesFormatException(java.lang.String);
   }
 
-  public abstract interface Iterator {
+  public abstract interface Iterator<E> {
     method public default void forEachRemaining(java.util.function.Consumer<? super E>);
     method public abstract boolean hasNext();
     method public abstract E next();
     method public default void remove();
   }
 
-  public class LinkedHashMap extends java.util.HashMap implements java.util.Map {
+  public class LinkedHashMap<K, V> extends java.util.HashMap implements java.util.Map {
     ctor public LinkedHashMap(int, float);
     ctor public LinkedHashMap(int);
     ctor public LinkedHashMap();
@@ -62848,14 +62842,14 @@
     method protected boolean removeEldestEntry(java.util.Map.Entry<K, V>);
   }
 
-  public class LinkedHashSet extends java.util.HashSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
+  public class LinkedHashSet<E> extends java.util.HashSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
     ctor public LinkedHashSet(int, float);
     ctor public LinkedHashSet(int);
     ctor public LinkedHashSet();
     ctor public LinkedHashSet(java.util.Collection<? extends E>);
   }
 
-  public class LinkedList extends java.util.AbstractSequentialList implements java.lang.Cloneable java.util.Deque java.util.List java.io.Serializable {
+  public class LinkedList<E> extends java.util.AbstractSequentialList implements java.lang.Cloneable java.util.Deque java.util.List java.io.Serializable {
     ctor public LinkedList();
     ctor public LinkedList(java.util.Collection<? extends E>);
     method public void addFirst(E);
@@ -62886,7 +62880,7 @@
     method public java.util.Spliterator<E> spliterator();
   }
 
-  public abstract interface List implements java.util.Collection {
+  public abstract interface List<E> implements java.util.Collection {
     method public abstract boolean add(E);
     method public abstract void add(int, E);
     method public abstract boolean addAll(java.util.Collection<? extends E>);
@@ -62913,10 +62907,10 @@
     method public default void sort(java.util.Comparator<? super E>);
     method public abstract java.util.List<E> subList(int, int);
     method public abstract java.lang.Object[] toArray();
-    method public abstract T[] toArray(T[]);
+    method public abstract <T> T[] toArray(T[]);
   }
 
-  public abstract interface ListIterator implements java.util.Iterator {
+  public abstract interface ListIterator<E> implements java.util.Iterator {
     method public abstract void add(E);
     method public abstract boolean hasNext();
     method public abstract boolean hasPrevious();
@@ -63033,7 +63027,7 @@
     method public final long getSum();
   }
 
-  public abstract interface Map {
+  public abstract interface Map<K, V> {
     method public abstract void clear();
     method public default V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public default V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
@@ -63061,11 +63055,11 @@
     method public abstract java.util.Collection<V> values();
   }
 
-  public static abstract interface Map.Entry {
-    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey();
-    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>);
-    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue();
-    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(java.util.Comparator<? super V>);
+  public static abstract interface Map.Entry<K, V> {
+    method public static <K extends java.lang.Comparable<? super K>, V> java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey();
+    method public static <K, V> java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>);
+    method public static <K, V extends java.lang.Comparable<? super V>> java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue();
+    method public static <K, V> java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(java.util.Comparator<? super V>);
     method public abstract boolean equals(java.lang.Object);
     method public abstract K getKey();
     method public abstract V getValue();
@@ -63089,7 +63083,7 @@
     method public java.lang.String getKey();
   }
 
-  public abstract interface NavigableMap implements java.util.SortedMap {
+  public abstract interface NavigableMap<K, V> implements java.util.SortedMap {
     method public abstract java.util.Map.Entry<K, V> ceilingEntry(K);
     method public abstract K ceilingKey(K);
     method public abstract java.util.NavigableSet<K> descendingKeySet();
@@ -63113,7 +63107,7 @@
     method public abstract java.util.SortedMap<K, V> tailMap(K);
   }
 
-  public abstract interface NavigableSet implements java.util.SortedSet {
+  public abstract interface NavigableSet<E> implements java.util.SortedSet {
     method public abstract E ceiling(E);
     method public abstract java.util.Iterator<E> descendingIterator();
     method public abstract java.util.NavigableSet<E> descendingSet();
@@ -63137,16 +63131,16 @@
   }
 
   public final class Objects {
-    method public static int compare(T, T, java.util.Comparator<? super T>);
+    method public static <T> int compare(T, T, java.util.Comparator<? super T>);
     method public static boolean deepEquals(java.lang.Object, java.lang.Object);
     method public static boolean equals(java.lang.Object, java.lang.Object);
     method public static int hash(java.lang.Object...);
     method public static int hashCode(java.lang.Object);
     method public static boolean isNull(java.lang.Object);
     method public static boolean nonNull(java.lang.Object);
-    method public static T requireNonNull(T);
-    method public static T requireNonNull(T, java.lang.String);
-    method public static T requireNonNull(T, java.util.function.Supplier<java.lang.String>);
+    method public static <T> T requireNonNull(T);
+    method public static <T> T requireNonNull(T, java.lang.String);
+    method public static <T> T requireNonNull(T, java.util.function.Supplier<java.lang.String>);
     method public static java.lang.String toString(java.lang.Object);
     method public static java.lang.String toString(java.lang.Object, java.lang.String);
   }
@@ -63168,19 +63162,19 @@
     method public abstract void update(java.util.Observable, java.lang.Object);
   }
 
-  public final class Optional {
-    method public static java.util.Optional<T> empty();
+  public final class Optional<T> {
+    method public static <T> java.util.Optional<T> empty();
     method public java.util.Optional<T> filter(java.util.function.Predicate<? super T>);
-    method public java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
+    method public <U> java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
     method public T get();
     method public void ifPresent(java.util.function.Consumer<? super T>);
     method public boolean isPresent();
-    method public java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
-    method public static java.util.Optional<T> of(T);
-    method public static java.util.Optional<T> ofNullable(T);
+    method public <U> java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
+    method public static <T> java.util.Optional<T> of(T);
+    method public static <T> java.util.Optional<T> ofNullable(T);
     method public T orElse(T);
     method public T orElseGet(java.util.function.Supplier<? extends T>);
-    method public T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
+    method public <X extends java.lang.Throwable> T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
   }
 
   public final class OptionalDouble {
@@ -63191,7 +63185,7 @@
     method public static java.util.OptionalDouble of(double);
     method public double orElse(double);
     method public double orElseGet(java.util.function.DoubleSupplier);
-    method public double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+    method public <X extends java.lang.Throwable> double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
   }
 
   public final class OptionalInt {
@@ -63202,7 +63196,7 @@
     method public static java.util.OptionalInt of(int);
     method public int orElse(int);
     method public int orElseGet(java.util.function.IntSupplier);
-    method public int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+    method public <X extends java.lang.Throwable> int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
   }
 
   public final class OptionalLong {
@@ -63213,10 +63207,10 @@
     method public static java.util.OptionalLong of(long);
     method public long orElse(long);
     method public long orElseGet(java.util.function.LongSupplier);
-    method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+    method public <X extends java.lang.Throwable> long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
   }
 
-  public abstract interface PrimitiveIterator implements java.util.Iterator {
+  public abstract interface PrimitiveIterator<T, T_CONS> implements java.util.Iterator {
     method public abstract void forEachRemaining(T_CONS);
   }
 
@@ -63241,7 +63235,7 @@
     method public abstract long nextLong();
   }
 
-  public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
+  public class PriorityQueue<E> extends java.util.AbstractQueue implements java.io.Serializable {
     ctor public PriorityQueue();
     ctor public PriorityQueue(int);
     ctor public PriorityQueue(java.util.Comparator<? super E>);
@@ -63290,7 +63284,7 @@
     method public java.lang.Object handleGetObject(java.lang.String);
   }
 
-  public abstract interface Queue implements java.util.Collection {
+  public abstract interface Queue<E> implements java.util.Collection {
     method public abstract boolean add(E);
     method public abstract E element();
     method public abstract boolean offer(E);
@@ -63334,6 +63328,7 @@
     method public static final void clearCache();
     method public static final void clearCache(java.lang.ClassLoader);
     method public boolean containsKey(java.lang.String);
+    method public java.lang.String getBaseBundleName();
     method public static final java.util.ResourceBundle getBundle(java.lang.String);
     method public static final java.util.ResourceBundle getBundle(java.lang.String, java.util.ResourceBundle.Control);
     method public static final java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale);
@@ -63442,15 +63437,15 @@
     ctor public ServiceConfigurationError(java.lang.String, java.lang.Throwable);
   }
 
-  public final class ServiceLoader implements java.lang.Iterable {
+  public final class ServiceLoader<S> implements java.lang.Iterable {
     method public java.util.Iterator<S> iterator();
-    method public static java.util.ServiceLoader<S> load(java.lang.Class<S>, java.lang.ClassLoader);
-    method public static java.util.ServiceLoader<S> load(java.lang.Class<S>);
-    method public static java.util.ServiceLoader<S> loadInstalled(java.lang.Class<S>);
+    method public static <S> java.util.ServiceLoader<S> load(java.lang.Class<S>, java.lang.ClassLoader);
+    method public static <S> java.util.ServiceLoader<S> load(java.lang.Class<S>);
+    method public static <S> java.util.ServiceLoader<S> loadInstalled(java.lang.Class<S>);
     method public void reload();
   }
 
-  public abstract interface Set implements java.util.Collection {
+  public abstract interface Set<E> implements java.util.Collection {
     method public abstract boolean add(E);
     method public abstract boolean addAll(java.util.Collection<? extends E>);
     method public abstract void clear();
@@ -63465,7 +63460,7 @@
     method public abstract boolean retainAll(java.util.Collection<?>);
     method public abstract int size();
     method public abstract java.lang.Object[] toArray();
-    method public abstract T[] toArray(T[]);
+    method public abstract <T> T[] toArray(T[]);
   }
 
   public class SimpleTimeZone extends java.util.TimeZone {
@@ -63491,7 +63486,7 @@
     field public static final int WALL_TIME = 0; // 0x0
   }
 
-  public abstract interface SortedMap implements java.util.Map {
+  public abstract interface SortedMap<K, V> implements java.util.Map {
     method public abstract java.util.Comparator<? super K> comparator();
     method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public abstract K firstKey();
@@ -63503,7 +63498,7 @@
     method public abstract java.util.Collection<V> values();
   }
 
-  public abstract interface SortedSet implements java.util.Set {
+  public abstract interface SortedSet<E> implements java.util.Set {
     method public abstract java.util.Comparator<? super E> comparator();
     method public abstract E first();
     method public abstract java.util.SortedSet<E> headSet(E);
@@ -63512,7 +63507,7 @@
     method public abstract java.util.SortedSet<E> tailSet(E);
   }
 
-  public abstract interface Spliterator {
+  public abstract interface Spliterator<T> {
     method public abstract int characteristics();
     method public abstract long estimateSize();
     method public default void forEachRemaining(java.util.function.Consumer<? super T>);
@@ -63555,7 +63550,7 @@
     method public abstract java.util.Spliterator.OfLong trySplit();
   }
 
-  public static abstract interface Spliterator.OfPrimitive implements java.util.Spliterator {
+  public static abstract interface Spliterator.OfPrimitive<T, T_CONS, T_SPLITR extends java.util.Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>> implements java.util.Spliterator {
     method public default void forEachRemaining(T_CONS);
     method public abstract boolean tryAdvance(T_CONS);
     method public abstract T_SPLITR trySplit();
@@ -63565,25 +63560,25 @@
     method public static java.util.Spliterator.OfDouble emptyDoubleSpliterator();
     method public static java.util.Spliterator.OfInt emptyIntSpliterator();
     method public static java.util.Spliterator.OfLong emptyLongSpliterator();
-    method public static java.util.Spliterator<T> emptySpliterator();
-    method public static java.util.Iterator<T> iterator(java.util.Spliterator<? extends T>);
+    method public static <T> java.util.Spliterator<T> emptySpliterator();
+    method public static <T> java.util.Iterator<T> iterator(java.util.Spliterator<? extends T>);
     method public static java.util.PrimitiveIterator.OfInt iterator(java.util.Spliterator.OfInt);
     method public static java.util.PrimitiveIterator.OfLong iterator(java.util.Spliterator.OfLong);
     method public static java.util.PrimitiveIterator.OfDouble iterator(java.util.Spliterator.OfDouble);
-    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int);
-    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int, int, int);
+    method public static <T> java.util.Spliterator<T> spliterator(java.lang.Object[], int);
+    method public static <T> java.util.Spliterator<T> spliterator(java.lang.Object[], int, int, int);
     method public static java.util.Spliterator.OfInt spliterator(int[], int);
     method public static java.util.Spliterator.OfInt spliterator(int[], int, int, int);
     method public static java.util.Spliterator.OfLong spliterator(long[], int);
     method public static java.util.Spliterator.OfLong spliterator(long[], int, int, int);
     method public static java.util.Spliterator.OfDouble spliterator(double[], int);
     method public static java.util.Spliterator.OfDouble spliterator(double[], int, int, int);
-    method public static java.util.Spliterator<T> spliterator(java.util.Collection<? extends T>, int);
-    method public static java.util.Spliterator<T> spliterator(java.util.Iterator<? extends T>, long, int);
+    method public static <T> java.util.Spliterator<T> spliterator(java.util.Collection<? extends T>, int);
+    method public static <T> java.util.Spliterator<T> spliterator(java.util.Iterator<? extends T>, long, int);
     method public static java.util.Spliterator.OfInt spliterator(java.util.PrimitiveIterator.OfInt, long, int);
     method public static java.util.Spliterator.OfLong spliterator(java.util.PrimitiveIterator.OfLong, long, int);
     method public static java.util.Spliterator.OfDouble spliterator(java.util.PrimitiveIterator.OfDouble, long, int);
-    method public static java.util.Spliterator<T> spliteratorUnknownSize(java.util.Iterator<? extends T>, int);
+    method public static <T> java.util.Spliterator<T> spliteratorUnknownSize(java.util.Iterator<? extends T>, int);
     method public static java.util.Spliterator.OfInt spliteratorUnknownSize(java.util.PrimitiveIterator.OfInt, int);
     method public static java.util.Spliterator.OfLong spliteratorUnknownSize(java.util.PrimitiveIterator.OfLong, int);
     method public static java.util.Spliterator.OfDouble spliteratorUnknownSize(java.util.PrimitiveIterator.OfDouble, int);
@@ -63610,7 +63605,7 @@
     method public java.util.Spliterator.OfLong trySplit();
   }
 
-  public static abstract class Spliterators.AbstractSpliterator implements java.util.Spliterator {
+  public static abstract class Spliterators.AbstractSpliterator<T> implements java.util.Spliterator {
     ctor protected Spliterators.AbstractSpliterator(long, int);
     method public int characteristics();
     method public long estimateSize();
@@ -63645,7 +63640,7 @@
     method public java.util.SplittableRandom split();
   }
 
-  public class Stack extends java.util.Vector {
+  public class Stack<E> extends java.util.Vector {
     ctor public Stack();
     method public boolean empty();
     method public synchronized E peek();
@@ -63729,7 +63724,7 @@
     ctor public TooManyListenersException(java.lang.String);
   }
 
-  public class TreeMap extends java.util.AbstractMap implements java.lang.Cloneable java.util.NavigableMap java.io.Serializable {
+  public class TreeMap<K, V> extends java.util.AbstractMap implements java.lang.Cloneable java.util.NavigableMap java.io.Serializable {
     ctor public TreeMap();
     ctor public TreeMap(java.util.Comparator<? super K>);
     ctor public TreeMap(java.util.Map<? extends K, ? extends V>);
@@ -63766,7 +63761,7 @@
     method public java.util.SortedMap<K, V> tailMap(K);
   }
 
-  public class TreeSet extends java.util.AbstractSet implements java.lang.Cloneable java.util.NavigableSet java.io.Serializable {
+  public class TreeSet<E> extends java.util.AbstractSet implements java.lang.Cloneable java.util.NavigableSet java.io.Serializable {
     ctor public TreeSet();
     ctor public TreeSet(java.util.Comparator<? super E>);
     ctor public TreeSet(java.util.Collection<? extends E>);
@@ -63819,7 +63814,7 @@
     method public java.lang.String getFlags();
   }
 
-  public class Vector extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
+  public class Vector<E> extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
     ctor public Vector(int, int);
     ctor public Vector(int);
     ctor public Vector();
@@ -63854,7 +63849,7 @@
     field protected java.lang.Object[] elementData;
   }
 
-  public class WeakHashMap extends java.util.AbstractMap implements java.util.Map {
+  public class WeakHashMap<K, V> extends java.util.AbstractMap implements java.util.Map {
     ctor public WeakHashMap(int, float);
     ctor public WeakHashMap(int);
     ctor public WeakHashMap();
@@ -63870,18 +63865,18 @@
 
   public abstract class AbstractExecutorService implements java.util.concurrent.ExecutorService {
     ctor public AbstractExecutorService();
-    method public java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.lang.InterruptedException;
-    method public java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
-    method public T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
-    method public T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
-    method protected java.util.concurrent.RunnableFuture<T> newTaskFor(java.lang.Runnable, T);
-    method protected java.util.concurrent.RunnableFuture<T> newTaskFor(java.util.concurrent.Callable<T>);
+    method public <T> java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.lang.InterruptedException;
+    method public <T> java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public <T> T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public <T> T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method protected <T> java.util.concurrent.RunnableFuture<T> newTaskFor(java.lang.Runnable, T);
+    method protected <T> java.util.concurrent.RunnableFuture<T> newTaskFor(java.util.concurrent.Callable<T>);
     method public java.util.concurrent.Future<?> submit(java.lang.Runnable);
-    method public java.util.concurrent.Future<T> submit(java.lang.Runnable, T);
-    method public java.util.concurrent.Future<T> submit(java.util.concurrent.Callable<T>);
+    method public <T> java.util.concurrent.Future<T> submit(java.lang.Runnable, T);
+    method public <T> java.util.concurrent.Future<T> submit(java.util.concurrent.Callable<T>);
   }
 
-  public class ArrayBlockingQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
+  public class ArrayBlockingQueue<E> extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
     ctor public ArrayBlockingQueue(int);
     ctor public ArrayBlockingQueue(int, boolean);
     ctor public ArrayBlockingQueue(int, boolean, java.util.Collection<? extends E>);
@@ -63900,7 +63895,7 @@
     method public E take() throws java.lang.InterruptedException;
   }
 
-  public abstract interface BlockingDeque implements java.util.concurrent.BlockingQueue java.util.Deque {
+  public abstract interface BlockingDeque<E> implements java.util.concurrent.BlockingQueue java.util.Deque {
     method public abstract boolean add(E);
     method public abstract void addFirst(E);
     method public abstract void addLast(E);
@@ -63932,7 +63927,7 @@
     method public abstract E takeLast() throws java.lang.InterruptedException;
   }
 
-  public abstract interface BlockingQueue implements java.util.Queue {
+  public abstract interface BlockingQueue<E> implements java.util.Queue {
     method public abstract boolean add(E);
     method public abstract boolean contains(java.lang.Object);
     method public abstract int drainTo(java.util.Collection<? super E>);
@@ -63951,7 +63946,7 @@
     ctor public BrokenBarrierException(java.lang.String);
   }
 
-  public abstract interface Callable {
+  public abstract interface Callable<V> {
     method public abstract V call() throws java.lang.Exception;
   }
 
@@ -63960,28 +63955,28 @@
     ctor public CancellationException(java.lang.String);
   }
 
-  public class CompletableFuture implements java.util.concurrent.CompletionStage java.util.concurrent.Future {
+  public class CompletableFuture<T> implements java.util.concurrent.CompletionStage java.util.concurrent.Future {
     ctor public CompletableFuture();
     method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
     method public static java.util.concurrent.CompletableFuture<java.lang.Void> allOf(java.util.concurrent.CompletableFuture<?>...);
     method public static java.util.concurrent.CompletableFuture<java.lang.Object> anyOf(java.util.concurrent.CompletableFuture<?>...);
-    method public java.util.concurrent.CompletableFuture<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
-    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
-    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public <U> java.util.concurrent.CompletableFuture<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
     method public boolean cancel(boolean);
     method public boolean complete(T);
     method public boolean completeExceptionally(java.lang.Throwable);
-    method public static java.util.concurrent.CompletableFuture<U> completedFuture(U);
+    method public static <U> java.util.concurrent.CompletableFuture<U> completedFuture(U);
     method public java.util.concurrent.CompletableFuture<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
     method public T get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
     method public T get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
     method public T getNow(T);
     method public int getNumberOfDependents();
-    method public java.util.concurrent.CompletableFuture<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
-    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
-    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public <U> java.util.concurrent.CompletableFuture<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
     method public boolean isCancelled();
     method public boolean isCompletedExceptionally();
     method public boolean isDone();
@@ -63996,23 +63991,23 @@
     method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
     method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable);
     method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable, java.util.concurrent.Executor);
-    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>);
-    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>, java.util.concurrent.Executor);
+    method public static <U> java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>);
+    method public static <U> java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>, java.util.concurrent.Executor);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
-    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
-    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
-    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
-    method public java.util.concurrent.CompletableFuture<U> thenApply(java.util.function.Function<? super T, ? extends U>);
-    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
-    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
-    method public java.util.concurrent.CompletableFuture<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
-    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
-    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
-    method public java.util.concurrent.CompletableFuture<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
-    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
-    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public <U> java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public <U> java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public <U> java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public <U, V> java.util.concurrent.CompletableFuture<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public <U, V> java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public <U, V> java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRun(java.lang.Runnable);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
@@ -64032,7 +64027,7 @@
     ctor public CompletionException(java.lang.Throwable);
   }
 
-  public abstract interface CompletionService {
+  public abstract interface CompletionService<V> {
     method public abstract java.util.concurrent.Future<V> poll();
     method public abstract java.util.concurrent.Future<V> poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
     method public abstract java.util.concurrent.Future<V> submit(java.util.concurrent.Callable<V>);
@@ -64040,17 +64035,17 @@
     method public abstract java.util.concurrent.Future<V> take() throws java.lang.InterruptedException;
   }
 
-  public abstract interface CompletionStage {
+  public abstract interface CompletionStage<T> {
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
-    method public abstract java.util.concurrent.CompletionStage<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
-    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
-    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
     method public abstract java.util.concurrent.CompletionStage<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
-    method public abstract java.util.concurrent.CompletionStage<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
-    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
-    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
@@ -64060,18 +64055,18 @@
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
-    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
-    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
-    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
-    method public abstract java.util.concurrent.CompletionStage<U> thenApply(java.util.function.Function<? super T, ? extends U>);
-    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
-    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
-    method public abstract java.util.concurrent.CompletionStage<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
-    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
-    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
-    method public abstract java.util.concurrent.CompletionStage<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
-    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
-    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public abstract <U> java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public abstract <U, V> java.util.concurrent.CompletionStage<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract <U, V> java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract <U, V> java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRun(java.lang.Runnable);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
@@ -64081,7 +64076,7 @@
     method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor);
   }
 
-  public class ConcurrentHashMap extends java.util.AbstractMap implements java.util.concurrent.ConcurrentMap java.io.Serializable {
+  public class ConcurrentHashMap<K, V> extends java.util.AbstractMap implements java.util.concurrent.ConcurrentMap java.io.Serializable {
     ctor public ConcurrentHashMap();
     ctor public ConcurrentHashMap(int);
     ctor public ConcurrentHashMap(java.util.Map<? extends K, ? extends V>);
@@ -64095,29 +64090,29 @@
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public void forEach(long, java.util.function.BiConsumer<? super K, ? super V>);
-    method public void forEach(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public <U> void forEach(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.Consumer<? super U>);
     method public void forEachEntry(long, java.util.function.Consumer<? super java.util.Map.Entry<K, V>>);
-    method public void forEachEntry(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.Consumer<? super U>);
+    method public <U> void forEachEntry(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.Consumer<? super U>);
     method public void forEachKey(long, java.util.function.Consumer<? super K>);
-    method public void forEachKey(long, java.util.function.Function<? super K, ? extends U>, java.util.function.Consumer<? super U>);
+    method public <U> void forEachKey(long, java.util.function.Function<? super K, ? extends U>, java.util.function.Consumer<? super U>);
     method public void forEachValue(long, java.util.function.Consumer<? super V>);
-    method public void forEachValue(long, java.util.function.Function<? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public <U> void forEachValue(long, java.util.function.Function<? super V, ? extends U>, java.util.function.Consumer<? super U>);
     method public V getOrDefault(java.lang.Object, V);
     method public java.util.concurrent.ConcurrentHashMap.KeySetView<K, V> keySet(V);
     method public java.util.Enumeration<K> keys();
     method public long mappingCount();
     method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
-    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet();
-    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(int);
+    method public static <K> java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet();
+    method public static <K> java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(int);
     method public V putIfAbsent(K, V);
-    method public U reduce(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public <U> U reduce(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
     method public java.util.Map.Entry<K, V> reduceEntries(long, java.util.function.BiFunction<java.util.Map.Entry<K, V>, java.util.Map.Entry<K, V>, ? extends java.util.Map.Entry<K, V>>);
-    method public U reduceEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public <U> U reduceEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
     method public double reduceEntriesToDouble(long, java.util.function.ToDoubleFunction<java.util.Map.Entry<K, V>>, double, java.util.function.DoubleBinaryOperator);
     method public int reduceEntriesToInt(long, java.util.function.ToIntFunction<java.util.Map.Entry<K, V>>, int, java.util.function.IntBinaryOperator);
     method public long reduceEntriesToLong(long, java.util.function.ToLongFunction<java.util.Map.Entry<K, V>>, long, java.util.function.LongBinaryOperator);
     method public K reduceKeys(long, java.util.function.BiFunction<? super K, ? super K, ? extends K>);
-    method public U reduceKeys(long, java.util.function.Function<? super K, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public <U> U reduceKeys(long, java.util.function.Function<? super K, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
     method public double reduceKeysToDouble(long, java.util.function.ToDoubleFunction<? super K>, double, java.util.function.DoubleBinaryOperator);
     method public int reduceKeysToInt(long, java.util.function.ToIntFunction<? super K>, int, java.util.function.IntBinaryOperator);
     method public long reduceKeysToLong(long, java.util.function.ToLongFunction<? super K>, long, java.util.function.LongBinaryOperator);
@@ -64125,7 +64120,7 @@
     method public int reduceToInt(long, java.util.function.ToIntBiFunction<? super K, ? super V>, int, java.util.function.IntBinaryOperator);
     method public long reduceToLong(long, java.util.function.ToLongBiFunction<? super K, ? super V>, long, java.util.function.LongBinaryOperator);
     method public V reduceValues(long, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
-    method public U reduceValues(long, java.util.function.Function<? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public <U> U reduceValues(long, java.util.function.Function<? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
     method public double reduceValuesToDouble(long, java.util.function.ToDoubleFunction<? super V>, double, java.util.function.DoubleBinaryOperator);
     method public int reduceValuesToInt(long, java.util.function.ToIntFunction<? super V>, int, java.util.function.IntBinaryOperator);
     method public long reduceValuesToLong(long, java.util.function.ToLongFunction<? super V>, long, java.util.function.LongBinaryOperator);
@@ -64133,13 +64128,13 @@
     method public boolean replace(K, V, V);
     method public V replace(K, V);
     method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
-    method public U search(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>);
-    method public U searchEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>);
-    method public U searchKeys(long, java.util.function.Function<? super K, ? extends U>);
-    method public U searchValues(long, java.util.function.Function<? super V, ? extends U>);
+    method public <U> U search(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>);
+    method public <U> U searchEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>);
+    method public <U> U searchKeys(long, java.util.function.Function<? super K, ? extends U>);
+    method public <U> U searchValues(long, java.util.function.Function<? super V, ? extends U>);
   }
 
-   static abstract class ConcurrentHashMap.CollectionView implements java.util.Collection java.io.Serializable {
+   static abstract class ConcurrentHashMap.CollectionView<K, V, E> implements java.util.Collection java.io.Serializable {
     method public final void clear();
     method public abstract boolean contains(java.lang.Object);
     method public final boolean containsAll(java.util.Collection<?>);
@@ -64151,11 +64146,11 @@
     method public final boolean retainAll(java.util.Collection<?>);
     method public final int size();
     method public final java.lang.Object[] toArray();
-    method public final T[] toArray(T[]);
+    method public final <T> T[] toArray(T[]);
     method public final java.lang.String toString();
   }
 
-  public static class ConcurrentHashMap.KeySetView extends java.util.concurrent.ConcurrentHashMap.CollectionView implements java.io.Serializable java.util.Set {
+  public static class ConcurrentHashMap.KeySetView<K, V> extends java.util.concurrent.ConcurrentHashMap.CollectionView implements java.io.Serializable java.util.Set {
     method public boolean add(K);
     method public boolean addAll(java.util.Collection<? extends K>);
     method public boolean contains(java.lang.Object);
@@ -64166,7 +64161,7 @@
     method public java.util.Spliterator<K> spliterator();
   }
 
-  public class ConcurrentLinkedDeque extends java.util.AbstractCollection implements java.util.Deque java.io.Serializable {
+  public class ConcurrentLinkedDeque<E> extends java.util.AbstractCollection implements java.util.Deque java.io.Serializable {
     ctor public ConcurrentLinkedDeque();
     ctor public ConcurrentLinkedDeque(java.util.Collection<? extends E>);
     method public void addFirst(E);
@@ -64196,7 +64191,7 @@
     method public java.util.Spliterator<E> spliterator();
   }
 
-  public class ConcurrentLinkedQueue extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable {
+  public class ConcurrentLinkedQueue<E> extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable {
     ctor public ConcurrentLinkedQueue();
     ctor public ConcurrentLinkedQueue(java.util.Collection<? extends E>);
     method public java.util.Iterator<E> iterator();
@@ -64207,14 +64202,14 @@
     method public java.util.Spliterator<E> spliterator();
   }
 
-  public abstract interface ConcurrentMap implements java.util.Map {
+  public abstract interface ConcurrentMap<K, V> implements java.util.Map {
     method public abstract V putIfAbsent(K, V);
     method public abstract boolean remove(java.lang.Object, java.lang.Object);
     method public abstract boolean replace(K, V, V);
     method public abstract V replace(K, V);
   }
 
-  public abstract interface ConcurrentNavigableMap implements java.util.concurrent.ConcurrentMap java.util.NavigableMap {
+  public abstract interface ConcurrentNavigableMap<K, V> implements java.util.concurrent.ConcurrentMap java.util.NavigableMap {
     method public abstract java.util.NavigableSet<K> descendingKeySet();
     method public abstract java.util.concurrent.ConcurrentNavigableMap<K, V> descendingMap();
     method public abstract java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K, boolean);
@@ -64227,7 +64222,7 @@
     method public abstract java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K);
   }
 
-  public class ConcurrentSkipListMap extends java.util.AbstractMap implements java.lang.Cloneable java.util.concurrent.ConcurrentNavigableMap java.io.Serializable {
+  public class ConcurrentSkipListMap<K, V> extends java.util.AbstractMap implements java.lang.Cloneable java.util.concurrent.ConcurrentNavigableMap java.io.Serializable {
     ctor public ConcurrentSkipListMap();
     ctor public ConcurrentSkipListMap(java.util.Comparator<? super K>);
     ctor public ConcurrentSkipListMap(java.util.Map<? extends K, ? extends V>);
@@ -64271,7 +64266,7 @@
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K);
   }
 
-  public class ConcurrentSkipListSet extends java.util.AbstractSet implements java.lang.Cloneable java.util.NavigableSet java.io.Serializable {
+  public class ConcurrentSkipListSet<E> extends java.util.AbstractSet implements java.lang.Cloneable java.util.NavigableSet java.io.Serializable {
     ctor public ConcurrentSkipListSet();
     ctor public ConcurrentSkipListSet(java.util.Comparator<? super E>);
     ctor public ConcurrentSkipListSet(java.util.Collection<? extends E>);
@@ -64299,7 +64294,7 @@
     method public java.util.NavigableSet<E> tailSet(E);
   }
 
-  public class CopyOnWriteArrayList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
+  public class CopyOnWriteArrayList<E> implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
     ctor public CopyOnWriteArrayList();
     ctor public CopyOnWriteArrayList(java.util.Collection<? extends E>);
     ctor public CopyOnWriteArrayList(E[]);
@@ -64331,10 +64326,10 @@
     method public int size();
     method public java.util.List<E> subList(int, int);
     method public java.lang.Object[] toArray();
-    method public T[] toArray(T[]);
+    method public <T> T[] toArray(T[]);
   }
 
-  public class CopyOnWriteArraySet extends java.util.AbstractSet implements java.io.Serializable {
+  public class CopyOnWriteArraySet<E> extends java.util.AbstractSet implements java.io.Serializable {
     ctor public CopyOnWriteArraySet();
     ctor public CopyOnWriteArraySet(java.util.Collection<? extends E>);
     method public void forEach(java.util.function.Consumer<? super E>);
@@ -64352,7 +64347,7 @@
     method public long getCount();
   }
 
-  public abstract class CountedCompleter extends java.util.concurrent.ForkJoinTask {
+  public abstract class CountedCompleter<T> extends java.util.concurrent.ForkJoinTask {
     ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>, int);
     ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>);
     ctor protected CountedCompleter();
@@ -64389,7 +64384,7 @@
     method public void reset();
   }
 
-  public class DelayQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue {
+  public class DelayQueue<E extends java.util.concurrent.Delayed> extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue {
     ctor public DelayQueue();
     ctor public DelayQueue(java.util.Collection<? extends E>);
     method public int drainTo(java.util.Collection<? super E>);
@@ -64410,7 +64405,7 @@
     method public abstract long getDelay(java.util.concurrent.TimeUnit);
   }
 
-  public class Exchanger {
+  public class Exchanger<V> {
     ctor public Exchanger();
     method public V exchange(V) throws java.lang.InterruptedException;
     method public V exchange(V, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException, java.util.concurrent.TimeoutException;
@@ -64427,7 +64422,7 @@
     method public abstract void execute(java.lang.Runnable);
   }
 
-  public class ExecutorCompletionService implements java.util.concurrent.CompletionService {
+  public class ExecutorCompletionService<V> implements java.util.concurrent.CompletionService {
     ctor public ExecutorCompletionService(java.util.concurrent.Executor);
     ctor public ExecutorCompletionService(java.util.concurrent.Executor, java.util.concurrent.BlockingQueue<java.util.concurrent.Future<V>>);
     method public java.util.concurrent.Future<V> poll();
@@ -64439,21 +64434,21 @@
 
   public abstract interface ExecutorService implements java.util.concurrent.Executor {
     method public abstract boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
-    method public abstract java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.lang.InterruptedException;
-    method public abstract java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
-    method public abstract T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
-    method public abstract T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method public abstract <T> java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.lang.InterruptedException;
+    method public abstract <T> java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public abstract <T> T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public abstract <T> T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
     method public abstract boolean isShutdown();
     method public abstract boolean isTerminated();
     method public abstract void shutdown();
     method public abstract java.util.List<java.lang.Runnable> shutdownNow();
-    method public abstract java.util.concurrent.Future<T> submit(java.util.concurrent.Callable<T>);
-    method public abstract java.util.concurrent.Future<T> submit(java.lang.Runnable, T);
+    method public abstract <T> java.util.concurrent.Future<T> submit(java.util.concurrent.Callable<T>);
+    method public abstract <T> java.util.concurrent.Future<T> submit(java.lang.Runnable, T);
     method public abstract java.util.concurrent.Future<?> submit(java.lang.Runnable);
   }
 
   public class Executors {
-    method public static java.util.concurrent.Callable<T> callable(java.lang.Runnable, T);
+    method public static <T> java.util.concurrent.Callable<T> callable(java.lang.Runnable, T);
     method public static java.util.concurrent.Callable<java.lang.Object> callable(java.lang.Runnable);
     method public static java.util.concurrent.Callable<java.lang.Object> callable(java.security.PrivilegedAction<?>);
     method public static java.util.concurrent.Callable<java.lang.Object> callable(java.security.PrivilegedExceptionAction<?>);
@@ -64470,8 +64465,8 @@
     method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor(java.util.concurrent.ThreadFactory);
     method public static java.util.concurrent.ExecutorService newWorkStealingPool(int);
     method public static java.util.concurrent.ExecutorService newWorkStealingPool();
-    method public static java.util.concurrent.Callable<T> privilegedCallable(java.util.concurrent.Callable<T>);
-    method public static java.util.concurrent.Callable<T> privilegedCallableUsingCurrentClassLoader(java.util.concurrent.Callable<T>);
+    method public static <T> java.util.concurrent.Callable<T> privilegedCallable(java.util.concurrent.Callable<T>);
+    method public static <T> java.util.concurrent.Callable<T> privilegedCallableUsingCurrentClassLoader(java.util.concurrent.Callable<T>);
     method public static java.util.concurrent.ThreadFactory privilegedThreadFactory();
     method public static java.util.concurrent.ExecutorService unconfigurableExecutorService(java.util.concurrent.ExecutorService);
     method public static java.util.concurrent.ScheduledExecutorService unconfigurableScheduledExecutorService(java.util.concurrent.ScheduledExecutorService);
@@ -64499,7 +64494,7 @@
     method public long getStealCount();
     method public java.lang.Thread.UncaughtExceptionHandler getUncaughtExceptionHandler();
     method public boolean hasQueuedSubmissions();
-    method public T invoke(java.util.concurrent.ForkJoinTask<T>);
+    method public <T> T invoke(java.util.concurrent.ForkJoinTask<T>);
     method public boolean isQuiescent();
     method public boolean isShutdown();
     method public boolean isTerminated();
@@ -64508,7 +64503,7 @@
     method protected java.util.concurrent.ForkJoinTask<?> pollSubmission();
     method public void shutdown();
     method public java.util.List<java.lang.Runnable> shutdownNow();
-    method public java.util.concurrent.ForkJoinTask<T> submit(java.util.concurrent.ForkJoinTask<T>);
+    method public <T> java.util.concurrent.ForkJoinTask<T> submit(java.util.concurrent.ForkJoinTask<T>);
     field public static final java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory defaultForkJoinWorkerThreadFactory;
   }
 
@@ -64521,11 +64516,11 @@
     method public abstract boolean isReleasable();
   }
 
-  public abstract class ForkJoinTask implements java.util.concurrent.Future java.io.Serializable {
+  public abstract class ForkJoinTask<V> implements java.util.concurrent.Future java.io.Serializable {
     ctor public ForkJoinTask();
     method public static java.util.concurrent.ForkJoinTask<?> adapt(java.lang.Runnable);
-    method public static java.util.concurrent.ForkJoinTask<T> adapt(java.lang.Runnable, T);
-    method public static java.util.concurrent.ForkJoinTask<T> adapt(java.util.concurrent.Callable<? extends T>);
+    method public static <T> java.util.concurrent.ForkJoinTask<T> adapt(java.lang.Runnable, T);
+    method public static <T> java.util.concurrent.ForkJoinTask<T> adapt(java.util.concurrent.Callable<? extends T>);
     method public boolean cancel(boolean);
     method public final boolean compareAndSetForkJoinTaskTag(short, short);
     method public void complete(V);
@@ -64545,7 +64540,7 @@
     method public final V invoke();
     method public static void invokeAll(java.util.concurrent.ForkJoinTask<?>, java.util.concurrent.ForkJoinTask<?>);
     method public static void invokeAll(java.util.concurrent.ForkJoinTask<?>...);
-    method public static java.util.Collection<T> invokeAll(java.util.Collection<T>);
+    method public static <T extends java.util.concurrent.ForkJoinTask<?>> java.util.Collection<T> invokeAll(java.util.Collection<T>);
     method public final boolean isCancelled();
     method public final boolean isCompletedAbnormally();
     method public final boolean isCompletedNormally();
@@ -64571,7 +64566,7 @@
     method protected void onTermination(java.lang.Throwable);
   }
 
-  public abstract interface Future {
+  public abstract interface Future<V> {
     method public abstract boolean cancel(boolean);
     method public abstract V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
     method public abstract V get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
@@ -64579,7 +64574,7 @@
     method public abstract boolean isDone();
   }
 
-  public class FutureTask implements java.util.concurrent.RunnableFuture {
+  public class FutureTask<V> implements java.util.concurrent.RunnableFuture {
     ctor public FutureTask(java.util.concurrent.Callable<V>);
     ctor public FutureTask(java.lang.Runnable, V);
     method public boolean cancel(boolean);
@@ -64594,7 +64589,7 @@
     method protected void setException(java.lang.Throwable);
   }
 
-  public class LinkedBlockingDeque extends java.util.AbstractQueue implements java.util.concurrent.BlockingDeque java.io.Serializable {
+  public class LinkedBlockingDeque<E> extends java.util.AbstractQueue implements java.util.concurrent.BlockingDeque java.io.Serializable {
     ctor public LinkedBlockingDeque();
     ctor public LinkedBlockingDeque(int);
     ctor public LinkedBlockingDeque(java.util.Collection<? extends E>);
@@ -64638,7 +64633,7 @@
     method public E takeLast() throws java.lang.InterruptedException;
   }
 
-  public class LinkedBlockingQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
+  public class LinkedBlockingQueue<E> extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
     ctor public LinkedBlockingQueue();
     ctor public LinkedBlockingQueue(int);
     ctor public LinkedBlockingQueue(java.util.Collection<? extends E>);
@@ -64657,7 +64652,7 @@
     method public E take() throws java.lang.InterruptedException;
   }
 
-  public class LinkedTransferQueue extends java.util.AbstractQueue implements java.io.Serializable java.util.concurrent.TransferQueue {
+  public class LinkedTransferQueue<E> extends java.util.AbstractQueue implements java.io.Serializable java.util.concurrent.TransferQueue {
     ctor public LinkedTransferQueue();
     ctor public LinkedTransferQueue(java.util.Collection<? extends E>);
     method public int drainTo(java.util.Collection<? super E>);
@@ -64704,7 +64699,7 @@
     method public int register();
   }
 
-  public class PriorityBlockingQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
+  public class PriorityBlockingQueue<E> extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
     ctor public PriorityBlockingQueue();
     ctor public PriorityBlockingQueue(int);
     ctor public PriorityBlockingQueue(int, java.util.Comparator<? super E>);
@@ -64733,7 +64728,7 @@
     method protected final void setRawResult(java.lang.Void);
   }
 
-  public abstract class RecursiveTask extends java.util.concurrent.ForkJoinTask {
+  public abstract class RecursiveTask<V> extends java.util.concurrent.ForkJoinTask {
     ctor public RecursiveTask();
     method protected abstract V compute();
     method protected final boolean exec();
@@ -64752,22 +64747,22 @@
     method public abstract void rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor);
   }
 
-  public abstract interface RunnableFuture implements java.util.concurrent.Future java.lang.Runnable {
+  public abstract interface RunnableFuture<V> implements java.util.concurrent.Future java.lang.Runnable {
     method public abstract void run();
   }
 
-  public abstract interface RunnableScheduledFuture implements java.util.concurrent.RunnableFuture java.util.concurrent.ScheduledFuture {
+  public abstract interface RunnableScheduledFuture<V> implements java.util.concurrent.RunnableFuture java.util.concurrent.ScheduledFuture {
     method public abstract boolean isPeriodic();
   }
 
   public abstract interface ScheduledExecutorService implements java.util.concurrent.ExecutorService {
     method public abstract java.util.concurrent.ScheduledFuture<?> schedule(java.lang.Runnable, long, java.util.concurrent.TimeUnit);
-    method public abstract java.util.concurrent.ScheduledFuture<V> schedule(java.util.concurrent.Callable<V>, long, java.util.concurrent.TimeUnit);
+    method public abstract <V> java.util.concurrent.ScheduledFuture<V> schedule(java.util.concurrent.Callable<V>, long, java.util.concurrent.TimeUnit);
     method public abstract java.util.concurrent.ScheduledFuture<?> scheduleAtFixedRate(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
     method public abstract java.util.concurrent.ScheduledFuture<?> scheduleWithFixedDelay(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
   }
 
-  public abstract interface ScheduledFuture implements java.util.concurrent.Delayed java.util.concurrent.Future {
+  public abstract interface ScheduledFuture<V> implements java.util.concurrent.Delayed java.util.concurrent.Future {
   }
 
   public class ScheduledThreadPoolExecutor extends java.util.concurrent.ThreadPoolExecutor implements java.util.concurrent.ScheduledExecutorService {
@@ -64775,13 +64770,13 @@
     ctor public ScheduledThreadPoolExecutor(int, java.util.concurrent.ThreadFactory);
     ctor public ScheduledThreadPoolExecutor(int, java.util.concurrent.RejectedExecutionHandler);
     ctor public ScheduledThreadPoolExecutor(int, java.util.concurrent.ThreadFactory, java.util.concurrent.RejectedExecutionHandler);
-    method protected java.util.concurrent.RunnableScheduledFuture<V> decorateTask(java.lang.Runnable, java.util.concurrent.RunnableScheduledFuture<V>);
-    method protected java.util.concurrent.RunnableScheduledFuture<V> decorateTask(java.util.concurrent.Callable<V>, java.util.concurrent.RunnableScheduledFuture<V>);
+    method protected <V> java.util.concurrent.RunnableScheduledFuture<V> decorateTask(java.lang.Runnable, java.util.concurrent.RunnableScheduledFuture<V>);
+    method protected <V> java.util.concurrent.RunnableScheduledFuture<V> decorateTask(java.util.concurrent.Callable<V>, java.util.concurrent.RunnableScheduledFuture<V>);
     method public boolean getContinueExistingPeriodicTasksAfterShutdownPolicy();
     method public boolean getExecuteExistingDelayedTasksAfterShutdownPolicy();
     method public boolean getRemoveOnCancelPolicy();
     method public java.util.concurrent.ScheduledFuture<?> schedule(java.lang.Runnable, long, java.util.concurrent.TimeUnit);
-    method public java.util.concurrent.ScheduledFuture<V> schedule(java.util.concurrent.Callable<V>, long, java.util.concurrent.TimeUnit);
+    method public <V> java.util.concurrent.ScheduledFuture<V> schedule(java.util.concurrent.Callable<V>, long, java.util.concurrent.TimeUnit);
     method public java.util.concurrent.ScheduledFuture<?> scheduleAtFixedRate(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
     method public java.util.concurrent.ScheduledFuture<?> scheduleWithFixedDelay(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
     method public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean);
@@ -64811,7 +64806,7 @@
     method public boolean tryAcquire(int, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
   }
 
-  public class SynchronousQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
+  public class SynchronousQueue<E> extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
     ctor public SynchronousQueue();
     ctor public SynchronousQueue(boolean);
     method public int drainTo(java.util.Collection<? super E>);
@@ -64929,7 +64924,7 @@
     ctor public TimeoutException(java.lang.String);
   }
 
-  public abstract interface TransferQueue implements java.util.concurrent.BlockingQueue {
+  public abstract interface TransferQueue<E> implements java.util.concurrent.BlockingQueue {
     method public abstract int getWaitingConsumerCount();
     method public abstract boolean hasWaitingConsumer();
     method public abstract void transfer(E) throws java.lang.InterruptedException;
@@ -64999,7 +64994,7 @@
     method public final boolean weakCompareAndSet(int, int, int);
   }
 
-  public abstract class AtomicIntegerFieldUpdater {
+  public abstract class AtomicIntegerFieldUpdater<T> {
     ctor protected AtomicIntegerFieldUpdater();
     method public final int accumulateAndGet(T, int, java.util.function.IntBinaryOperator);
     method public int addAndGet(T, int);
@@ -65014,7 +65009,7 @@
     method public final int getAndUpdate(T, java.util.function.IntUnaryOperator);
     method public int incrementAndGet(T);
     method public abstract void lazySet(T, int);
-    method public static java.util.concurrent.atomic.AtomicIntegerFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
+    method public static <U> java.util.concurrent.atomic.AtomicIntegerFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, int);
     method public final int updateAndGet(T, java.util.function.IntUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, int, int);
@@ -65067,7 +65062,7 @@
     method public final boolean weakCompareAndSet(int, long, long);
   }
 
-  public abstract class AtomicLongFieldUpdater {
+  public abstract class AtomicLongFieldUpdater<T> {
     ctor protected AtomicLongFieldUpdater();
     method public final long accumulateAndGet(T, long, java.util.function.LongBinaryOperator);
     method public long addAndGet(T, long);
@@ -65082,13 +65077,13 @@
     method public final long getAndUpdate(T, java.util.function.LongUnaryOperator);
     method public long incrementAndGet(T);
     method public abstract void lazySet(T, long);
-    method public static java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
+    method public static <U> java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, long);
     method public final long updateAndGet(T, java.util.function.LongUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, long, long);
   }
 
-  public class AtomicMarkableReference {
+  public class AtomicMarkableReference<V> {
     ctor public AtomicMarkableReference(V, boolean);
     method public boolean attemptMark(V, boolean);
     method public boolean compareAndSet(V, V, boolean, boolean);
@@ -65099,7 +65094,7 @@
     method public boolean weakCompareAndSet(V, V, boolean, boolean);
   }
 
-  public class AtomicReference implements java.io.Serializable {
+  public class AtomicReference<V> implements java.io.Serializable {
     ctor public AtomicReference(V);
     ctor public AtomicReference();
     method public final V accumulateAndGet(V, java.util.function.BinaryOperator<V>);
@@ -65114,7 +65109,7 @@
     method public final boolean weakCompareAndSet(V, V);
   }
 
-  public class AtomicReferenceArray implements java.io.Serializable {
+  public class AtomicReferenceArray<E> implements java.io.Serializable {
     ctor public AtomicReferenceArray(int);
     ctor public AtomicReferenceArray(E[]);
     method public final E accumulateAndGet(int, E, java.util.function.BinaryOperator<E>);
@@ -65130,7 +65125,7 @@
     method public final boolean weakCompareAndSet(int, E, E);
   }
 
-  public abstract class AtomicReferenceFieldUpdater {
+  public abstract class AtomicReferenceFieldUpdater<T, V> {
     ctor protected AtomicReferenceFieldUpdater();
     method public final V accumulateAndGet(T, V, java.util.function.BinaryOperator<V>);
     method public abstract boolean compareAndSet(T, V, V);
@@ -65139,13 +65134,13 @@
     method public V getAndSet(T, V);
     method public final V getAndUpdate(T, java.util.function.UnaryOperator<V>);
     method public abstract void lazySet(T, V);
-    method public static java.util.concurrent.atomic.AtomicReferenceFieldUpdater<U, W> newUpdater(java.lang.Class<U>, java.lang.Class<W>, java.lang.String);
+    method public static <U, W> java.util.concurrent.atomic.AtomicReferenceFieldUpdater<U, W> newUpdater(java.lang.Class<U>, java.lang.Class<W>, java.lang.String);
     method public abstract void set(T, V);
     method public final V updateAndGet(T, java.util.function.UnaryOperator<V>);
     method public abstract boolean weakCompareAndSet(T, V, V);
   }
 
-  public class AtomicStampedReference {
+  public class AtomicStampedReference<V> {
     ctor public AtomicStampedReference(V, int);
     method public boolean attemptStamp(V, int);
     method public boolean compareAndSet(V, V, int, int);
@@ -65448,33 +65443,33 @@
 
 package java.util.function {
 
-  public abstract interface BiConsumer {
+  public abstract interface BiConsumer<T, U> {
     method public abstract void accept(T, U);
     method public default java.util.function.BiConsumer<T, U> andThen(java.util.function.BiConsumer<? super T, ? super U>);
   }
 
-  public abstract interface BiFunction {
-    method public default java.util.function.BiFunction<T, U, V> andThen(java.util.function.Function<? super R, ? extends V>);
+  public abstract interface BiFunction<T, U, R> {
+    method public default <V> java.util.function.BiFunction<T, U, V> andThen(java.util.function.Function<? super R, ? extends V>);
     method public abstract R apply(T, U);
   }
 
-  public abstract interface BiPredicate {
+  public abstract interface BiPredicate<T, U> {
     method public default java.util.function.BiPredicate<T, U> and(java.util.function.BiPredicate<? super T, ? super U>);
     method public default java.util.function.BiPredicate<T, U> negate();
     method public default java.util.function.BiPredicate<T, U> or(java.util.function.BiPredicate<? super T, ? super U>);
     method public abstract boolean test(T, U);
   }
 
-  public abstract interface BinaryOperator implements java.util.function.BiFunction {
-    method public static java.util.function.BinaryOperator<T> maxBy(java.util.Comparator<? super T>);
-    method public static java.util.function.BinaryOperator<T> minBy(java.util.Comparator<? super T>);
+  public abstract interface BinaryOperator<T> implements java.util.function.BiFunction {
+    method public static <T> java.util.function.BinaryOperator<T> maxBy(java.util.Comparator<? super T>);
+    method public static <T> java.util.function.BinaryOperator<T> minBy(java.util.Comparator<? super T>);
   }
 
   public abstract interface BooleanSupplier {
     method public abstract boolean getAsBoolean();
   }
 
-  public abstract interface Consumer {
+  public abstract interface Consumer<T> {
     method public abstract void accept(T);
     method public default java.util.function.Consumer<T> andThen(java.util.function.Consumer<? super T>);
   }
@@ -65488,7 +65483,7 @@
     method public default java.util.function.DoubleConsumer andThen(java.util.function.DoubleConsumer);
   }
 
-  public abstract interface DoubleFunction {
+  public abstract interface DoubleFunction<R> {
     method public abstract R apply(double);
   }
 
@@ -65518,11 +65513,11 @@
     method public static java.util.function.DoubleUnaryOperator identity();
   }
 
-  public abstract interface Function {
-    method public default java.util.function.Function<T, V> andThen(java.util.function.Function<? super R, ? extends V>);
+  public abstract interface Function<T, R> {
+    method public default <V> java.util.function.Function<T, V> andThen(java.util.function.Function<? super R, ? extends V>);
     method public abstract R apply(T);
-    method public default java.util.function.Function<V, R> compose(java.util.function.Function<? super V, ? extends T>);
-    method public static java.util.function.Function<T, T> identity();
+    method public default <V> java.util.function.Function<V, R> compose(java.util.function.Function<? super V, ? extends T>);
+    method public static <T> java.util.function.Function<T, T> identity();
   }
 
   public abstract interface IntBinaryOperator {
@@ -65534,7 +65529,7 @@
     method public default java.util.function.IntConsumer andThen(java.util.function.IntConsumer);
   }
 
-  public abstract interface IntFunction {
+  public abstract interface IntFunction<R> {
     method public abstract R apply(int);
   }
 
@@ -65573,7 +65568,7 @@
     method public default java.util.function.LongConsumer andThen(java.util.function.LongConsumer);
   }
 
-  public abstract interface LongFunction {
+  public abstract interface LongFunction<R> {
     method public abstract R apply(long);
   }
 
@@ -65603,56 +65598,56 @@
     method public static java.util.function.LongUnaryOperator identity();
   }
 
-  public abstract interface ObjDoubleConsumer {
+  public abstract interface ObjDoubleConsumer<T> {
     method public abstract void accept(T, double);
   }
 
-  public abstract interface ObjIntConsumer {
+  public abstract interface ObjIntConsumer<T> {
     method public abstract void accept(T, int);
   }
 
-  public abstract interface ObjLongConsumer {
+  public abstract interface ObjLongConsumer<T> {
     method public abstract void accept(T, long);
   }
 
-  public abstract interface Predicate {
+  public abstract interface Predicate<T> {
     method public default java.util.function.Predicate<T> and(java.util.function.Predicate<? super T>);
-    method public static java.util.function.Predicate<T> isEqual(java.lang.Object);
+    method public static <T> java.util.function.Predicate<T> isEqual(java.lang.Object);
     method public default java.util.function.Predicate<T> negate();
     method public default java.util.function.Predicate<T> or(java.util.function.Predicate<? super T>);
     method public abstract boolean test(T);
   }
 
-  public abstract interface Supplier {
+  public abstract interface Supplier<T> {
     method public abstract T get();
   }
 
-  public abstract interface ToDoubleBiFunction {
+  public abstract interface ToDoubleBiFunction<T, U> {
     method public abstract double applyAsDouble(T, U);
   }
 
-  public abstract interface ToDoubleFunction {
+  public abstract interface ToDoubleFunction<T> {
     method public abstract double applyAsDouble(T);
   }
 
-  public abstract interface ToIntBiFunction {
+  public abstract interface ToIntBiFunction<T, U> {
     method public abstract int applyAsInt(T, U);
   }
 
-  public abstract interface ToIntFunction {
+  public abstract interface ToIntFunction<T> {
     method public abstract int applyAsInt(T);
   }
 
-  public abstract interface ToLongBiFunction {
+  public abstract interface ToLongBiFunction<T, U> {
     method public abstract long applyAsLong(T, U);
   }
 
-  public abstract interface ToLongFunction {
+  public abstract interface ToLongFunction<T> {
     method public abstract long applyAsLong(T);
   }
 
-  public abstract interface UnaryOperator implements java.util.function.Function {
-    method public static java.util.function.UnaryOperator<T> identity();
+  public abstract interface UnaryOperator<T> implements java.util.function.Function {
+    method public static <T> java.util.function.UnaryOperator<T> identity();
   }
 
 }
@@ -66240,7 +66235,7 @@
 
 package java.util.stream {
 
-  public abstract interface BaseStream implements java.lang.AutoCloseable {
+  public abstract interface BaseStream<T, S extends java.util.stream.BaseStream<T, S>> implements java.lang.AutoCloseable {
     method public abstract void close();
     method public abstract boolean isParallel();
     method public abstract java.util.Iterator<T> iterator();
@@ -66251,13 +66246,13 @@
     method public abstract S unordered();
   }
 
-  public abstract interface Collector {
+  public abstract interface Collector<T, A, R> {
     method public abstract java.util.function.BiConsumer<A, T> accumulator();
     method public abstract java.util.Set<java.util.stream.Collector.Characteristics> characteristics();
     method public abstract java.util.function.BinaryOperator<A> combiner();
     method public abstract java.util.function.Function<A, R> finisher();
-    method public static java.util.stream.Collector<T, R, R> of(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, T>, java.util.function.BinaryOperator<R>, java.util.stream.Collector.Characteristics...);
-    method public static java.util.stream.Collector<T, A, R> of(java.util.function.Supplier<A>, java.util.function.BiConsumer<A, T>, java.util.function.BinaryOperator<A>, java.util.function.Function<A, R>, java.util.stream.Collector.Characteristics...);
+    method public static <T, R> java.util.stream.Collector<T, R, R> of(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, T>, java.util.function.BinaryOperator<R>, java.util.stream.Collector.Characteristics...);
+    method public static <T, A, R> java.util.stream.Collector<T, A, R> of(java.util.function.Supplier<A>, java.util.function.BiConsumer<A, T>, java.util.function.BinaryOperator<A>, java.util.function.Function<A, R>, java.util.stream.Collector.Characteristics...);
     method public abstract java.util.function.Supplier<A> supplier();
   }
 
@@ -66270,43 +66265,43 @@
   }
 
   public final class Collectors {
-    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingDouble(java.util.function.ToDoubleFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingInt(java.util.function.ToIntFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingLong(java.util.function.ToLongFunction<? super T>);
-    method public static java.util.stream.Collector<T, A, RR> collectingAndThen(java.util.stream.Collector<T, A, R>, java.util.function.Function<R, RR>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Long> counting();
-    method public static java.util.stream.Collector<T, ?, java.util.Map<K, java.util.List<T>>> groupingBy(java.util.function.Function<? super T, ? extends K>);
-    method public static java.util.stream.Collector<T, ?, java.util.Map<K, D>> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
-    method public static java.util.stream.Collector<T, ?, M> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
-    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, java.util.List<T>>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>);
-    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, D>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
-    method public static java.util.stream.Collector<T, ?, M> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Double> averagingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Double> averagingInt(java.util.function.ToIntFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Double> averagingLong(java.util.function.ToLongFunction<? super T>);
+    method public static <T, A, R, RR> java.util.stream.Collector<T, A, RR> collectingAndThen(java.util.stream.Collector<T, A, R>, java.util.function.Function<R, RR>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Long> counting();
+    method public static <T, K> java.util.stream.Collector<T, ?, java.util.Map<K, java.util.List<T>>> groupingBy(java.util.function.Function<? super T, ? extends K>);
+    method public static <T, K, A, D> java.util.stream.Collector<T, ?, java.util.Map<K, D>> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
+    method public static <T, K, D, A, M extends java.util.Map<K, D>> java.util.stream.Collector<T, ?, M> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
+    method public static <T, K> java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, java.util.List<T>>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>);
+    method public static <T, K, A, D> java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, D>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
+    method public static <T, K, A, D, M extends java.util.concurrent.ConcurrentMap<K, D>> java.util.stream.Collector<T, ?, M> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
     method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining();
     method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining(java.lang.CharSequence);
     method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining(java.lang.CharSequence, java.lang.CharSequence, java.lang.CharSequence);
-    method public static java.util.stream.Collector<T, ?, R> mapping(java.util.function.Function<? super T, ? extends U>, java.util.stream.Collector<? super U, A, R>);
-    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> maxBy(java.util.Comparator<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> minBy(java.util.Comparator<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, java.util.List<T>>> partitioningBy(java.util.function.Predicate<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, D>> partitioningBy(java.util.function.Predicate<? super T>, java.util.stream.Collector<? super T, A, D>);
-    method public static java.util.stream.Collector<T, ?, T> reducing(T, java.util.function.BinaryOperator<T>);
-    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> reducing(java.util.function.BinaryOperator<T>);
-    method public static java.util.stream.Collector<T, ?, U> reducing(U, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
-    method public static java.util.stream.Collector<T, ?, java.util.DoubleSummaryStatistics> summarizingDouble(java.util.function.ToDoubleFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.util.IntSummaryStatistics> summarizingInt(java.util.function.ToIntFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.util.LongSummaryStatistics> summarizingLong(java.util.function.ToLongFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Double> summingDouble(java.util.function.ToDoubleFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Integer> summingInt(java.util.function.ToIntFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Long> summingLong(java.util.function.ToLongFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, C> toCollection(java.util.function.Supplier<C>);
-    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
-    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
-    method public static java.util.stream.Collector<T, ?, M> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
-    method public static java.util.stream.Collector<T, ?, java.util.List<T>> toList();
-    method public static java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
-    method public static java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
-    method public static java.util.stream.Collector<T, ?, M> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
-    method public static java.util.stream.Collector<T, ?, java.util.Set<T>> toSet();
+    method public static <T, U, A, R> java.util.stream.Collector<T, ?, R> mapping(java.util.function.Function<? super T, ? extends U>, java.util.stream.Collector<? super U, A, R>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.Optional<T>> maxBy(java.util.Comparator<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.Optional<T>> minBy(java.util.Comparator<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, java.util.List<T>>> partitioningBy(java.util.function.Predicate<? super T>);
+    method public static <T, D, A> java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, D>> partitioningBy(java.util.function.Predicate<? super T>, java.util.stream.Collector<? super T, A, D>);
+    method public static <T> java.util.stream.Collector<T, ?, T> reducing(T, java.util.function.BinaryOperator<T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.Optional<T>> reducing(java.util.function.BinaryOperator<T>);
+    method public static <T, U> java.util.stream.Collector<T, ?, U> reducing(U, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.DoubleSummaryStatistics> summarizingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.IntSummaryStatistics> summarizingInt(java.util.function.ToIntFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.LongSummaryStatistics> summarizingLong(java.util.function.ToLongFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Double> summingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Integer> summingInt(java.util.function.ToIntFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Long> summingLong(java.util.function.ToLongFunction<? super T>);
+    method public static <T, C extends java.util.Collection<T>> java.util.stream.Collector<T, ?, C> toCollection(java.util.function.Supplier<C>);
+    method public static <T, K, U> java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
+    method public static <T, K, U> java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static <T, K, U, M extends java.util.concurrent.ConcurrentMap<K, U>> java.util.stream.Collector<T, ?, M> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.List<T>> toList();
+    method public static <T, K, U> java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
+    method public static <T, K, U> java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static <T, K, U, M extends java.util.Map<K, U>> java.util.stream.Collector<T, ?, M> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.Set<T>> toSet();
   }
 
   public abstract interface DoubleStream implements java.util.stream.BaseStream {
@@ -66315,7 +66310,7 @@
     method public abstract java.util.OptionalDouble average();
     method public abstract java.util.stream.Stream<java.lang.Double> boxed();
     method public static java.util.stream.DoubleStream.Builder builder();
-    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjDoubleConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public abstract <R> R collect(java.util.function.Supplier<R>, java.util.function.ObjDoubleConsumer<R>, java.util.function.BiConsumer<R, R>);
     method public static java.util.stream.DoubleStream concat(java.util.stream.DoubleStream, java.util.stream.DoubleStream);
     method public abstract long count();
     method public abstract java.util.stream.DoubleStream distinct();
@@ -66333,7 +66328,7 @@
     method public abstract java.util.stream.DoubleStream map(java.util.function.DoubleUnaryOperator);
     method public abstract java.util.stream.IntStream mapToInt(java.util.function.DoubleToIntFunction);
     method public abstract java.util.stream.LongStream mapToLong(java.util.function.DoubleToLongFunction);
-    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.DoubleFunction<? extends U>);
+    method public abstract <U> java.util.stream.Stream<U> mapToObj(java.util.function.DoubleFunction<? extends U>);
     method public abstract java.util.OptionalDouble max();
     method public abstract java.util.OptionalDouble min();
     method public abstract boolean noneMatch(java.util.function.DoublePredicate);
@@ -66366,7 +66361,7 @@
     method public abstract java.util.OptionalDouble average();
     method public abstract java.util.stream.Stream<java.lang.Integer> boxed();
     method public static java.util.stream.IntStream.Builder builder();
-    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjIntConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public abstract <R> R collect(java.util.function.Supplier<R>, java.util.function.ObjIntConsumer<R>, java.util.function.BiConsumer<R, R>);
     method public static java.util.stream.IntStream concat(java.util.stream.IntStream, java.util.stream.IntStream);
     method public abstract long count();
     method public abstract java.util.stream.IntStream distinct();
@@ -66384,7 +66379,7 @@
     method public abstract java.util.stream.IntStream map(java.util.function.IntUnaryOperator);
     method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.IntToDoubleFunction);
     method public abstract java.util.stream.LongStream mapToLong(java.util.function.IntToLongFunction);
-    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.IntFunction<? extends U>);
+    method public abstract <U> java.util.stream.Stream<U> mapToObj(java.util.function.IntFunction<? extends U>);
     method public abstract java.util.OptionalInt max();
     method public abstract java.util.OptionalInt min();
     method public abstract boolean noneMatch(java.util.function.IntPredicate);
@@ -66418,7 +66413,7 @@
     method public abstract java.util.OptionalDouble average();
     method public abstract java.util.stream.Stream<java.lang.Long> boxed();
     method public static java.util.stream.LongStream.Builder builder();
-    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjLongConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public abstract <R> R collect(java.util.function.Supplier<R>, java.util.function.ObjLongConsumer<R>, java.util.function.BiConsumer<R, R>);
     method public static java.util.stream.LongStream concat(java.util.stream.LongStream, java.util.stream.LongStream);
     method public abstract long count();
     method public abstract java.util.stream.LongStream distinct();
@@ -66436,7 +66431,7 @@
     method public abstract java.util.stream.LongStream map(java.util.function.LongUnaryOperator);
     method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.LongToDoubleFunction);
     method public abstract java.util.stream.IntStream mapToInt(java.util.function.LongToIntFunction);
-    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.LongFunction<? extends U>);
+    method public abstract <U> java.util.stream.Stream<U> mapToObj(java.util.function.LongFunction<? extends U>);
     method public abstract java.util.OptionalLong max();
     method public abstract java.util.OptionalLong min();
     method public abstract boolean noneMatch(java.util.function.LongPredicate);
@@ -66463,49 +66458,49 @@
     method public abstract java.util.stream.LongStream build();
   }
 
-  public abstract interface Stream implements java.util.stream.BaseStream {
+  public abstract interface Stream<T> implements java.util.stream.BaseStream {
     method public abstract boolean allMatch(java.util.function.Predicate<? super T>);
     method public abstract boolean anyMatch(java.util.function.Predicate<? super T>);
-    method public static java.util.stream.Stream.Builder<T> builder();
-    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, ? super T>, java.util.function.BiConsumer<R, R>);
-    method public abstract R collect(java.util.stream.Collector<? super T, A, R>);
-    method public static java.util.stream.Stream<T> concat(java.util.stream.Stream<? extends T>, java.util.stream.Stream<? extends T>);
+    method public static <T> java.util.stream.Stream.Builder<T> builder();
+    method public abstract <R> R collect(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, ? super T>, java.util.function.BiConsumer<R, R>);
+    method public abstract <R, A> R collect(java.util.stream.Collector<? super T, A, R>);
+    method public static <T> java.util.stream.Stream<T> concat(java.util.stream.Stream<? extends T>, java.util.stream.Stream<? extends T>);
     method public abstract long count();
     method public abstract java.util.stream.Stream<T> distinct();
-    method public static java.util.stream.Stream<T> empty();
+    method public static <T> java.util.stream.Stream<T> empty();
     method public abstract java.util.stream.Stream<T> filter(java.util.function.Predicate<? super T>);
     method public abstract java.util.Optional<T> findAny();
     method public abstract java.util.Optional<T> findFirst();
-    method public abstract java.util.stream.Stream<R> flatMap(java.util.function.Function<? super T, ? extends java.util.stream.Stream<? extends R>>);
+    method public abstract <R> java.util.stream.Stream<R> flatMap(java.util.function.Function<? super T, ? extends java.util.stream.Stream<? extends R>>);
     method public abstract java.util.stream.DoubleStream flatMapToDouble(java.util.function.Function<? super T, ? extends java.util.stream.DoubleStream>);
     method public abstract java.util.stream.IntStream flatMapToInt(java.util.function.Function<? super T, ? extends java.util.stream.IntStream>);
     method public abstract java.util.stream.LongStream flatMapToLong(java.util.function.Function<? super T, ? extends java.util.stream.LongStream>);
     method public abstract void forEach(java.util.function.Consumer<? super T>);
     method public abstract void forEachOrdered(java.util.function.Consumer<? super T>);
-    method public static java.util.stream.Stream<T> generate(java.util.function.Supplier<T>);
-    method public static java.util.stream.Stream<T> iterate(T, java.util.function.UnaryOperator<T>);
+    method public static <T> java.util.stream.Stream<T> generate(java.util.function.Supplier<T>);
+    method public static <T> java.util.stream.Stream<T> iterate(T, java.util.function.UnaryOperator<T>);
     method public abstract java.util.stream.Stream<T> limit(long);
-    method public abstract java.util.stream.Stream<R> map(java.util.function.Function<? super T, ? extends R>);
+    method public abstract <R> java.util.stream.Stream<R> map(java.util.function.Function<? super T, ? extends R>);
     method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.ToDoubleFunction<? super T>);
     method public abstract java.util.stream.IntStream mapToInt(java.util.function.ToIntFunction<? super T>);
     method public abstract java.util.stream.LongStream mapToLong(java.util.function.ToLongFunction<? super T>);
     method public abstract java.util.Optional<T> max(java.util.Comparator<? super T>);
     method public abstract java.util.Optional<T> min(java.util.Comparator<? super T>);
     method public abstract boolean noneMatch(java.util.function.Predicate<? super T>);
-    method public static java.util.stream.Stream<T> of(T);
-    method public static java.util.stream.Stream<T> of(T...);
+    method public static <T> java.util.stream.Stream<T> of(T);
+    method public static <T> java.util.stream.Stream<T> of(T...);
     method public abstract java.util.stream.Stream<T> peek(java.util.function.Consumer<? super T>);
     method public abstract T reduce(T, java.util.function.BinaryOperator<T>);
     method public abstract java.util.Optional<T> reduce(java.util.function.BinaryOperator<T>);
-    method public abstract U reduce(U, java.util.function.BiFunction<U, ? super T, U>, java.util.function.BinaryOperator<U>);
+    method public abstract <U> U reduce(U, java.util.function.BiFunction<U, ? super T, U>, java.util.function.BinaryOperator<U>);
     method public abstract java.util.stream.Stream<T> skip(long);
     method public abstract java.util.stream.Stream<T> sorted();
     method public abstract java.util.stream.Stream<T> sorted(java.util.Comparator<? super T>);
     method public abstract java.lang.Object[] toArray();
-    method public abstract A[] toArray(java.util.function.IntFunction<A[]>);
+    method public abstract <A> A[] toArray(java.util.function.IntFunction<A[]>);
   }
 
-  public static abstract interface Stream.Builder implements java.util.function.Consumer {
+  public static abstract interface Stream.Builder<T> implements java.util.function.Consumer {
     method public abstract void accept(T);
     method public default java.util.stream.Stream.Builder<T> add(T);
     method public abstract java.util.stream.Stream<T> build();
@@ -66518,8 +66513,8 @@
     method public static java.util.stream.IntStream intStream(java.util.function.Supplier<? extends java.util.Spliterator.OfInt>, int, boolean);
     method public static java.util.stream.LongStream longStream(java.util.Spliterator.OfLong, boolean);
     method public static java.util.stream.LongStream longStream(java.util.function.Supplier<? extends java.util.Spliterator.OfLong>, int, boolean);
-    method public static java.util.stream.Stream<T> stream(java.util.Spliterator<T>, boolean);
-    method public static java.util.stream.Stream<T> stream(java.util.function.Supplier<? extends java.util.Spliterator<T>>, int, boolean);
+    method public static <T> java.util.stream.Stream<T> stream(java.util.Spliterator<T>, boolean);
+    method public static <T> java.util.stream.Stream<T> stream(java.util.function.Supplier<? extends java.util.Spliterator<T>>, int, boolean);
   }
 
 }
@@ -68692,16 +68687,16 @@
   public final class Subject implements java.io.Serializable {
     ctor public Subject();
     ctor public Subject(boolean, java.util.Set<? extends java.security.Principal>, java.util.Set<?>, java.util.Set<?>);
-    method public static T doAs(javax.security.auth.Subject, java.security.PrivilegedAction<T>);
-    method public static T doAs(javax.security.auth.Subject, java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
-    method public static T doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedAction<T>, java.security.AccessControlContext);
-    method public static T doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedExceptionAction<T>, java.security.AccessControlContext) throws java.security.PrivilegedActionException;
+    method public static <T> T doAs(javax.security.auth.Subject, java.security.PrivilegedAction<T>);
+    method public static <T> T doAs(javax.security.auth.Subject, java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
+    method public static <T> T doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedAction<T>, java.security.AccessControlContext);
+    method public static <T> T doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedExceptionAction<T>, java.security.AccessControlContext) throws java.security.PrivilegedActionException;
     method public java.util.Set<java.security.Principal> getPrincipals();
-    method public java.util.Set<T> getPrincipals(java.lang.Class<T>);
+    method public <T extends java.security.Principal> java.util.Set<T> getPrincipals(java.lang.Class<T>);
     method public java.util.Set<java.lang.Object> getPrivateCredentials();
-    method public java.util.Set<T> getPrivateCredentials(java.lang.Class<T>);
+    method public <T> java.util.Set<T> getPrivateCredentials(java.lang.Class<T>);
     method public java.util.Set<java.lang.Object> getPublicCredentials();
-    method public java.util.Set<T> getPublicCredentials(java.lang.Class<T>);
+    method public <T> java.util.Set<T> getPublicCredentials(java.lang.Class<T>);
     method public static javax.security.auth.Subject getSubject(java.security.AccessControlContext);
     method public boolean isReadOnly();
     method public void setReadOnly();
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 3811e22..98e7953 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -165,6 +165,13 @@
 
 package android.net {
 
+  public abstract class PskKeyManager {
+    ctor public PskKeyManager();
+    field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
+    field public static final int MAX_IDENTITY_LENGTH_BYTES = 128; // 0x80
+    field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100
+  }
+
   public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
     method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index eda4019..6d4590d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2921,11 +2921,11 @@
     field public static final java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
   }
 
-  public abstract interface AccountManagerCallback {
+  public abstract interface AccountManagerCallback<V> {
     method public abstract void run(android.accounts.AccountManagerFuture<V>);
   }
 
-  public abstract interface AccountManagerFuture {
+  public abstract interface AccountManagerFuture<V> {
     method public abstract boolean cancel(boolean);
     method public abstract V getResult() throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
     method public abstract V getResult(long, java.util.concurrent.TimeUnit) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
@@ -3071,7 +3071,7 @@
     method public java.lang.Object evaluate(float, java.lang.Object, java.lang.Object);
   }
 
-  public abstract class BidirectionalTypeConverter extends android.animation.TypeConverter {
+  public abstract class BidirectionalTypeConverter<T, V> extends android.animation.TypeConverter {
     ctor public BidirectionalTypeConverter(java.lang.Class<T>, java.lang.Class<V>);
     method public abstract T convertBack(V);
     method public android.animation.BidirectionalTypeConverter<V, T> invert();
@@ -3163,26 +3163,26 @@
     method public java.lang.String getPropertyName();
     method public java.lang.Object getTarget();
     method public static android.animation.ObjectAnimator ofArgb(java.lang.Object, java.lang.String, int...);
-    method public static android.animation.ObjectAnimator ofArgb(T, android.util.Property<T, java.lang.Integer>, int...);
+    method public static <T> android.animation.ObjectAnimator ofArgb(T, android.util.Property<T, java.lang.Integer>, int...);
     method public static android.animation.ObjectAnimator ofFloat(java.lang.Object, java.lang.String, float...);
     method public static android.animation.ObjectAnimator ofFloat(java.lang.Object, java.lang.String, java.lang.String, android.graphics.Path);
-    method public static android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, float...);
-    method public static android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, android.util.Property<T, java.lang.Float>, android.graphics.Path);
+    method public static <T> android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, float...);
+    method public static <T> android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, android.util.Property<T, java.lang.Float>, android.graphics.Path);
     method public static android.animation.ObjectAnimator ofInt(java.lang.Object, java.lang.String, int...);
     method public static android.animation.ObjectAnimator ofInt(java.lang.Object, java.lang.String, java.lang.String, android.graphics.Path);
-    method public static android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, int...);
-    method public static android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, android.util.Property<T, java.lang.Integer>, android.graphics.Path);
+    method public static <T> android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, int...);
+    method public static <T> android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, android.util.Property<T, java.lang.Integer>, android.graphics.Path);
     method public static android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, float[][]);
     method public static android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, android.graphics.Path);
-    method public static android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, android.animation.TypeConverter<T, float[]>, android.animation.TypeEvaluator<T>, T...);
+    method public static <T> android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, android.animation.TypeConverter<T, float[]>, android.animation.TypeEvaluator<T>, T...);
     method public static android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, int[][]);
     method public static android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, android.graphics.Path);
-    method public static android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, android.animation.TypeConverter<T, int[]>, android.animation.TypeEvaluator<T>, T...);
+    method public static <T> android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, android.animation.TypeConverter<T, int[]>, android.animation.TypeEvaluator<T>, T...);
     method public static android.animation.ObjectAnimator ofObject(java.lang.Object, java.lang.String, android.animation.TypeEvaluator, java.lang.Object...);
     method public static android.animation.ObjectAnimator ofObject(java.lang.Object, java.lang.String, android.animation.TypeConverter<android.graphics.PointF, ?>, android.graphics.Path);
-    method public static android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeEvaluator<V>, V...);
-    method public static android.animation.ObjectAnimator ofObject(T, android.util.Property<T, P>, android.animation.TypeConverter<V, P>, android.animation.TypeEvaluator<V>, V...);
-    method public static android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeConverter<android.graphics.PointF, V>, android.graphics.Path);
+    method public static <T, V> android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeEvaluator<V>, V...);
+    method public static <T, V, P> android.animation.ObjectAnimator ofObject(T, android.util.Property<T, P>, android.animation.TypeConverter<V, P>, android.animation.TypeEvaluator<V>, V...);
+    method public static <T, V> android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeConverter<android.graphics.PointF, V>, android.graphics.Path);
     method public static android.animation.ObjectAnimator ofPropertyValuesHolder(java.lang.Object, android.animation.PropertyValuesHolder...);
     method public void setAutoCancel(boolean);
     method public void setProperty(android.util.Property);
@@ -3206,17 +3206,17 @@
     method public static android.animation.PropertyValuesHolder ofKeyframe(android.util.Property, android.animation.Keyframe...);
     method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, float[][]);
     method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.graphics.Path);
-    method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter<V, float[]>, android.animation.TypeEvaluator<V>, V...);
-    method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter<T, float[]>, android.animation.TypeEvaluator<T>, android.animation.Keyframe...);
+    method public static <V> android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter<V, float[]>, android.animation.TypeEvaluator<V>, V...);
+    method public static <T> android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter<T, float[]>, android.animation.TypeEvaluator<T>, android.animation.Keyframe...);
     method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, int[][]);
     method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.graphics.Path);
-    method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter<V, int[]>, android.animation.TypeEvaluator<V>, V...);
-    method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter<T, int[]>, android.animation.TypeEvaluator<T>, android.animation.Keyframe...);
+    method public static <V> android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter<V, int[]>, android.animation.TypeEvaluator<V>, V...);
+    method public static <T> android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter<T, int[]>, android.animation.TypeEvaluator<T>, android.animation.Keyframe...);
     method public static android.animation.PropertyValuesHolder ofObject(java.lang.String, android.animation.TypeEvaluator, java.lang.Object...);
     method public static android.animation.PropertyValuesHolder ofObject(java.lang.String, android.animation.TypeConverter<android.graphics.PointF, ?>, android.graphics.Path);
-    method public static android.animation.PropertyValuesHolder ofObject(android.util.Property, android.animation.TypeEvaluator<V>, V...);
-    method public static android.animation.PropertyValuesHolder ofObject(android.util.Property<?, V>, android.animation.TypeConverter<T, V>, android.animation.TypeEvaluator<T>, T...);
-    method public static android.animation.PropertyValuesHolder ofObject(android.util.Property<?, V>, android.animation.TypeConverter<android.graphics.PointF, V>, android.graphics.Path);
+    method public static <V> android.animation.PropertyValuesHolder ofObject(android.util.Property, android.animation.TypeEvaluator<V>, V...);
+    method public static <T, V> android.animation.PropertyValuesHolder ofObject(android.util.Property<?, V>, android.animation.TypeConverter<T, V>, android.animation.TypeEvaluator<T>, T...);
+    method public static <V> android.animation.PropertyValuesHolder ofObject(android.util.Property<?, V>, android.animation.TypeConverter<android.graphics.PointF, V>, android.graphics.Path);
     method public void setConverter(android.animation.TypeConverter);
     method public void setEvaluator(android.animation.TypeEvaluator);
     method public void setFloatValues(float...);
@@ -3253,12 +3253,12 @@
     method public abstract float getInterpolation(float);
   }
 
-  public abstract class TypeConverter {
+  public abstract class TypeConverter<T, V> {
     ctor public TypeConverter(java.lang.Class<T>, java.lang.Class<V>);
     method public abstract V convert(T);
   }
 
-  public abstract interface TypeEvaluator {
+  public abstract interface TypeEvaluator<T> {
     method public abstract T evaluate(float, T, T);
   }
 
@@ -4045,6 +4045,7 @@
     field public static final java.lang.String OPSTR_MOCK_LOCATION = "android:mock_location";
     field public static final java.lang.String OPSTR_MONITOR_HIGH_POWER_LOCATION = "android:monitor_location_high_power";
     field public static final java.lang.String OPSTR_MONITOR_LOCATION = "android:monitor_location";
+    field public static final java.lang.String OPSTR_PROCESS_OUTGOING_CALLS = "android:process_outgoing_calls";
     field public static final java.lang.String OPSTR_READ_CALENDAR = "android:read_calendar";
     field public static final java.lang.String OPSTR_READ_CALL_LOG = "android:read_call_log";
     field public static final java.lang.String OPSTR_READ_CELL_BROADCASTS = "android:read_cell_broadcasts";
@@ -4591,7 +4592,7 @@
     method public android.os.Parcelable saveAllState();
   }
 
-  public abstract class FragmentHostCallback extends android.app.FragmentContainer {
+  public abstract class FragmentHostCallback<E> extends android.app.FragmentContainer {
     ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
     method public void onAttachFragment(android.app.Fragment);
     method public void onDump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
@@ -4858,12 +4859,12 @@
     method public abstract void destroyLoader(int);
     method public abstract void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
     method public static void enableDebugLogging(boolean);
-    method public abstract android.content.Loader<D> getLoader(int);
-    method public abstract android.content.Loader<D> initLoader(int, android.os.Bundle, android.app.LoaderManager.LoaderCallbacks<D>);
-    method public abstract android.content.Loader<D> restartLoader(int, android.os.Bundle, android.app.LoaderManager.LoaderCallbacks<D>);
+    method public abstract <D> android.content.Loader<D> getLoader(int);
+    method public abstract <D> android.content.Loader<D> initLoader(int, android.os.Bundle, android.app.LoaderManager.LoaderCallbacks<D>);
+    method public abstract <D> android.content.Loader<D> restartLoader(int, android.os.Bundle, android.app.LoaderManager.LoaderCallbacks<D>);
   }
 
-  public static abstract interface LoaderManager.LoaderCallbacks {
+  public static abstract interface LoaderManager.LoaderCallbacks<D> {
     method public abstract android.content.Loader<D> onCreateLoader(int, android.os.Bundle);
     method public abstract void onLoadFinished(android.content.Loader<D>, D);
     method public abstract void onLoaderReset(android.content.Loader<D>);
@@ -5676,6 +5677,7 @@
   public class TimePickerDialog extends android.app.AlertDialog implements android.content.DialogInterface.OnClickListener android.widget.TimePicker.OnTimeChangedListener {
     ctor public TimePickerDialog(android.content.Context, android.app.TimePickerDialog.OnTimeSetListener, int, int, boolean);
     ctor public TimePickerDialog(android.content.Context, int, android.app.TimePickerDialog.OnTimeSetListener, int, int, boolean);
+    method public android.widget.TimePicker getTimePicker();
     method public void onClick(android.content.DialogInterface, int);
     method public void onTimeChanged(android.widget.TimePicker, int, int);
     method public void updateTime(int, int);
@@ -7685,7 +7687,7 @@
     ctor public AsyncQueryHandler.WorkerHandler(android.os.Looper);
   }
 
-  public abstract class AsyncTaskLoader extends android.content.Loader {
+  public abstract class AsyncTaskLoader<D> extends android.content.Loader {
     ctor public AsyncTaskLoader(android.content.Context);
     method public void cancelLoadInBackground();
     method public boolean isLoadInBackgroundCanceled();
@@ -7867,7 +7869,7 @@
     method public android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
     method public android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method protected final android.os.ParcelFileDescriptor openFileHelper(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
-    method public android.os.ParcelFileDescriptor openPipeHelper(android.net.Uri, java.lang.String, android.os.Bundle, T, android.content.ContentProvider.PipeDataWriter<T>) throws java.io.FileNotFoundException;
+    method public <T> android.os.ParcelFileDescriptor openPipeHelper(android.net.Uri, java.lang.String, android.os.Bundle, T, android.content.ContentProvider.PipeDataWriter<T>) throws java.io.FileNotFoundException;
     method public android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle) throws java.io.FileNotFoundException;
     method public android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public abstract android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
@@ -7880,7 +7882,7 @@
     method public abstract int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
   }
 
-  public static abstract interface ContentProvider.PipeDataWriter {
+  public static abstract interface ContentProvider.PipeDataWriter<T> {
     method public abstract void writeDataToPipe(android.os.ParcelFileDescriptor, android.net.Uri, java.lang.String, android.os.Bundle, T);
   }
 
@@ -8152,7 +8154,7 @@
     method public final java.lang.String getString(int);
     method public final java.lang.String getString(int, java.lang.Object...);
     method public abstract java.lang.Object getSystemService(java.lang.String);
-    method public final T getSystemService(java.lang.Class<T>);
+    method public final <T> T getSystemService(java.lang.Class<T>);
     method public abstract java.lang.String getSystemServiceName(java.lang.Class<?>);
     method public final java.lang.CharSequence getText(int);
     method public abstract android.content.res.Resources.Theme getTheme();
@@ -8509,8 +8511,8 @@
     method public long getLongExtra(java.lang.String, long);
     method public java.lang.String getPackage();
     method public android.os.Parcelable[] getParcelableArrayExtra(java.lang.String);
-    method public java.util.ArrayList<T> getParcelableArrayListExtra(java.lang.String);
-    method public T getParcelableExtra(java.lang.String);
+    method public <T extends android.os.Parcelable> java.util.ArrayList<T> getParcelableArrayListExtra(java.lang.String);
+    method public <T extends android.os.Parcelable> T getParcelableExtra(java.lang.String);
     method public java.lang.String getScheme();
     method public android.content.Intent getSelector();
     method public java.io.Serializable getSerializableExtra(java.lang.String);
@@ -8985,7 +8987,7 @@
     ctor public IntentSender.SendIntentException(java.lang.Exception);
   }
 
-  public class Loader {
+  public class Loader<D> {
     ctor public Loader(android.content.Context);
     method public void abandon();
     method public boolean cancelLoad();
@@ -9022,11 +9024,11 @@
     ctor public Loader.ForceLoadContentObserver();
   }
 
-  public static abstract interface Loader.OnLoadCanceledListener {
+  public static abstract interface Loader.OnLoadCanceledListener<D> {
     method public abstract void onLoadCanceled(android.content.Loader<D>);
   }
 
-  public static abstract interface Loader.OnLoadCompleteListener {
+  public static abstract interface Loader.OnLoadCompleteListener<D> {
     method public abstract void onLoadComplete(android.content.Loader<D>, D);
   }
 
@@ -10903,7 +10905,7 @@
     method public boolean isNull(int);
   }
 
-  public abstract class Observable {
+  public abstract class Observable<T> {
     ctor public Observable();
     method public void registerObserver(T);
     method public void unregisterAll();
@@ -12708,6 +12710,7 @@
   public class SurfaceTexture {
     ctor public SurfaceTexture(int);
     ctor public SurfaceTexture(int, boolean);
+    ctor public SurfaceTexture(boolean);
     method public void attachToGLContext(int);
     method public void detachFromGLContext();
     method public long getTimestamp();
@@ -12794,7 +12797,7 @@
   public class AnimatedStateListDrawable extends android.graphics.drawable.StateListDrawable {
     ctor public AnimatedStateListDrawable();
     method public void addState(int[], android.graphics.drawable.Drawable, int);
-    method public void addTransition(int, int, T, boolean);
+    method public <T extends android.graphics.drawable.Drawable & android.graphics.drawable.Animatable> void addTransition(int, int, T, boolean);
   }
 
   public class AnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable2 {
@@ -13919,7 +13922,7 @@
   }
 
   public final class CameraCharacteristics extends android.hardware.camera2.CameraMetadata {
-    method public T get(android.hardware.camera2.CameraCharacteristics.Key<T>);
+    method public <T> T get(android.hardware.camera2.CameraCharacteristics.Key<T>);
     method public java.util.List<android.hardware.camera2.CaptureRequest.Key<?>> getAvailableCaptureRequestKeys();
     method public java.util.List<android.hardware.camera2.CaptureResult.Key<?>> getAvailableCaptureResultKeys();
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES;
@@ -14004,7 +14007,7 @@
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> TONEMAP_MAX_CURVE_POINTS;
   }
 
-  public static final class CameraCharacteristics.Key {
+  public static final class CameraCharacteristics.Key<T> {
     method public final boolean equals(java.lang.Object);
     method public java.lang.String getName();
     method public final int hashCode();
@@ -14069,7 +14072,7 @@
     method public void onTorchModeUnavailable(java.lang.String);
   }
 
-  public abstract class CameraMetadata {
+  public abstract class CameraMetadata<TKey> {
     method public java.util.List<TKey> getKeys();
     field public static final int COLOR_CORRECTION_ABERRATION_MODE_FAST = 1; // 0x1
     field public static final int COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY = 2; // 0x2
@@ -14277,7 +14280,7 @@
 
   public final class CaptureRequest extends android.hardware.camera2.CameraMetadata implements android.os.Parcelable {
     method public int describeContents();
-    method public T get(android.hardware.camera2.CaptureRequest.Key<T>);
+    method public <T> T get(android.hardware.camera2.CaptureRequest.Key<T>);
     method public java.lang.Object getTag();
     method public boolean isReprocess();
     method public void writeToParcel(android.os.Parcel, int);
@@ -14340,20 +14343,20 @@
   public static final class CaptureRequest.Builder {
     method public void addTarget(android.view.Surface);
     method public android.hardware.camera2.CaptureRequest build();
-    method public T get(android.hardware.camera2.CaptureRequest.Key<T>);
+    method public <T> T get(android.hardware.camera2.CaptureRequest.Key<T>);
     method public void removeTarget(android.view.Surface);
-    method public void set(android.hardware.camera2.CaptureRequest.Key<T>, T);
+    method public <T> void set(android.hardware.camera2.CaptureRequest.Key<T>, T);
     method public void setTag(java.lang.Object);
   }
 
-  public static final class CaptureRequest.Key {
+  public static final class CaptureRequest.Key<T> {
     method public final boolean equals(java.lang.Object);
     method public java.lang.String getName();
     method public final int hashCode();
   }
 
   public class CaptureResult extends android.hardware.camera2.CameraMetadata {
-    method public T get(android.hardware.camera2.CaptureResult.Key<T>);
+    method public <T> T get(android.hardware.camera2.CaptureResult.Key<T>);
     method public long getFrameNumber();
     method public android.hardware.camera2.CaptureRequest getRequest();
     method public int getSequenceId();
@@ -14434,7 +14437,7 @@
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> TONEMAP_PRESET_CURVE;
   }
 
-  public static final class CaptureResult.Key {
+  public static final class CaptureResult.Key<T> {
     method public final boolean equals(java.lang.Object);
     method public java.lang.String getName();
     method public final int hashCode();
@@ -14561,14 +14564,14 @@
     method public android.util.Size[] getInputSizes(int);
     method public final int[] getOutputFormats();
     method public long getOutputMinFrameDuration(int, android.util.Size);
-    method public long getOutputMinFrameDuration(java.lang.Class<T>, android.util.Size);
-    method public android.util.Size[] getOutputSizes(java.lang.Class<T>);
+    method public <T> long getOutputMinFrameDuration(java.lang.Class<T>, android.util.Size);
+    method public <T> android.util.Size[] getOutputSizes(java.lang.Class<T>);
     method public android.util.Size[] getOutputSizes(int);
     method public long getOutputStallDuration(int, android.util.Size);
-    method public long getOutputStallDuration(java.lang.Class<T>, android.util.Size);
+    method public <T> long getOutputStallDuration(java.lang.Class<T>, android.util.Size);
     method public final int[] getValidOutputFormatsForInput(int);
     method public boolean isOutputSupportedFor(int);
-    method public static boolean isOutputSupportedFor(java.lang.Class<T>);
+    method public static <T> boolean isOutputSupportedFor(java.lang.Class<T>);
     method public boolean isOutputSupportedFor(android.view.Surface);
   }
 
@@ -16269,7 +16272,7 @@
 
 package android.icu.text {
 
-  public final class AlphabeticIndex implements java.lang.Iterable {
+  public final class AlphabeticIndex<V> implements java.lang.Iterable {
     ctor public AlphabeticIndex(android.icu.util.ULocale);
     ctor public AlphabeticIndex(java.util.Locale);
     ctor public AlphabeticIndex(android.icu.text.RuleBasedCollator);
@@ -16295,7 +16298,7 @@
     method public android.icu.text.AlphabeticIndex<V> setUnderflowLabel(java.lang.String);
   }
 
-  public static class AlphabeticIndex.Bucket implements java.lang.Iterable {
+  public static class AlphabeticIndex.Bucket<V> implements java.lang.Iterable {
     method public java.lang.String getLabel();
     method public android.icu.text.AlphabeticIndex.Bucket.LabelType getLabelType();
     method public java.util.Iterator<android.icu.text.AlphabeticIndex.Record<V>> iterator();
@@ -16311,14 +16314,14 @@
     enum_constant public static final android.icu.text.AlphabeticIndex.Bucket.LabelType UNDERFLOW;
   }
 
-  public static final class AlphabeticIndex.ImmutableIndex implements java.lang.Iterable {
+  public static final class AlphabeticIndex.ImmutableIndex<V> implements java.lang.Iterable {
     method public android.icu.text.AlphabeticIndex.Bucket<V> getBucket(int);
     method public int getBucketCount();
     method public int getBucketIndex(java.lang.CharSequence);
     method public java.util.Iterator<android.icu.text.AlphabeticIndex.Bucket<V>> iterator();
   }
 
-  public static class AlphabeticIndex.Record {
+  public static class AlphabeticIndex.Record<V> {
     method public V getData();
     method public java.lang.CharSequence getName();
   }
@@ -17831,8 +17834,8 @@
     method public final android.icu.text.UnicodeSet addAll(java.lang.CharSequence);
     method public android.icu.text.UnicodeSet addAll(android.icu.text.UnicodeSet);
     method public android.icu.text.UnicodeSet addAll(java.lang.Iterable<?>);
-    method public android.icu.text.UnicodeSet addAll(T...);
-    method public T addAllTo(T);
+    method public <T extends java.lang.CharSequence> android.icu.text.UnicodeSet addAll(T...);
+    method public <T extends java.util.Collection<java.lang.String>> T addAllTo(T);
     method public void addMatchSetTo(android.icu.text.UnicodeSet);
     method public android.icu.text.UnicodeSet applyIntPropertyValue(int, int);
     method public final android.icu.text.UnicodeSet applyPattern(java.lang.String);
@@ -17860,15 +17863,15 @@
     method public final boolean contains(java.lang.CharSequence);
     method public boolean containsAll(android.icu.text.UnicodeSet);
     method public boolean containsAll(java.lang.String);
-    method public boolean containsAll(java.lang.Iterable<T>);
+    method public <T extends java.lang.CharSequence> boolean containsAll(java.lang.Iterable<T>);
     method public boolean containsNone(int, int);
     method public boolean containsNone(android.icu.text.UnicodeSet);
     method public boolean containsNone(java.lang.CharSequence);
-    method public boolean containsNone(java.lang.Iterable<T>);
+    method public <T extends java.lang.CharSequence> boolean containsNone(java.lang.Iterable<T>);
     method public final boolean containsSome(int, int);
     method public final boolean containsSome(android.icu.text.UnicodeSet);
     method public final boolean containsSome(java.lang.CharSequence);
-    method public final boolean containsSome(java.lang.Iterable<T>);
+    method public final <T extends java.lang.CharSequence> boolean containsSome(java.lang.Iterable<T>);
     method public android.icu.text.UnicodeSet freeze();
     method public static android.icu.text.UnicodeSet from(java.lang.CharSequence);
     method public static android.icu.text.UnicodeSet fromAll(java.lang.CharSequence);
@@ -17886,14 +17889,14 @@
     method public final android.icu.text.UnicodeSet remove(java.lang.CharSequence);
     method public final android.icu.text.UnicodeSet removeAll(java.lang.CharSequence);
     method public android.icu.text.UnicodeSet removeAll(android.icu.text.UnicodeSet);
-    method public android.icu.text.UnicodeSet removeAll(java.lang.Iterable<T>);
+    method public <T extends java.lang.CharSequence> android.icu.text.UnicodeSet removeAll(java.lang.Iterable<T>);
     method public final android.icu.text.UnicodeSet removeAllStrings();
     method public android.icu.text.UnicodeSet retain(int, int);
     method public final android.icu.text.UnicodeSet retain(int);
     method public final android.icu.text.UnicodeSet retain(java.lang.CharSequence);
     method public final android.icu.text.UnicodeSet retainAll(java.lang.CharSequence);
     method public android.icu.text.UnicodeSet retainAll(android.icu.text.UnicodeSet);
-    method public android.icu.text.UnicodeSet retainAll(java.lang.Iterable<T>);
+    method public <T extends java.lang.CharSequence> android.icu.text.UnicodeSet retainAll(java.lang.Iterable<T>);
     method public android.icu.text.UnicodeSet set(int, int);
     method public android.icu.text.UnicodeSet set(android.icu.text.UnicodeSet);
     method public int size();
@@ -18303,7 +18306,7 @@
     method public long getToDate();
   }
 
-  public abstract interface Freezable implements java.lang.Cloneable {
+  public abstract interface Freezable<T> implements java.lang.Cloneable {
     method public abstract T cloneAsThawed();
     method public abstract T freeze();
     method public abstract boolean isFrozen();
@@ -18585,7 +18588,7 @@
     field public static final android.icu.util.TimeUnit YEAR;
   }
 
-  public class Output {
+  public class Output<T> {
     ctor public Output();
     ctor public Output(T);
     field public T value;
@@ -23969,19 +23972,6 @@
     field public static final android.os.Parcelable.Creator<android.net.ProxyInfo> CREATOR;
   }
 
-  public abstract class PskKeyManager {
-    ctor public PskKeyManager();
-    method public java.lang.String chooseClientKeyIdentity(java.lang.String, java.net.Socket);
-    method public java.lang.String chooseClientKeyIdentity(java.lang.String, javax.net.ssl.SSLEngine);
-    method public java.lang.String chooseServerKeyIdentityHint(java.net.Socket);
-    method public java.lang.String chooseServerKeyIdentityHint(javax.net.ssl.SSLEngine);
-    method public javax.crypto.SecretKey getKey(java.lang.String, java.lang.String, java.net.Socket);
-    method public javax.crypto.SecretKey getKey(java.lang.String, java.lang.String, javax.net.ssl.SSLEngine);
-    field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
-    field public static final int MAX_IDENTITY_LENGTH_BYTES = 128; // 0x80
-    field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100
-  }
-
   public final class RouteInfo implements android.os.Parcelable {
     method public int describeContents();
     method public android.net.IpPrefix getDestination();
@@ -28336,7 +28326,7 @@
 
 package android.os {
 
-  public abstract class AsyncTask {
+  public abstract class AsyncTask<Params, Progress, Result> {
     ctor public AsyncTask();
     method public final boolean cancel(boolean);
     method protected abstract Result doInBackground(Params...);
@@ -28565,16 +28555,16 @@
     method public float getFloat(java.lang.String, float);
     method public float[] getFloatArray(java.lang.String);
     method public java.util.ArrayList<java.lang.Integer> getIntegerArrayList(java.lang.String);
-    method public T getParcelable(java.lang.String);
+    method public <T extends android.os.Parcelable> T getParcelable(java.lang.String);
     method public android.os.Parcelable[] getParcelableArray(java.lang.String);
-    method public java.util.ArrayList<T> getParcelableArrayList(java.lang.String);
+    method public <T extends android.os.Parcelable> java.util.ArrayList<T> getParcelableArrayList(java.lang.String);
     method public java.io.Serializable getSerializable(java.lang.String);
     method public short getShort(java.lang.String);
     method public short getShort(java.lang.String, short);
     method public short[] getShortArray(java.lang.String);
     method public android.util.Size getSize(java.lang.String);
     method public android.util.SizeF getSizeF(java.lang.String);
-    method public android.util.SparseArray<T> getSparseParcelableArray(java.lang.String);
+    method public <T extends android.os.Parcelable> android.util.SparseArray<T> getSparseParcelableArray(java.lang.String);
     method public java.util.ArrayList<java.lang.String> getStringArrayList(java.lang.String);
     method public boolean hasFileDescriptors();
     method public void putAll(android.os.Bundle);
@@ -29079,8 +29069,8 @@
     method public final long[] createLongArray();
     method public final java.lang.String[] createStringArray();
     method public final java.util.ArrayList<java.lang.String> createStringArrayList();
-    method public final T[] createTypedArray(android.os.Parcelable.Creator<T>);
-    method public final java.util.ArrayList<T> createTypedArrayList(android.os.Parcelable.Creator<T>);
+    method public final <T> T[] createTypedArray(android.os.Parcelable.Creator<T>);
+    method public final <T> java.util.ArrayList<T> createTypedArrayList(android.os.Parcelable.Creator<T>);
     method public final int dataAvail();
     method public final int dataCapacity();
     method public final int dataPosition();
@@ -29113,7 +29103,7 @@
     method public final long readLong();
     method public final void readLongArray(long[]);
     method public final void readMap(java.util.Map, java.lang.ClassLoader);
-    method public final T readParcelable(java.lang.ClassLoader);
+    method public final <T extends android.os.Parcelable> T readParcelable(java.lang.ClassLoader);
     method public final android.os.Parcelable[] readParcelableArray(java.lang.ClassLoader);
     method public final android.os.PersistableBundle readPersistableBundle();
     method public final android.os.PersistableBundle readPersistableBundle(java.lang.ClassLoader);
@@ -29126,9 +29116,9 @@
     method public final void readStringArray(java.lang.String[]);
     method public final void readStringList(java.util.List<java.lang.String>);
     method public final android.os.IBinder readStrongBinder();
-    method public final void readTypedArray(T[], android.os.Parcelable.Creator<T>);
-    method public final void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>);
-    method public final T readTypedObject(android.os.Parcelable.Creator<T>);
+    method public final <T> void readTypedArray(T[], android.os.Parcelable.Creator<T>);
+    method public final <T> void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>);
+    method public final <T> T readTypedObject(android.os.Parcelable.Creator<T>);
     method public final java.lang.Object readValue(java.lang.ClassLoader);
     method public final void recycle();
     method public final void setDataCapacity(int);
@@ -29159,7 +29149,7 @@
     method public final void writeMap(java.util.Map);
     method public final void writeNoException();
     method public final void writeParcelable(android.os.Parcelable, int);
-    method public final void writeParcelableArray(T[], int);
+    method public final <T extends android.os.Parcelable> void writeParcelableArray(T[], int);
     method public final void writePersistableBundle(android.os.PersistableBundle);
     method public final void writeSerializable(java.io.Serializable);
     method public final void writeSize(android.util.Size);
@@ -29171,9 +29161,9 @@
     method public final void writeStringList(java.util.List<java.lang.String>);
     method public final void writeStrongBinder(android.os.IBinder);
     method public final void writeStrongInterface(android.os.IInterface);
-    method public final void writeTypedArray(T[], int);
-    method public final void writeTypedList(java.util.List<T>);
-    method public final void writeTypedObject(T, int);
+    method public final <T extends android.os.Parcelable> void writeTypedArray(T[], int);
+    method public final <T extends android.os.Parcelable> void writeTypedList(java.util.List<T>);
+    method public final <T extends android.os.Parcelable> void writeTypedObject(T, int);
     method public final void writeValue(java.lang.Object);
     field public static final android.os.Parcelable.Creator<java.lang.String> STRING_CREATOR;
   }
@@ -29251,11 +29241,11 @@
     field public static final int PARCELABLE_WRITE_RETURN_VALUE = 1; // 0x1
   }
 
-  public static abstract interface Parcelable.ClassLoaderCreator implements android.os.Parcelable.Creator {
+  public static abstract interface Parcelable.ClassLoaderCreator<T> implements android.os.Parcelable.Creator {
     method public abstract T createFromParcel(android.os.Parcel, java.lang.ClassLoader);
   }
 
-  public static abstract interface Parcelable.Creator {
+  public static abstract interface Parcelable.Creator<T> {
     method public abstract T createFromParcel(android.os.Parcel);
     method public abstract T[] newArray(int);
   }
@@ -29371,7 +29361,7 @@
     method public abstract void onProgress(int);
   }
 
-  public class RemoteCallbackList {
+  public class RemoteCallbackList<E extends android.os.IInterface> {
     ctor public RemoteCallbackList();
     method public int beginBroadcast();
     method public void finishBroadcast();
@@ -34705,7 +34695,7 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.carrier.CarrierMessagingService";
   }
 
-  public static abstract interface CarrierMessagingService.ResultCallback {
+  public static abstract interface CarrierMessagingService.ResultCallback<T> {
     method public abstract void onReceiveResult(T) throws android.os.RemoteException;
   }
 
@@ -34857,7 +34847,7 @@
     field public static final java.lang.String EXTRA_SUGGESTION_KEYWORDS = "android.service.media.extra.SUGGESTION_KEYWORDS";
   }
 
-  public class MediaBrowserService.Result {
+  public class MediaBrowserService.Result<T> {
     method public void detach();
     method public void sendResult(T);
   }
@@ -37007,6 +36997,7 @@
     field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
     field public static final java.lang.String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT = "duration_blocking_disabled_after_emergency_int";
     field public static final java.lang.String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool";
+    field public static final java.lang.String KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL = "editable_voicemail_number_bool";
     field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_key_vibration_bool";
     field public static final java.lang.String KEY_FORCE_HOME_NETWORK_BOOL = "force_home_network_bool";
     field public static final java.lang.String KEY_GSM_DTMF_TONE_DELAY_INT = "gsm_dtmf_tone_delay_int";
@@ -37785,14 +37776,14 @@
 
 package android.test {
 
-  public abstract deprecated class ActivityInstrumentationTestCase extends android.test.ActivityTestCase {
+  public abstract deprecated class ActivityInstrumentationTestCase<T extends android.app.Activity> extends android.test.ActivityTestCase {
     ctor public ActivityInstrumentationTestCase(java.lang.String, java.lang.Class<T>);
     ctor public ActivityInstrumentationTestCase(java.lang.String, java.lang.Class<T>, boolean);
     method public T getActivity();
     method public void testActivityTestCaseSetUpProperly() throws java.lang.Exception;
   }
 
-  public abstract deprecated class ActivityInstrumentationTestCase2 extends android.test.ActivityTestCase {
+  public abstract deprecated class ActivityInstrumentationTestCase2<T extends android.app.Activity> extends android.test.ActivityTestCase {
     ctor public deprecated ActivityInstrumentationTestCase2(java.lang.String, java.lang.Class<T>);
     ctor public ActivityInstrumentationTestCase2(java.lang.Class<T>);
     method public T getActivity();
@@ -37807,7 +37798,7 @@
     method protected void setActivity(android.app.Activity);
   }
 
-  public abstract deprecated class ActivityUnitTestCase extends android.test.ActivityTestCase {
+  public abstract deprecated class ActivityUnitTestCase<T extends android.app.Activity> extends android.test.ActivityTestCase {
     ctor public ActivityUnitTestCase(java.lang.Class<T>);
     method public T getActivity();
     method public int getFinishedActivityRequest();
@@ -37853,7 +37844,7 @@
     method public void testStarted(java.lang.String);
   }
 
-  public abstract deprecated class ApplicationTestCase extends android.test.AndroidTestCase {
+  public abstract deprecated class ApplicationTestCase<T extends android.app.Application> extends android.test.AndroidTestCase {
     ctor public ApplicationTestCase(java.lang.Class<T>);
     method protected final void createApplication();
     method public T getApplication();
@@ -37879,8 +37870,8 @@
     method public android.app.Instrumentation getInstrumentation();
     method public deprecated void injectInsrumentation(android.app.Instrumentation);
     method public void injectInstrumentation(android.app.Instrumentation);
-    method public final T launchActivity(java.lang.String, java.lang.Class<T>, android.os.Bundle);
-    method public final T launchActivityWithIntent(java.lang.String, java.lang.Class<T>, android.content.Intent);
+    method public final <T extends android.app.Activity> T launchActivity(java.lang.String, java.lang.Class<T>, android.os.Bundle);
+    method public final <T extends android.app.Activity> T launchActivityWithIntent(java.lang.String, java.lang.Class<T>, android.content.Intent);
     method public void runTestOnUiThread(java.lang.Runnable) throws java.lang.Throwable;
     method public void sendKeys(java.lang.String);
     method public void sendKeys(int...);
@@ -37920,7 +37911,7 @@
 
   public class LoaderTestCase extends android.test.AndroidTestCase {
     ctor public LoaderTestCase();
-    method public T getLoaderResultSynchronously(android.content.Loader<T>);
+    method public <T> T getLoaderResultSynchronously(android.content.Loader<T>);
   }
 
   public final deprecated class MoreAsserts {
@@ -37975,20 +37966,20 @@
     method public abstract void startTiming(boolean);
   }
 
-  public abstract deprecated class ProviderTestCase extends android.test.InstrumentationTestCase {
+  public abstract deprecated class ProviderTestCase<T extends android.content.ContentProvider> extends android.test.InstrumentationTestCase {
     ctor public ProviderTestCase(java.lang.Class<T>, java.lang.String);
     method public android.test.mock.MockContentResolver getMockContentResolver();
     method public android.test.IsolatedContext getMockContext();
     method public T getProvider();
-    method public static android.content.ContentResolver newResolverWithContentProviderFromSql(android.content.Context, java.lang.Class<T>, java.lang.String, java.lang.String, int, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public static <T extends android.content.ContentProvider> android.content.ContentResolver newResolverWithContentProviderFromSql(android.content.Context, java.lang.Class<T>, java.lang.String, java.lang.String, int, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
   }
 
-  public abstract class ProviderTestCase2 extends android.test.AndroidTestCase {
+  public abstract class ProviderTestCase2<T extends android.content.ContentProvider> extends android.test.AndroidTestCase {
     ctor public ProviderTestCase2(java.lang.Class<T>, java.lang.String);
     method public android.test.mock.MockContentResolver getMockContentResolver();
     method public android.test.IsolatedContext getMockContext();
     method public T getProvider();
-    method public static android.content.ContentResolver newResolverWithContentProviderFromSql(android.content.Context, java.lang.String, java.lang.Class<T>, java.lang.String, java.lang.String, int, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public static <T extends android.content.ContentProvider> android.content.ContentResolver newResolverWithContentProviderFromSql(android.content.Context, java.lang.String, java.lang.Class<T>, java.lang.String, java.lang.String, int, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
   }
 
   public deprecated class RenamingDelegatingContext extends android.content.ContextWrapper {
@@ -37996,11 +37987,11 @@
     ctor public RenamingDelegatingContext(android.content.Context, android.content.Context, java.lang.String);
     method public java.lang.String getDatabasePrefix();
     method public void makeExistingFilesAndDbsAccessible();
-    method public static T providerWithRenamedContext(java.lang.Class<T>, android.content.Context, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
-    method public static T providerWithRenamedContext(java.lang.Class<T>, android.content.Context, java.lang.String, boolean) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public static <T extends android.content.ContentProvider> T providerWithRenamedContext(java.lang.Class<T>, android.content.Context, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public static <T extends android.content.ContentProvider> T providerWithRenamedContext(java.lang.Class<T>, android.content.Context, java.lang.String, boolean) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
   }
 
-  public abstract deprecated class ServiceTestCase extends android.test.AndroidTestCase {
+  public abstract deprecated class ServiceTestCase<T extends android.app.Service> extends android.test.AndroidTestCase {
     ctor public ServiceTestCase(java.lang.Class<T>);
     method protected android.os.IBinder bindService(android.content.Intent);
     method public android.app.Application getApplication();
@@ -38013,7 +38004,7 @@
     method public void testServiceTestCaseSetUpProperly() throws java.lang.Exception;
   }
 
-  public abstract deprecated class SingleLaunchActivityTestCase extends android.test.InstrumentationTestCase {
+  public abstract deprecated class SingleLaunchActivityTestCase<T extends android.app.Activity> extends android.test.InstrumentationTestCase {
     ctor public SingleLaunchActivityTestCase(java.lang.String, java.lang.Class<T>);
     method public T getActivity();
     method public void testActivityTestCaseSetUpProperly() throws java.lang.Exception;
@@ -38370,7 +38361,7 @@
     ctor public TestMethod(java.lang.String, java.lang.Class<? extends junit.framework.TestCase>);
     ctor public TestMethod(junit.framework.TestCase);
     method public junit.framework.TestCase createTest() throws java.lang.IllegalAccessException, java.lang.InstantiationException, java.lang.reflect.InvocationTargetException;
-    method public T getAnnotation(java.lang.Class<T>);
+    method public <T extends java.lang.annotation.Annotation> T getAnnotation(java.lang.Class<T>);
     method public java.lang.Class<? extends junit.framework.TestCase> getEnclosingClass();
     method public java.lang.String getEnclosingClassname();
     method public java.lang.String getName();
@@ -38818,7 +38809,7 @@
     method public int getSpanEnd(java.lang.Object);
     method public int getSpanFlags(java.lang.Object);
     method public int getSpanStart(java.lang.Object);
-    method public T[] getSpans(int, int, java.lang.Class<T>);
+    method public <T> T[] getSpans(int, int, java.lang.Class<T>);
     method public deprecated int getTextRunCursor(int, int, int, int, int, android.graphics.Paint);
     method public int getTextWatcherDepth();
     method public android.text.SpannableStringBuilder insert(int, java.lang.CharSequence, int, int);
@@ -38840,7 +38831,7 @@
     method public int getSpanEnd(java.lang.Object);
     method public int getSpanFlags(java.lang.Object);
     method public int getSpanStart(java.lang.Object);
-    method public T[] getSpans(int, int, java.lang.Class<T>);
+    method public <T> T[] getSpans(int, int, java.lang.Class<T>);
     method public final int length();
     method public int nextSpanTransition(int, int, java.lang.Class);
     method public final java.lang.String toString();
@@ -38850,7 +38841,7 @@
     method public abstract int getSpanEnd(java.lang.Object);
     method public abstract int getSpanFlags(java.lang.Object);
     method public abstract int getSpanStart(java.lang.Object);
-    method public abstract T[] getSpans(int, int, java.lang.Class<T>);
+    method public abstract <T> T[] getSpans(int, int, java.lang.Class<T>);
     method public abstract int nextSpanTransition(int, int, java.lang.Class);
     field public static final int SPAN_COMPOSING = 256; // 0x100
     field public static final int SPAN_EXCLUSIVE_EXCLUSIVE = 33; // 0x21
@@ -39828,7 +39819,7 @@
     field public static final int WEEKDAY_WEDNESDAY = 4; // 0x4
   }
 
-  public static class TtsSpan.Builder {
+  public static class TtsSpan.Builder<C extends android.text.style.TtsSpan.Builder<?>> {
     ctor public TtsSpan.Builder(java.lang.String);
     method public android.text.style.TtsSpan build();
     method public C setIntArgument(java.lang.String, int);
@@ -39924,7 +39915,7 @@
     method public android.text.style.TtsSpan.OrdinalBuilder setNumber(java.lang.String);
   }
 
-  public static class TtsSpan.SemioticClassBuilder extends android.text.style.TtsSpan.Builder {
+  public static class TtsSpan.SemioticClassBuilder<C extends android.text.style.TtsSpan.SemioticClassBuilder<?>> extends android.text.style.TtsSpan.Builder {
     ctor public TtsSpan.SemioticClassBuilder(java.lang.String);
     method public C setAnimacy(java.lang.String);
     method public C setCase(java.lang.String);
@@ -40332,7 +40323,7 @@
     ctor public AndroidRuntimeException(java.lang.Exception);
   }
 
-  public final class ArrayMap implements java.util.Map {
+  public final class ArrayMap<K, V> implements java.util.Map {
     ctor public ArrayMap();
     ctor public ArrayMap(int);
     ctor public ArrayMap(android.util.ArrayMap<K, V>);
@@ -40360,7 +40351,7 @@
     method public java.util.Collection<V> values();
   }
 
-  public final class ArraySet implements java.util.Collection java.util.Set {
+  public final class ArraySet<E> implements java.util.Collection java.util.Set {
     ctor public ArraySet();
     ctor public ArraySet(int);
     ctor public ArraySet(android.util.ArraySet<E>);
@@ -40381,7 +40372,7 @@
     method public boolean retainAll(java.util.Collection<?>);
     method public int size();
     method public java.lang.Object[] toArray();
-    method public T[] toArray(T[]);
+    method public <T> T[] toArray(T[]);
     method public E valueAt(int);
   }
 
@@ -40526,13 +40517,13 @@
   public deprecated class FloatMath {
   }
 
-  public abstract class FloatProperty extends android.util.Property {
+  public abstract class FloatProperty<T> extends android.util.Property {
     ctor public FloatProperty(java.lang.String);
     method public final void set(T, java.lang.Float);
     method public abstract void setValue(T, float);
   }
 
-  public abstract class IntProperty extends android.util.Property {
+  public abstract class IntProperty<T> extends android.util.Property {
     ctor public IntProperty(java.lang.String);
     method public final void set(T, java.lang.Integer);
     method public abstract void setValue(T, int);
@@ -40632,7 +40623,7 @@
     method public void println(java.lang.String);
   }
 
-  public class LongSparseArray implements java.lang.Cloneable {
+  public class LongSparseArray<E> implements java.lang.Cloneable {
     ctor public LongSparseArray();
     ctor public LongSparseArray(int);
     method public void append(long, E);
@@ -40653,7 +40644,7 @@
     method public E valueAt(int);
   }
 
-  public class LruCache {
+  public class LruCache<K, V> {
     ctor public LruCache(int);
     method protected V create(K);
     method public final synchronized int createCount();
@@ -40741,9 +40732,9 @@
     ctor public NoSuchPropertyException(java.lang.String);
   }
 
-  public class Pair {
+  public class Pair<F, S> {
     ctor public Pair(F, S);
-    method public static android.util.Pair<A, B> create(A, B);
+    method public static <A, B> android.util.Pair<A, B> create(A, B);
     field public final F first;
     field public final S second;
   }
@@ -40776,22 +40767,22 @@
     method public abstract void println(java.lang.String);
   }
 
-  public abstract class Property {
+  public abstract class Property<T, V> {
     ctor public Property(java.lang.Class<V>, java.lang.String);
     method public abstract V get(T);
     method public java.lang.String getName();
     method public java.lang.Class<V> getType();
     method public boolean isReadOnly();
-    method public static android.util.Property<T, V> of(java.lang.Class<T>, java.lang.Class<V>, java.lang.String);
+    method public static <T, V> android.util.Property<T, V> of(java.lang.Class<T>, java.lang.Class<V>, java.lang.String);
     method public void set(T, V);
   }
 
-  public final class Range {
+  public final class Range<T extends java.lang.Comparable<? super T>> {
     ctor public Range(T, T);
     method public T clamp(T);
     method public boolean contains(T);
     method public boolean contains(android.util.Range<T>);
-    method public static android.util.Range<T> create(T, T);
+    method public static <T extends java.lang.Comparable<? super T>> android.util.Range<T> create(T, T);
     method public android.util.Range<T> extend(android.util.Range<T>);
     method public android.util.Range<T> extend(T, T);
     method public android.util.Range<T> extend(T);
@@ -40835,7 +40826,7 @@
     method public static android.util.SizeF parseSizeF(java.lang.String) throws java.lang.NumberFormatException;
   }
 
-  public class SparseArray implements java.lang.Cloneable {
+  public class SparseArray<E> implements java.lang.Cloneable {
     ctor public SparseArray();
     ctor public SparseArray(int);
     method public void append(int, E);
@@ -42134,6 +42125,7 @@
     method public final void recycle();
     method public final void setAction(int);
     method public final void setActionButton(int);
+    method public final void setButtonState(int);
     method public final void setEdgeFlags(int);
     method public final void setLocation(float, float);
     method public final void setSource(int);
@@ -45573,7 +45565,7 @@
     method public static java.lang.String stripAnchor(java.lang.String);
   }
 
-  public abstract interface ValueCallback {
+  public abstract interface ValueCallback<T> {
     method public abstract void onReceiveValue(T);
   }
 
@@ -45934,7 +45926,7 @@
     method public int getContentHeight();
     method public android.graphics.Bitmap getFavicon();
     method public android.webkit.WebView.HitTestResult getHitTestResult();
-    method public java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
+    method public deprecated java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
     method public java.lang.String getOriginalUrl();
     method public int getProgress();
     method public deprecated float getScale();
@@ -45977,7 +45969,7 @@
     method public void setDownloadListener(android.webkit.DownloadListener);
     method public void setFindListener(android.webkit.WebView.FindListener);
     method public deprecated void setHorizontalScrollbarOverlay(boolean);
-    method public void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public deprecated void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
     method public void setInitialScale(int);
     method public deprecated void setMapTrackballToArrowKeys(boolean);
     method public void setNetworkAvailable(boolean);
@@ -46075,10 +46067,12 @@
     method public abstract void clearFormData();
     method public abstract void clearHttpAuthUsernamePassword();
     method public abstract deprecated void clearUsernamePassword();
+    method public abstract java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
     method public static android.webkit.WebViewDatabase getInstance(android.content.Context);
     method public abstract boolean hasFormData();
     method public abstract boolean hasHttpAuthUsernamePassword();
     method public abstract deprecated boolean hasUsernamePassword();
+    method public abstract void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
   }
 
   public class WebViewFragment extends android.app.Fragment {
@@ -46307,7 +46301,7 @@
     field public static final int NO_SELECTION = -2147483648; // 0x80000000
   }
 
-  public abstract class AdapterView extends android.view.ViewGroup {
+  public abstract class AdapterView<T extends android.widget.Adapter> extends android.view.ViewGroup {
     ctor public AdapterView(android.content.Context);
     ctor public AdapterView(android.content.Context, android.util.AttributeSet);
     ctor public AdapterView(android.content.Context, android.util.AttributeSet, int);
@@ -46430,7 +46424,7 @@
     ctor public AnalogClock(android.content.Context, android.util.AttributeSet, int, int);
   }
 
-  public class ArrayAdapter extends android.widget.BaseAdapter implements android.widget.Filterable android.widget.ThemedSpinnerAdapter {
+  public class ArrayAdapter<T> extends android.widget.BaseAdapter implements android.widget.Filterable android.widget.ThemedSpinnerAdapter {
     ctor public ArrayAdapter(android.content.Context, int);
     ctor public ArrayAdapter(android.content.Context, int, int);
     ctor public ArrayAdapter(android.content.Context, int, T[]);
@@ -46491,7 +46485,7 @@
     method protected void performFiltering(java.lang.CharSequence, int);
     method public void performValidation();
     method protected void replaceText(java.lang.CharSequence);
-    method public void setAdapter(T);
+    method public <T extends android.widget.ListAdapter & android.widget.Filterable> void setAdapter(T);
     method public void setCompletionHint(java.lang.CharSequence);
     method public void setDropDownAnchor(int);
     method public void setDropDownBackgroundDrawable(android.graphics.drawable.Drawable);
@@ -46743,6 +46737,7 @@
     method public int getFirstDayOfWeek();
     method public long getMaxDate();
     method public long getMinDate();
+    method public int getMode();
     method public int getMonth();
     method public deprecated boolean getSpinnersShown();
     method public int getYear();
@@ -46754,6 +46749,8 @@
     method public void setOnDateChangedListener(android.widget.DatePicker.OnDateChangedListener);
     method public deprecated void setSpinnersShown(boolean);
     method public void updateDate(int, int, int);
+    field public static final int MODE_CALENDAR = 2; // 0x2
+    field public static final int MODE_SPINNER = 1; // 0x1
   }
 
   public static abstract interface DatePicker.OnDateChangedListener {
@@ -48523,6 +48520,7 @@
     method public android.view.View getHourView();
     method public int getMinute();
     method public android.view.View getMinuteView();
+    method public int getMode();
     method public android.view.View getPmView();
     method public boolean is24HourView();
     method public deprecated void setCurrentHour(java.lang.Integer);
@@ -48531,6 +48529,8 @@
     method public void setIs24HourView(java.lang.Boolean);
     method public void setMinute(int);
     method public void setOnTimeChangedListener(android.widget.TimePicker.OnTimeChangedListener);
+    field public static final int MODE_CLOCK = 2; // 0x2
+    field public static final int MODE_SPINNER = 1; // 0x1
   }
 
   public static abstract interface TimePicker.OnTimeChangedListener {
@@ -48785,7 +48785,7 @@
 
 package com.android.internal.util {
 
-  public abstract interface Predicate {
+  public abstract interface Predicate<T> {
     method public abstract boolean apply(T);
   }
 
@@ -50857,22 +50857,22 @@
     enum_constant public static final java.lang.Character.UnicodeScript YI;
   }
 
-  public final class Class implements java.lang.reflect.AnnotatedElement java.lang.reflect.GenericDeclaration java.io.Serializable java.lang.reflect.Type {
-    method public java.lang.Class<? extends U> asSubclass(java.lang.Class<U>);
+  public final class Class<T> implements java.lang.reflect.AnnotatedElement java.lang.reflect.GenericDeclaration java.io.Serializable java.lang.reflect.Type {
+    method public <U> java.lang.Class<? extends U> asSubclass(java.lang.Class<U>);
     method public T cast(java.lang.Object);
     method public boolean desiredAssertionStatus();
     method public static java.lang.Class<?> forName(java.lang.String) throws java.lang.ClassNotFoundException;
     method public static java.lang.Class<?> forName(java.lang.String, boolean, java.lang.ClassLoader) throws java.lang.ClassNotFoundException;
-    method public A getAnnotation(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
-    method public A[] getAnnotationsByType(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A[] getAnnotationsByType(java.lang.Class<A>);
     method public java.lang.String getCanonicalName();
     method public java.lang.ClassLoader getClassLoader();
     method public java.lang.Class<?>[] getClasses();
     method public java.lang.Class<?> getComponentType();
     method public java.lang.reflect.Constructor<T> getConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
-    method public A getDeclaredAnnotation(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A getDeclaredAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public java.lang.Class<?>[] getDeclaredClasses();
     method public java.lang.reflect.Constructor<T> getDeclaredConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
@@ -50984,7 +50984,7 @@
   public abstract interface Cloneable {
   }
 
-  public abstract interface Comparable {
+  public abstract interface Comparable<T> {
     method public abstract int compareTo(T);
   }
 
@@ -51038,7 +51038,7 @@
     field public static final java.lang.Class<java.lang.Double> TYPE;
   }
 
-  public abstract class Enum implements java.lang.Comparable java.io.Serializable {
+  public abstract class Enum<E extends java.lang.Enum<E>> implements java.lang.Comparable java.io.Serializable {
     ctor protected Enum(java.lang.String, int);
     method protected final java.lang.Object clone() throws java.lang.CloneNotSupportedException;
     method public final int compareTo(E);
@@ -51048,7 +51048,7 @@
     method public final int hashCode();
     method public final java.lang.String name();
     method public final int ordinal();
-    method public static T valueOf(java.lang.Class<T>, java.lang.String);
+    method public static <T extends java.lang.Enum<T>> T valueOf(java.lang.Class<T>, java.lang.String);
   }
 
   public class EnumConstantNotPresentException extends java.lang.RuntimeException {
@@ -51167,7 +51167,7 @@
     ctor public IndexOutOfBoundsException(java.lang.String);
   }
 
-  public class InheritableThreadLocal extends java.lang.ThreadLocal {
+  public class InheritableThreadLocal<T> extends java.lang.ThreadLocal {
     ctor public InheritableThreadLocal();
     method protected T childValue(T);
   }
@@ -51246,7 +51246,7 @@
     ctor public InterruptedException(java.lang.String);
   }
 
-  public abstract interface Iterable {
+  public abstract interface Iterable<T> {
     method public default void forEach(java.util.function.Consumer<? super T>);
     method public abstract java.util.Iterator<T> iterator();
     method public default java.util.Spliterator<T> spliterator();
@@ -51461,12 +51461,12 @@
   }
 
   public class Package implements java.lang.reflect.AnnotatedElement {
-    method public A getAnnotation(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
-    method public A[] getAnnotationsByType(java.lang.Class<A>);
-    method public A getDeclaredAnnotation(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A[] getAnnotationsByType(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A getDeclaredAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
-    method public A[] getDeclaredAnnotationsByType(java.lang.Class<A>);
+    method public <A extends java.lang.annotation.Annotation> A[] getDeclaredAnnotationsByType(java.lang.Class<A>);
     method public java.lang.String getImplementationTitle();
     method public java.lang.String getImplementationVendor();
     method public java.lang.String getImplementationVersion();
@@ -52065,13 +52065,13 @@
     method public void uncaughtException(java.lang.Thread, java.lang.Throwable);
   }
 
-  public class ThreadLocal {
+  public class ThreadLocal<T> {
     ctor public ThreadLocal();
     method public T get();
     method protected T initialValue();
     method public void remove();
     method public void set(T);
-    method public static java.lang.ThreadLocal<S> withInitial(java.util.function.Supplier<? extends S>);
+    method public static <S> java.lang.ThreadLocal<S> withInitial(java.util.function.Supplier<? extends S>);
   }
 
   public class Throwable implements java.io.Serializable {
@@ -52174,6 +52174,8 @@
     enum_constant public static final java.lang.annotation.ElementType PACKAGE;
     enum_constant public static final java.lang.annotation.ElementType PARAMETER;
     enum_constant public static final java.lang.annotation.ElementType TYPE;
+    enum_constant public static final java.lang.annotation.ElementType TYPE_PARAMETER;
+    enum_constant public static final java.lang.annotation.ElementType TYPE_USE;
   }
 
   public class IncompleteAnnotationException extends java.lang.RuntimeException {
@@ -52209,30 +52211,30 @@
 
 package java.lang.ref {
 
-  public class PhantomReference extends java.lang.ref.Reference {
+  public class PhantomReference<T> extends java.lang.ref.Reference {
     ctor public PhantomReference(T, java.lang.ref.ReferenceQueue<? super T>);
   }
 
-  public abstract class Reference {
+  public abstract class Reference<T> {
     method public void clear();
     method public boolean enqueue();
     method public T get();
     method public boolean isEnqueued();
   }
 
-  public class ReferenceQueue {
+  public class ReferenceQueue<T> {
     ctor public ReferenceQueue();
     method public java.lang.ref.Reference<? extends T> poll();
     method public java.lang.ref.Reference<? extends T> remove(long) throws java.lang.IllegalArgumentException, java.lang.InterruptedException;
     method public java.lang.ref.Reference<? extends T> remove() throws java.lang.InterruptedException;
   }
 
-  public class SoftReference extends java.lang.ref.Reference {
+  public class SoftReference<T> extends java.lang.ref.Reference {
     ctor public SoftReference(T);
     ctor public SoftReference(T, java.lang.ref.ReferenceQueue<? super T>);
   }
 
-  public class WeakReference extends java.lang.ref.Reference {
+  public class WeakReference<T> extends java.lang.ref.Reference {
     ctor public WeakReference(T);
     ctor public WeakReference(T, java.lang.ref.ReferenceQueue<? super T>);
   }
@@ -52243,7 +52245,7 @@
 
   public class AccessibleObject implements java.lang.reflect.AnnotatedElement {
     ctor protected AccessibleObject();
-    method public T getAnnotation(java.lang.Class<T>);
+    method public <T extends java.lang.annotation.Annotation> T getAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getAnnotations();
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public boolean isAccessible();
@@ -52252,12 +52254,12 @@
   }
 
   public abstract interface AnnotatedElement {
-    method public abstract T getAnnotation(java.lang.Class<T>);
+    method public abstract <T extends java.lang.annotation.Annotation> T getAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getAnnotations();
-    method public default T[] getAnnotationsByType(java.lang.Class<T>);
-    method public default java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
+    method public default <T extends java.lang.annotation.Annotation> T[] getAnnotationsByType(java.lang.Class<T>);
+    method public default <T extends java.lang.annotation.Annotation> T getDeclaredAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getDeclaredAnnotations();
-    method public default T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
+    method public default <T extends java.lang.annotation.Annotation> T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public default boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
   }
 
@@ -52285,7 +52287,7 @@
     method public static void setShort(java.lang.Object, int, short) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
   }
 
-  public final class Constructor extends java.lang.reflect.Executable {
+  public final class Constructor<T> extends java.lang.reflect.Executable {
     method public java.lang.Class<T> getDeclaringClass();
     method public java.lang.Class<?>[] getExceptionTypes();
     method public int getModifiers();
@@ -52433,7 +52435,7 @@
   }
 
   public final class Parameter implements java.lang.reflect.AnnotatedElement {
-    method public T getAnnotation(java.lang.Class<T>);
+    method public <T extends java.lang.annotation.Annotation> T getAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getAnnotations();
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public java.lang.reflect.Executable getDeclaringExecutable();
@@ -52470,7 +52472,7 @@
   public abstract interface Type {
   }
 
-  public abstract interface TypeVariable implements java.lang.reflect.Type {
+  public abstract interface TypeVariable<D extends java.lang.reflect.GenericDeclaration> implements java.lang.reflect.Type {
     method public abstract java.lang.reflect.Type[] getBounds();
     method public abstract D getGenericDeclaration();
     method public abstract java.lang.String getName();
@@ -53259,7 +53261,7 @@
     method public abstract java.net.SocketImpl createSocketImpl();
   }
 
-  public abstract interface SocketOption {
+  public abstract interface SocketOption<T> {
     method public abstract java.lang.String name();
     method public abstract java.lang.Class<T> type();
   }
@@ -53791,9 +53793,9 @@
   }
 
   public abstract interface AsynchronousByteChannel implements java.nio.channels.AsynchronousChannel {
-    method public abstract void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer);
-    method public abstract void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer);
   }
 
@@ -53821,25 +53823,25 @@
   public abstract class AsynchronousFileChannel implements java.nio.channels.AsynchronousChannel {
     ctor protected AsynchronousFileChannel();
     method public abstract void force(boolean) throws java.io.IOException;
-    method public abstract void lock(long, long, boolean, A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
-    method public final void lock(A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
+    method public abstract <A> void lock(long, long, boolean, A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
+    method public final <A> void lock(A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
     method public abstract java.util.concurrent.Future<java.nio.channels.FileLock> lock(long, long, boolean);
     method public final java.util.concurrent.Future<java.nio.channels.FileLock> lock();
     method public static java.nio.channels.AsynchronousFileChannel open(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.util.concurrent.ExecutorService, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
     method public static java.nio.channels.AsynchronousFileChannel open(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public abstract void read(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void read(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer, long);
     method public abstract long size() throws java.io.IOException;
     method public abstract java.nio.channels.AsynchronousFileChannel truncate(long) throws java.io.IOException;
     method public abstract java.nio.channels.FileLock tryLock(long, long, boolean) throws java.io.IOException;
     method public final java.nio.channels.FileLock tryLock() throws java.io.IOException;
-    method public abstract void write(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void write(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer, long);
   }
 
   public abstract class AsynchronousServerSocketChannel implements java.nio.channels.AsynchronousChannel java.nio.channels.NetworkChannel {
     ctor protected AsynchronousServerSocketChannel(java.nio.channels.spi.AsynchronousChannelProvider);
-    method public abstract void accept(A, java.nio.channels.CompletionHandler<java.nio.channels.AsynchronousSocketChannel, ? super A>);
+    method public abstract <A> void accept(A, java.nio.channels.CompletionHandler<java.nio.channels.AsynchronousSocketChannel, ? super A>);
     method public abstract java.util.concurrent.Future<java.nio.channels.AsynchronousSocketChannel> accept();
     method public final java.nio.channels.AsynchronousServerSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.nio.channels.AsynchronousServerSocketChannel bind(java.net.SocketAddress, int) throws java.io.IOException;
@@ -53847,30 +53849,30 @@
     method public static java.nio.channels.AsynchronousServerSocketChannel open(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
     method public static java.nio.channels.AsynchronousServerSocketChannel open() throws java.io.IOException;
     method public final java.nio.channels.spi.AsynchronousChannelProvider provider();
-    method public abstract java.nio.channels.AsynchronousServerSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <T> java.nio.channels.AsynchronousServerSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
   }
 
   public abstract class AsynchronousSocketChannel implements java.nio.channels.AsynchronousByteChannel java.nio.channels.NetworkChannel {
     ctor protected AsynchronousSocketChannel(java.nio.channels.spi.AsynchronousChannelProvider);
     method public abstract java.nio.channels.AsynchronousSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
-    method public abstract void connect(java.net.SocketAddress, A, java.nio.channels.CompletionHandler<java.lang.Void, ? super A>);
+    method public abstract <A> void connect(java.net.SocketAddress, A, java.nio.channels.CompletionHandler<java.lang.Void, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Void> connect(java.net.SocketAddress);
     method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
     method public abstract java.net.SocketAddress getRemoteAddress() throws java.io.IOException;
     method public static java.nio.channels.AsynchronousSocketChannel open(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
     method public static java.nio.channels.AsynchronousSocketChannel open() throws java.io.IOException;
     method public final java.nio.channels.spi.AsynchronousChannelProvider provider();
-    method public abstract void read(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public final void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void read(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public final <A> void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer);
-    method public abstract void read(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
-    method public abstract java.nio.channels.AsynchronousSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <A> void read(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
+    method public abstract <T> java.nio.channels.AsynchronousSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public abstract java.nio.channels.AsynchronousSocketChannel shutdownInput() throws java.io.IOException;
     method public abstract java.nio.channels.AsynchronousSocketChannel shutdownOutput() throws java.io.IOException;
-    method public abstract void write(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public final void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public abstract <A> void write(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
+    method public final <A> void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer);
-    method public abstract void write(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
+    method public abstract <A> void write(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
   }
 
   public abstract interface ByteChannel implements java.nio.channels.ReadableByteChannel java.nio.channels.WritableByteChannel {
@@ -53910,7 +53912,7 @@
     ctor public ClosedSelectorException();
   }
 
-  public abstract interface CompletionHandler {
+  public abstract interface CompletionHandler<V, A> {
     method public abstract void completed(V, A);
     method public abstract void failed(java.lang.Throwable, A);
   }
@@ -53934,7 +53936,7 @@
     method public final long read(java.nio.ByteBuffer[]) throws java.io.IOException;
     method public abstract java.net.SocketAddress receive(java.nio.ByteBuffer) throws java.io.IOException;
     method public abstract int send(java.nio.ByteBuffer, java.net.SocketAddress) throws java.io.IOException;
-    method public abstract java.nio.channels.DatagramChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <T> java.nio.channels.DatagramChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public abstract java.net.DatagramSocket socket();
     method public final int validOps();
     method public abstract int write(java.nio.ByteBuffer) throws java.io.IOException;
@@ -54039,8 +54041,8 @@
   public abstract interface NetworkChannel implements java.nio.channels.Channel {
     method public abstract java.nio.channels.NetworkChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
-    method public abstract T getOption(java.net.SocketOption<T>) throws java.io.IOException;
-    method public abstract java.nio.channels.NetworkChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <T> T getOption(java.net.SocketOption<T>) throws java.io.IOException;
+    method public abstract <T> java.nio.channels.NetworkChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public abstract java.util.Set<java.net.SocketOption<?>> supportedOptions();
   }
 
@@ -54162,7 +54164,7 @@
     method public abstract java.nio.channels.ServerSocketChannel bind(java.net.SocketAddress, int) throws java.io.IOException;
     method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
     method public static java.nio.channels.ServerSocketChannel open() throws java.io.IOException;
-    method public abstract java.nio.channels.ServerSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <T> java.nio.channels.ServerSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public abstract java.net.ServerSocket socket();
     method public final int validOps();
   }
@@ -54185,7 +54187,7 @@
     method public abstract int read(java.nio.ByteBuffer) throws java.io.IOException;
     method public abstract long read(java.nio.ByteBuffer[], int, int) throws java.io.IOException;
     method public final long read(java.nio.ByteBuffer[]) throws java.io.IOException;
-    method public abstract java.nio.channels.SocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
+    method public abstract <T> java.nio.channels.SocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public abstract java.nio.channels.SocketChannel shutdownInput() throws java.io.IOException;
     method public abstract java.nio.channels.SocketChannel shutdownOutput() throws java.io.IOException;
     method public abstract java.net.Socket socket();
@@ -54470,11 +54472,11 @@
     ctor public DirectoryNotEmptyException(java.lang.String);
   }
 
-  public abstract interface DirectoryStream implements java.io.Closeable java.lang.Iterable {
+  public abstract interface DirectoryStream<T> implements java.io.Closeable java.lang.Iterable {
     method public abstract java.util.Iterator<T> iterator();
   }
 
-  public static abstract interface DirectoryStream.Filter {
+  public static abstract interface DirectoryStream.Filter<T> {
     method public abstract boolean accept(T) throws java.io.IOException;
   }
 
@@ -54486,7 +54488,7 @@
   public abstract class FileStore {
     ctor protected FileStore();
     method public abstract java.lang.Object getAttribute(java.lang.String) throws java.io.IOException;
-    method public abstract V getFileStoreAttributeView(java.lang.Class<V>);
+    method public abstract <V extends java.nio.file.attribute.FileStoreAttributeView> V getFileStoreAttributeView(java.lang.Class<V>);
     method public abstract long getTotalSpace() throws java.io.IOException;
     method public abstract long getUnallocatedSpace() throws java.io.IOException;
     method public abstract long getUsableSpace() throws java.io.IOException;
@@ -54558,7 +54560,7 @@
     enum_constant public static final java.nio.file.FileVisitResult TERMINATE;
   }
 
-  public abstract interface FileVisitor {
+  public abstract interface FileVisitor<T> {
     method public abstract java.nio.file.FileVisitResult postVisitDirectory(T, java.io.IOException) throws java.io.IOException;
     method public abstract java.nio.file.FileVisitResult preVisitDirectory(T, java.nio.file.attribute.BasicFileAttributes) throws java.io.IOException;
     method public abstract java.nio.file.FileVisitResult visitFile(T, java.nio.file.attribute.BasicFileAttributes) throws java.io.IOException;
@@ -54583,7 +54585,7 @@
     method public static boolean exists(java.nio.file.Path, java.nio.file.LinkOption...);
     method public static java.util.stream.Stream<java.nio.file.Path> find(java.nio.file.Path, int, java.util.function.BiPredicate<java.nio.file.Path, java.nio.file.attribute.BasicFileAttributes>, java.nio.file.FileVisitOption...) throws java.io.IOException;
     method public static java.lang.Object getAttribute(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
+    method public static <V extends java.nio.file.attribute.FileAttributeView> V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
     method public static java.nio.file.FileStore getFileStore(java.nio.file.Path) throws java.io.IOException;
     method public static java.nio.file.attribute.FileTime getLastModifiedTime(java.nio.file.Path, java.nio.file.LinkOption...) throws java.io.IOException;
     method public static java.nio.file.attribute.UserPrincipal getOwner(java.nio.file.Path, java.nio.file.LinkOption...) throws java.io.IOException;
@@ -54616,7 +54618,7 @@
     method public static byte[] readAllBytes(java.nio.file.Path) throws java.io.IOException;
     method public static java.util.List<java.lang.String> readAllLines(java.nio.file.Path, java.nio.charset.Charset) throws java.io.IOException;
     method public static java.util.List<java.lang.String> readAllLines(java.nio.file.Path) throws java.io.IOException;
-    method public static A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
+    method public static <A extends java.nio.file.attribute.BasicFileAttributes> A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
     method public static java.util.Map<java.lang.String, java.lang.Object> readAttributes(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
     method public static java.nio.file.Path readSymbolicLink(java.nio.file.Path) throws java.io.IOException;
     method public static java.nio.file.Path setAttribute(java.nio.file.Path, java.lang.String, java.lang.Object, java.nio.file.LinkOption...) throws java.io.IOException;
@@ -54724,17 +54726,17 @@
     ctor public ReadOnlyFileSystemException();
   }
 
-  public abstract interface SecureDirectoryStream implements java.nio.file.DirectoryStream {
+  public abstract interface SecureDirectoryStream<T> implements java.nio.file.DirectoryStream {
     method public abstract void deleteDirectory(T) throws java.io.IOException;
     method public abstract void deleteFile(T) throws java.io.IOException;
-    method public abstract V getFileAttributeView(java.lang.Class<V>);
-    method public abstract V getFileAttributeView(T, java.lang.Class<V>, java.nio.file.LinkOption...);
+    method public abstract <V extends java.nio.file.attribute.FileAttributeView> V getFileAttributeView(java.lang.Class<V>);
+    method public abstract <V extends java.nio.file.attribute.FileAttributeView> V getFileAttributeView(T, java.lang.Class<V>, java.nio.file.LinkOption...);
     method public abstract void move(T, java.nio.file.SecureDirectoryStream<T>, T) throws java.io.IOException;
     method public abstract java.nio.channels.SeekableByteChannel newByteChannel(T, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
     method public abstract java.nio.file.SecureDirectoryStream<T> newDirectoryStream(T, java.nio.file.LinkOption...) throws java.io.IOException;
   }
 
-  public class SimpleFileVisitor implements java.nio.file.FileVisitor {
+  public class SimpleFileVisitor<T> implements java.nio.file.FileVisitor {
     ctor protected SimpleFileVisitor();
     method public java.nio.file.FileVisitResult postVisitDirectory(T, java.io.IOException) throws java.io.IOException;
     method public java.nio.file.FileVisitResult preVisitDirectory(T, java.nio.file.attribute.BasicFileAttributes) throws java.io.IOException;
@@ -54772,13 +54774,13 @@
     field public static final java.nio.file.WatchEvent.Kind<java.lang.Object> OVERFLOW;
   }
 
-  public abstract interface WatchEvent {
+  public abstract interface WatchEvent<T> {
     method public abstract T context();
     method public abstract int count();
     method public abstract java.nio.file.WatchEvent.Kind<T> kind();
   }
 
-  public static abstract interface WatchEvent.Kind {
+  public static abstract interface WatchEvent.Kind<T> {
     method public abstract java.lang.String name();
     method public abstract java.lang.Class<T> type();
   }
@@ -54914,7 +54916,7 @@
     method public abstract boolean isSystem();
   }
 
-  public abstract interface FileAttribute {
+  public abstract interface FileAttribute<T> {
     method public abstract java.lang.String name();
     method public abstract T value();
   }
@@ -55011,7 +55013,7 @@
     method public void createSymbolicLink(java.nio.file.Path, java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
     method public abstract void delete(java.nio.file.Path) throws java.io.IOException;
     method public boolean deleteIfExists(java.nio.file.Path) throws java.io.IOException;
-    method public abstract V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
+    method public abstract <V extends java.nio.file.attribute.FileAttributeView> V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
     method public abstract java.nio.file.FileStore getFileStore(java.nio.file.Path) throws java.io.IOException;
     method public abstract java.nio.file.FileSystem getFileSystem(java.net.URI);
     method public abstract java.nio.file.Path getPath(java.net.URI);
@@ -55028,7 +55030,7 @@
     method public java.nio.file.FileSystem newFileSystem(java.nio.file.Path, java.util.Map<java.lang.String, ?>) throws java.io.IOException;
     method public java.io.InputStream newInputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
     method public java.io.OutputStream newOutputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public abstract A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
+    method public abstract <A extends java.nio.file.attribute.BasicFileAttributes> A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
     method public abstract java.util.Map<java.lang.String, java.lang.Object> readAttributes(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
     method public java.nio.file.Path readSymbolicLink(java.nio.file.Path) throws java.io.IOException;
     method public abstract void setAttribute(java.nio.file.Path, java.lang.String, java.lang.Object, java.nio.file.LinkOption...) throws java.io.IOException;
@@ -55058,12 +55060,12 @@
 
   public final class AccessController {
     method public static void checkPermission(java.security.Permission) throws java.security.AccessControlException;
-    method public static T doPrivileged(java.security.PrivilegedAction<T>);
-    method public static T doPrivileged(java.security.PrivilegedAction<T>, java.security.AccessControlContext);
-    method public static T doPrivileged(java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
-    method public static T doPrivileged(java.security.PrivilegedExceptionAction<T>, java.security.AccessControlContext) throws java.security.PrivilegedActionException;
-    method public static T doPrivilegedWithCombiner(java.security.PrivilegedAction<T>);
-    method public static T doPrivilegedWithCombiner(java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
+    method public static <T> T doPrivileged(java.security.PrivilegedAction<T>);
+    method public static <T> T doPrivileged(java.security.PrivilegedAction<T>, java.security.AccessControlContext);
+    method public static <T> T doPrivileged(java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
+    method public static <T> T doPrivileged(java.security.PrivilegedExceptionAction<T>, java.security.AccessControlContext) throws java.security.PrivilegedActionException;
+    method public static <T> T doPrivilegedWithCombiner(java.security.PrivilegedAction<T>);
+    method public static <T> T doPrivilegedWithCombiner(java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
     method public static java.security.AccessControlContext getContext();
   }
 
@@ -55102,7 +55104,7 @@
     method public static java.security.AlgorithmParameters getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
     method public static java.security.AlgorithmParameters getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
     method public static java.security.AlgorithmParameters getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
-    method public final T getParameterSpec(java.lang.Class<T>) throws java.security.spec.InvalidParameterSpecException;
+    method public final <T extends java.security.spec.AlgorithmParameterSpec> T getParameterSpec(java.lang.Class<T>) throws java.security.spec.InvalidParameterSpecException;
     method public final java.security.Provider getProvider();
     method public final void init(java.security.spec.AlgorithmParameterSpec) throws java.security.spec.InvalidParameterSpecException;
     method public final void init(byte[]) throws java.io.IOException;
@@ -55114,7 +55116,7 @@
     ctor public AlgorithmParametersSpi();
     method protected abstract byte[] engineGetEncoded() throws java.io.IOException;
     method protected abstract byte[] engineGetEncoded(java.lang.String) throws java.io.IOException;
-    method protected abstract T engineGetParameterSpec(java.lang.Class<T>) throws java.security.spec.InvalidParameterSpecException;
+    method protected abstract <T extends java.security.spec.AlgorithmParameterSpec> T engineGetParameterSpec(java.lang.Class<T>) throws java.security.spec.InvalidParameterSpecException;
     method protected abstract void engineInit(java.security.spec.AlgorithmParameterSpec) throws java.security.spec.InvalidParameterSpecException;
     method protected abstract void engineInit(byte[]) throws java.io.IOException;
     method protected abstract void engineInit(byte[], java.lang.String) throws java.io.IOException;
@@ -55306,7 +55308,7 @@
     method public static java.security.KeyFactory getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
     method public static java.security.KeyFactory getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
     method public static java.security.KeyFactory getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
-    method public final T getKeySpec(java.security.Key, java.lang.Class<T>) throws java.security.spec.InvalidKeySpecException;
+    method public final <T extends java.security.spec.KeySpec> T getKeySpec(java.security.Key, java.lang.Class<T>) throws java.security.spec.InvalidKeySpecException;
     method public final java.security.Provider getProvider();
     method public final java.security.Key translateKey(java.security.Key) throws java.security.InvalidKeyException;
   }
@@ -55315,7 +55317,7 @@
     ctor public KeyFactorySpi();
     method protected abstract java.security.PrivateKey engineGeneratePrivate(java.security.spec.KeySpec) throws java.security.spec.InvalidKeySpecException;
     method protected abstract java.security.PublicKey engineGeneratePublic(java.security.spec.KeySpec) throws java.security.spec.InvalidKeySpecException;
-    method protected abstract T engineGetKeySpec(java.security.Key, java.lang.Class<T>) throws java.security.spec.InvalidKeySpecException;
+    method protected abstract <T extends java.security.spec.KeySpec> T engineGetKeySpec(java.security.Key, java.lang.Class<T>) throws java.security.spec.InvalidKeySpecException;
     method protected abstract java.security.Key engineTranslateKey(java.security.Key) throws java.security.InvalidKeyException;
   }
 
@@ -55603,7 +55605,7 @@
     field public static final long serialVersionUID = 6034044314589513430L; // 0x53bd3b559a12c6d6L
   }
 
-  public abstract interface PrivilegedAction {
+  public abstract interface PrivilegedAction<T> {
     method public abstract T run();
   }
 
@@ -55612,7 +55614,7 @@
     method public java.lang.Exception getException();
   }
 
-  public abstract interface PrivilegedExceptionAction {
+  public abstract interface PrivilegedExceptionAction<T> {
     method public abstract T run() throws java.lang.Exception;
   }
 
@@ -57806,11 +57808,11 @@
     method public abstract void free() throws java.sql.SQLException;
     method public abstract java.io.InputStream getBinaryStream() throws java.sql.SQLException;
     method public abstract java.io.Reader getCharacterStream() throws java.sql.SQLException;
-    method public abstract T getSource(java.lang.Class<T>) throws java.sql.SQLException;
+    method public abstract <T extends javax.xml.transform.Source> T getSource(java.lang.Class<T>) throws java.sql.SQLException;
     method public abstract java.lang.String getString() throws java.sql.SQLException;
     method public abstract java.io.OutputStream setBinaryStream() throws java.sql.SQLException;
     method public abstract java.io.Writer setCharacterStream() throws java.sql.SQLException;
-    method public abstract T setResult(java.lang.Class<T>) throws java.sql.SQLException;
+    method public abstract <T extends javax.xml.transform.Result> T setResult(java.lang.Class<T>) throws java.sql.SQLException;
     method public abstract void setString(java.lang.String) throws java.sql.SQLException;
   }
 
@@ -57934,7 +57936,7 @@
 
   public abstract interface Wrapper {
     method public abstract boolean isWrapperFor(java.lang.Class<?>) throws java.sql.SQLException;
-    method public abstract T unwrap(java.lang.Class<T>) throws java.sql.SQLException;
+    method public abstract <T> T unwrap(java.lang.Class<T>) throws java.sql.SQLException;
   }
 
 }
@@ -58467,7 +58469,7 @@
 
 package java.util {
 
-  public abstract class AbstractCollection implements java.util.Collection {
+  public abstract class AbstractCollection<E> implements java.util.Collection {
     ctor protected AbstractCollection();
     method public boolean add(E);
     method public boolean addAll(java.util.Collection<? extends E>);
@@ -58481,10 +58483,10 @@
     method public boolean retainAll(java.util.Collection<?>);
     method public abstract int size();
     method public java.lang.Object[] toArray();
-    method public T[] toArray(T[]);
+    method public <T> T[] toArray(T[]);
   }
 
-  public abstract class AbstractList extends java.util.AbstractCollection implements java.util.List {
+  public abstract class AbstractList<E> extends java.util.AbstractCollection implements java.util.List {
     ctor protected AbstractList();
     method public void add(int, E);
     method public boolean addAll(int, java.util.Collection<? extends E>);
@@ -58501,7 +58503,7 @@
     field protected transient int modCount;
   }
 
-  public abstract class AbstractMap implements java.util.Map {
+  public abstract class AbstractMap<K, V> implements java.util.Map {
     ctor protected AbstractMap();
     method public void clear();
     method public boolean containsKey(java.lang.Object);
@@ -58517,7 +58519,7 @@
     method public java.util.Collection<V> values();
   }
 
-  public static class AbstractMap.SimpleEntry implements java.util.Map.Entry java.io.Serializable {
+  public static class AbstractMap.SimpleEntry<K, V> implements java.util.Map.Entry java.io.Serializable {
     ctor public AbstractMap.SimpleEntry(K, V);
     ctor public AbstractMap.SimpleEntry(java.util.Map.Entry<? extends K, ? extends V>);
     method public K getKey();
@@ -58525,7 +58527,7 @@
     method public V setValue(V);
   }
 
-  public static class AbstractMap.SimpleImmutableEntry implements java.util.Map.Entry java.io.Serializable {
+  public static class AbstractMap.SimpleImmutableEntry<K, V> implements java.util.Map.Entry java.io.Serializable {
     ctor public AbstractMap.SimpleImmutableEntry(K, V);
     ctor public AbstractMap.SimpleImmutableEntry(java.util.Map.Entry<? extends K, ? extends V>);
     method public K getKey();
@@ -58533,23 +58535,23 @@
     method public V setValue(V);
   }
 
-  public abstract class AbstractQueue extends java.util.AbstractCollection implements java.util.Queue {
+  public abstract class AbstractQueue<E> extends java.util.AbstractCollection implements java.util.Queue {
     ctor protected AbstractQueue();
     method public E element();
     method public E remove();
   }
 
-  public abstract class AbstractSequentialList extends java.util.AbstractList {
+  public abstract class AbstractSequentialList<E> extends java.util.AbstractList {
     ctor protected AbstractSequentialList();
     method public E get(int);
     method public abstract java.util.ListIterator<E> listIterator(int);
   }
 
-  public abstract class AbstractSet extends java.util.AbstractCollection implements java.util.Set {
+  public abstract class AbstractSet<E> extends java.util.AbstractCollection implements java.util.Set {
     ctor protected AbstractSet();
   }
 
-  public class ArrayDeque extends java.util.AbstractCollection implements java.lang.Cloneable java.util.Deque java.io.Serializable {
+  public class ArrayDeque<E> extends java.util.AbstractCollection implements java.lang.Cloneable java.util.Deque java.io.Serializable {
     ctor public ArrayDeque();
     ctor public ArrayDeque(int);
     ctor public ArrayDeque(java.util.Collection<? extends E>);
@@ -58581,7 +58583,7 @@
     method public java.util.Spliterator<E> spliterator();
   }
 
-  public class ArrayList extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
+  public class ArrayList<E> extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
     ctor public ArrayList(int);
     ctor public ArrayList();
     ctor public ArrayList(java.util.Collection<? extends E>);
@@ -58598,7 +58600,7 @@
   }
 
   public class Arrays {
-    method public static java.util.List<T> asList(T...);
+    method public static <T> java.util.List<T> asList(T...);
     method public static int binarySearch(long[], long);
     method public static int binarySearch(long[], int, int, long);
     method public static int binarySearch(int[], int);
@@ -58615,10 +58617,10 @@
     method public static int binarySearch(float[], int, int, float);
     method public static int binarySearch(java.lang.Object[], java.lang.Object);
     method public static int binarySearch(java.lang.Object[], int, int, java.lang.Object);
-    method public static int binarySearch(T[], T, java.util.Comparator<? super T>);
-    method public static int binarySearch(T[], int, int, T, java.util.Comparator<? super T>);
-    method public static T[] copyOf(T[], int);
-    method public static T[] copyOf(U[], int, java.lang.Class<? extends T[]>);
+    method public static <T> int binarySearch(T[], T, java.util.Comparator<? super T>);
+    method public static <T> int binarySearch(T[], int, int, T, java.util.Comparator<? super T>);
+    method public static <T> T[] copyOf(T[], int);
+    method public static <T, U> T[] copyOf(U[], int, java.lang.Class<? extends T[]>);
     method public static byte[] copyOf(byte[], int);
     method public static short[] copyOf(short[], int);
     method public static int[] copyOf(int[], int);
@@ -58627,8 +58629,8 @@
     method public static float[] copyOf(float[], int);
     method public static double[] copyOf(double[], int);
     method public static boolean[] copyOf(boolean[], int);
-    method public static T[] copyOfRange(T[], int, int);
-    method public static T[] copyOfRange(U[], int, int, java.lang.Class<? extends T[]>);
+    method public static <T> T[] copyOfRange(T[], int, int);
+    method public static <T, U> T[] copyOfRange(U[], int, int, java.lang.Class<? extends T[]>);
     method public static byte[] copyOfRange(byte[], int, int);
     method public static short[] copyOfRange(short[], int, int);
     method public static int[] copyOfRange(int[], int, int);
@@ -58676,15 +58678,15 @@
     method public static int hashCode(float[]);
     method public static int hashCode(double[]);
     method public static int hashCode(java.lang.Object[]);
-    method public static void parallelPrefix(T[], java.util.function.BinaryOperator<T>);
-    method public static void parallelPrefix(T[], int, int, java.util.function.BinaryOperator<T>);
+    method public static <T> void parallelPrefix(T[], java.util.function.BinaryOperator<T>);
+    method public static <T> void parallelPrefix(T[], int, int, java.util.function.BinaryOperator<T>);
     method public static void parallelPrefix(long[], java.util.function.LongBinaryOperator);
     method public static void parallelPrefix(long[], int, int, java.util.function.LongBinaryOperator);
     method public static void parallelPrefix(double[], java.util.function.DoubleBinaryOperator);
     method public static void parallelPrefix(double[], int, int, java.util.function.DoubleBinaryOperator);
     method public static void parallelPrefix(int[], java.util.function.IntBinaryOperator);
     method public static void parallelPrefix(int[], int, int, java.util.function.IntBinaryOperator);
-    method public static void parallelSetAll(T[], java.util.function.IntFunction<? extends T>);
+    method public static <T> void parallelSetAll(T[], java.util.function.IntFunction<? extends T>);
     method public static void parallelSetAll(int[], java.util.function.IntUnaryOperator);
     method public static void parallelSetAll(long[], java.util.function.IntToLongFunction);
     method public static void parallelSetAll(double[], java.util.function.IntToDoubleFunction);
@@ -58702,11 +58704,11 @@
     method public static void parallelSort(float[], int, int);
     method public static void parallelSort(double[]);
     method public static void parallelSort(double[], int, int);
-    method public static void parallelSort(T[]);
-    method public static void parallelSort(T[], int, int);
-    method public static void parallelSort(T[], java.util.Comparator<? super T>);
-    method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>);
-    method public static void setAll(T[], java.util.function.IntFunction<? extends T>);
+    method public static <T extends java.lang.Comparable<? super T>> void parallelSort(T[]);
+    method public static <T extends java.lang.Comparable<? super T>> void parallelSort(T[], int, int);
+    method public static <T> void parallelSort(T[], java.util.Comparator<? super T>);
+    method public static <T> void parallelSort(T[], int, int, java.util.Comparator<? super T>);
+    method public static <T> void setAll(T[], java.util.function.IntFunction<? extends T>);
     method public static void setAll(int[], java.util.function.IntUnaryOperator);
     method public static void setAll(long[], java.util.function.IntToLongFunction);
     method public static void setAll(double[], java.util.function.IntToDoubleFunction);
@@ -58726,18 +58728,18 @@
     method public static void sort(double[], int, int);
     method public static void sort(java.lang.Object[]);
     method public static void sort(java.lang.Object[], int, int);
-    method public static void sort(T[], java.util.Comparator<? super T>);
-    method public static void sort(T[], int, int, java.util.Comparator<? super T>);
-    method public static java.util.Spliterator<T> spliterator(T[]);
-    method public static java.util.Spliterator<T> spliterator(T[], int, int);
+    method public static <T> void sort(T[], java.util.Comparator<? super T>);
+    method public static <T> void sort(T[], int, int, java.util.Comparator<? super T>);
+    method public static <T> java.util.Spliterator<T> spliterator(T[]);
+    method public static <T> java.util.Spliterator<T> spliterator(T[], int, int);
     method public static java.util.Spliterator.OfInt spliterator(int[]);
     method public static java.util.Spliterator.OfInt spliterator(int[], int, int);
     method public static java.util.Spliterator.OfLong spliterator(long[]);
     method public static java.util.Spliterator.OfLong spliterator(long[], int, int);
     method public static java.util.Spliterator.OfDouble spliterator(double[]);
     method public static java.util.Spliterator.OfDouble spliterator(double[], int, int);
-    method public static java.util.stream.Stream<T> stream(T[]);
-    method public static java.util.stream.Stream<T> stream(T[], int, int);
+    method public static <T> java.util.stream.Stream<T> stream(T[]);
+    method public static <T> java.util.stream.Stream<T> stream(T[], int, int);
     method public static java.util.stream.IntStream stream(int[]);
     method public static java.util.stream.IntStream stream(int[], int, int);
     method public static java.util.stream.LongStream stream(long[]);
@@ -58921,7 +58923,7 @@
     field protected long time;
   }
 
-  public abstract interface Collection implements java.lang.Iterable {
+  public abstract interface Collection<E> implements java.lang.Iterable {
     method public abstract boolean add(E);
     method public abstract boolean addAll(java.util.Collection<? extends E>);
     method public abstract void clear();
@@ -58939,86 +58941,86 @@
     method public abstract int size();
     method public default java.util.stream.Stream<E> stream();
     method public abstract java.lang.Object[] toArray();
-    method public abstract T[] toArray(T[]);
+    method public abstract <T> T[] toArray(T[]);
   }
 
   public class Collections {
-    method public static boolean addAll(java.util.Collection<? super T>, T...);
-    method public static java.util.Queue<T> asLifoQueue(java.util.Deque<T>);
-    method public static int binarySearch(java.util.List<? extends java.lang.Comparable<? super T>>, T);
-    method public static int binarySearch(java.util.List<? extends T>, T, java.util.Comparator<? super T>);
-    method public static java.util.Collection<E> checkedCollection(java.util.Collection<E>, java.lang.Class<E>);
-    method public static java.util.List<E> checkedList(java.util.List<E>, java.lang.Class<E>);
-    method public static java.util.Map<K, V> checkedMap(java.util.Map<K, V>, java.lang.Class<K>, java.lang.Class<V>);
-    method public static java.util.Set<E> checkedSet(java.util.Set<E>, java.lang.Class<E>);
-    method public static java.util.SortedMap<K, V> checkedSortedMap(java.util.SortedMap<K, V>, java.lang.Class<K>, java.lang.Class<V>);
-    method public static java.util.SortedSet<E> checkedSortedSet(java.util.SortedSet<E>, java.lang.Class<E>);
-    method public static void copy(java.util.List<? super T>, java.util.List<? extends T>);
+    method public static <T> boolean addAll(java.util.Collection<? super T>, T...);
+    method public static <T> java.util.Queue<T> asLifoQueue(java.util.Deque<T>);
+    method public static <T> int binarySearch(java.util.List<? extends java.lang.Comparable<? super T>>, T);
+    method public static <T> int binarySearch(java.util.List<? extends T>, T, java.util.Comparator<? super T>);
+    method public static <E> java.util.Collection<E> checkedCollection(java.util.Collection<E>, java.lang.Class<E>);
+    method public static <E> java.util.List<E> checkedList(java.util.List<E>, java.lang.Class<E>);
+    method public static <K, V> java.util.Map<K, V> checkedMap(java.util.Map<K, V>, java.lang.Class<K>, java.lang.Class<V>);
+    method public static <E> java.util.Set<E> checkedSet(java.util.Set<E>, java.lang.Class<E>);
+    method public static <K, V> java.util.SortedMap<K, V> checkedSortedMap(java.util.SortedMap<K, V>, java.lang.Class<K>, java.lang.Class<V>);
+    method public static <E> java.util.SortedSet<E> checkedSortedSet(java.util.SortedSet<E>, java.lang.Class<E>);
+    method public static <T> void copy(java.util.List<? super T>, java.util.List<? extends T>);
     method public static boolean disjoint(java.util.Collection<?>, java.util.Collection<?>);
-    method public static java.util.Enumeration<T> emptyEnumeration();
-    method public static java.util.Iterator<T> emptyIterator();
-    method public static final java.util.List<T> emptyList();
-    method public static java.util.ListIterator<T> emptyListIterator();
-    method public static final java.util.Map<K, V> emptyMap();
-    method public static final java.util.Set<T> emptySet();
-    method public static java.util.Enumeration<T> enumeration(java.util.Collection<T>);
-    method public static void fill(java.util.List<? super T>, T);
+    method public static <T> java.util.Enumeration<T> emptyEnumeration();
+    method public static <T> java.util.Iterator<T> emptyIterator();
+    method public static final <T> java.util.List<T> emptyList();
+    method public static <T> java.util.ListIterator<T> emptyListIterator();
+    method public static final <K, V> java.util.Map<K, V> emptyMap();
+    method public static final <T> java.util.Set<T> emptySet();
+    method public static <T> java.util.Enumeration<T> enumeration(java.util.Collection<T>);
+    method public static <T> void fill(java.util.List<? super T>, T);
     method public static int frequency(java.util.Collection<?>, java.lang.Object);
     method public static int indexOfSubList(java.util.List<?>, java.util.List<?>);
     method public static int lastIndexOfSubList(java.util.List<?>, java.util.List<?>);
-    method public static java.util.ArrayList<T> list(java.util.Enumeration<T>);
-    method public static T max(java.util.Collection<? extends T>);
-    method public static T max(java.util.Collection<? extends T>, java.util.Comparator<? super T>);
-    method public static T min(java.util.Collection<? extends T>);
-    method public static T min(java.util.Collection<? extends T>, java.util.Comparator<? super T>);
-    method public static java.util.List<T> nCopies(int, T);
-    method public static java.util.Set<E> newSetFromMap(java.util.Map<E, java.lang.Boolean>);
-    method public static boolean replaceAll(java.util.List<T>, T, T);
+    method public static <T> java.util.ArrayList<T> list(java.util.Enumeration<T>);
+    method public static <T extends java.lang.Object & java.lang.Comparable<? super T>> T max(java.util.Collection<? extends T>);
+    method public static <T> T max(java.util.Collection<? extends T>, java.util.Comparator<? super T>);
+    method public static <T extends java.lang.Object & java.lang.Comparable<? super T>> T min(java.util.Collection<? extends T>);
+    method public static <T> T min(java.util.Collection<? extends T>, java.util.Comparator<? super T>);
+    method public static <T> java.util.List<T> nCopies(int, T);
+    method public static <E> java.util.Set<E> newSetFromMap(java.util.Map<E, java.lang.Boolean>);
+    method public static <T> boolean replaceAll(java.util.List<T>, T, T);
     method public static void reverse(java.util.List<?>);
-    method public static java.util.Comparator<T> reverseOrder();
-    method public static java.util.Comparator<T> reverseOrder(java.util.Comparator<T>);
+    method public static <T> java.util.Comparator<T> reverseOrder();
+    method public static <T> java.util.Comparator<T> reverseOrder(java.util.Comparator<T>);
     method public static void rotate(java.util.List<?>, int);
     method public static void shuffle(java.util.List<?>);
     method public static void shuffle(java.util.List<?>, java.util.Random);
-    method public static java.util.Set<E> singleton(E);
-    method public static java.util.List<E> singletonList(E);
-    method public static java.util.Map<K, V> singletonMap(K, V);
-    method public static void sort(java.util.List<T>);
-    method public static void sort(java.util.List<T>, java.util.Comparator<? super T>);
+    method public static <E> java.util.Set<E> singleton(E);
+    method public static <E> java.util.List<E> singletonList(E);
+    method public static <K, V> java.util.Map<K, V> singletonMap(K, V);
+    method public static <T extends java.lang.Comparable<? super T>> void sort(java.util.List<T>);
+    method public static <T> void sort(java.util.List<T>, java.util.Comparator<? super T>);
     method public static void swap(java.util.List<?>, int, int);
-    method public static java.util.Collection<T> synchronizedCollection(java.util.Collection<T>);
-    method public static java.util.List<T> synchronizedList(java.util.List<T>);
-    method public static java.util.Map<K, V> synchronizedMap(java.util.Map<K, V>);
-    method public static java.util.Set<T> synchronizedSet(java.util.Set<T>);
-    method public static java.util.SortedMap<K, V> synchronizedSortedMap(java.util.SortedMap<K, V>);
-    method public static java.util.SortedSet<T> synchronizedSortedSet(java.util.SortedSet<T>);
-    method public static java.util.Collection<T> unmodifiableCollection(java.util.Collection<? extends T>);
-    method public static java.util.List<T> unmodifiableList(java.util.List<? extends T>);
-    method public static java.util.Map<K, V> unmodifiableMap(java.util.Map<? extends K, ? extends V>);
-    method public static java.util.Set<T> unmodifiableSet(java.util.Set<? extends T>);
-    method public static java.util.SortedMap<K, V> unmodifiableSortedMap(java.util.SortedMap<K, ? extends V>);
-    method public static java.util.SortedSet<T> unmodifiableSortedSet(java.util.SortedSet<T>);
+    method public static <T> java.util.Collection<T> synchronizedCollection(java.util.Collection<T>);
+    method public static <T> java.util.List<T> synchronizedList(java.util.List<T>);
+    method public static <K, V> java.util.Map<K, V> synchronizedMap(java.util.Map<K, V>);
+    method public static <T> java.util.Set<T> synchronizedSet(java.util.Set<T>);
+    method public static <K, V> java.util.SortedMap<K, V> synchronizedSortedMap(java.util.SortedMap<K, V>);
+    method public static <T> java.util.SortedSet<T> synchronizedSortedSet(java.util.SortedSet<T>);
+    method public static <T> java.util.Collection<T> unmodifiableCollection(java.util.Collection<? extends T>);
+    method public static <T> java.util.List<T> unmodifiableList(java.util.List<? extends T>);
+    method public static <K, V> java.util.Map<K, V> unmodifiableMap(java.util.Map<? extends K, ? extends V>);
+    method public static <T> java.util.Set<T> unmodifiableSet(java.util.Set<? extends T>);
+    method public static <K, V> java.util.SortedMap<K, V> unmodifiableSortedMap(java.util.SortedMap<K, ? extends V>);
+    method public static <T> java.util.SortedSet<T> unmodifiableSortedSet(java.util.SortedSet<T>);
     field public static final java.util.List EMPTY_LIST;
     field public static final java.util.Map EMPTY_MAP;
     field public static final java.util.Set EMPTY_SET;
   }
 
-  public abstract interface Comparator {
+  public abstract interface Comparator<T> {
     method public abstract int compare(T, T);
-    method public static java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
-    method public static java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>);
-    method public static java.util.Comparator<T> comparingDouble(java.util.function.ToDoubleFunction<? super T>);
-    method public static java.util.Comparator<T> comparingInt(java.util.function.ToIntFunction<? super T>);
-    method public static java.util.Comparator<T> comparingLong(java.util.function.ToLongFunction<? super T>);
+    method public static <T, U> java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
+    method public static <T, U extends java.lang.Comparable<? super U>> java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>);
+    method public static <T> java.util.Comparator<T> comparingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static <T> java.util.Comparator<T> comparingInt(java.util.function.ToIntFunction<? super T>);
+    method public static <T> java.util.Comparator<T> comparingLong(java.util.function.ToLongFunction<? super T>);
     method public abstract boolean equals(java.lang.Object);
-    method public static java.util.Comparator<T> naturalOrder();
-    method public static java.util.Comparator<T> nullsFirst(java.util.Comparator<? super T>);
-    method public static java.util.Comparator<T> nullsLast(java.util.Comparator<? super T>);
-    method public static java.util.Comparator<T> reverseOrder();
+    method public static <T extends java.lang.Comparable<? super T>> java.util.Comparator<T> naturalOrder();
+    method public static <T> java.util.Comparator<T> nullsFirst(java.util.Comparator<? super T>);
+    method public static <T> java.util.Comparator<T> nullsLast(java.util.Comparator<? super T>);
+    method public static <T extends java.lang.Comparable<? super T>> java.util.Comparator<T> reverseOrder();
     method public default java.util.Comparator<T> reversed();
     method public default java.util.Comparator<T> thenComparing(java.util.Comparator<? super T>);
-    method public default java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
-    method public default java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>);
+    method public default <U> java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
+    method public default <U extends java.lang.Comparable<? super U>> java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>);
     method public default java.util.Comparator<T> thenComparingDouble(java.util.function.ToDoubleFunction<? super T>);
     method public default java.util.Comparator<T> thenComparingInt(java.util.function.ToIntFunction<? super T>);
     method public default java.util.Comparator<T> thenComparingLong(java.util.function.ToLongFunction<? super T>);
@@ -59077,7 +59079,7 @@
     method public deprecated java.lang.String toLocaleString();
   }
 
-  public abstract interface Deque implements java.util.Queue {
+  public abstract interface Deque<E> implements java.util.Queue {
     method public abstract boolean add(E);
     method public abstract void addFirst(E);
     method public abstract void addLast(E);
@@ -59107,7 +59109,7 @@
     method public abstract int size();
   }
 
-  public abstract class Dictionary {
+  public abstract class Dictionary<K, V> {
     ctor public Dictionary();
     method public abstract java.util.Enumeration<V> elements();
     method public abstract V get(java.lang.Object);
@@ -59138,7 +59140,7 @@
     ctor public EmptyStackException();
   }
 
-  public class EnumMap extends java.util.AbstractMap implements java.lang.Cloneable java.io.Serializable {
+  public class EnumMap<K extends java.lang.Enum<K>, V> extends java.util.AbstractMap implements java.lang.Cloneable java.io.Serializable {
     ctor public EnumMap(java.lang.Class<K>);
     ctor public EnumMap(java.util.EnumMap<K, ? extends V>);
     ctor public EnumMap(java.util.Map<K, ? extends V>);
@@ -59146,23 +59148,23 @@
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
   }
 
-  public abstract class EnumSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable {
-    method public static java.util.EnumSet<E> allOf(java.lang.Class<E>);
+  public abstract class EnumSet<E extends java.lang.Enum<E>> extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable {
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> allOf(java.lang.Class<E>);
     method public java.util.EnumSet<E> clone();
-    method public static java.util.EnumSet<E> complementOf(java.util.EnumSet<E>);
-    method public static java.util.EnumSet<E> copyOf(java.util.EnumSet<E>);
-    method public static java.util.EnumSet<E> copyOf(java.util.Collection<E>);
-    method public static java.util.EnumSet<E> noneOf(java.lang.Class<E>);
-    method public static java.util.EnumSet<E> of(E);
-    method public static java.util.EnumSet<E> of(E, E);
-    method public static java.util.EnumSet<E> of(E, E, E);
-    method public static java.util.EnumSet<E> of(E, E, E, E);
-    method public static java.util.EnumSet<E> of(E, E, E, E, E);
-    method public static java.util.EnumSet<E> of(E, E...);
-    method public static java.util.EnumSet<E> range(E, E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> complementOf(java.util.EnumSet<E>);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> copyOf(java.util.EnumSet<E>);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> copyOf(java.util.Collection<E>);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> noneOf(java.lang.Class<E>);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E, E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E, E, E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E, E, E, E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E, E, E, E, E);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> of(E, E...);
+    method public static <E extends java.lang.Enum<E>> java.util.EnumSet<E> range(E, E);
   }
 
-  public abstract interface Enumeration {
+  public abstract interface Enumeration<E> {
     method public abstract boolean hasMoreElements();
     method public abstract E nextElement();
   }
@@ -59170,7 +59172,7 @@
   public abstract interface EventListener {
   }
 
-  public abstract class EventListenerProxy implements java.util.EventListener {
+  public abstract class EventListenerProxy<T extends java.util.EventListener> implements java.util.EventListener {
     ctor public EventListenerProxy(T);
     method public T getListener();
   }
@@ -59256,7 +59258,7 @@
     field public static final int BC = 0; // 0x0
   }
 
-  public class HashMap extends java.util.AbstractMap implements java.lang.Cloneable java.util.Map java.io.Serializable {
+  public class HashMap<K, V> extends java.util.AbstractMap implements java.lang.Cloneable java.util.Map java.io.Serializable {
     ctor public HashMap(int, float);
     ctor public HashMap(int);
     ctor public HashMap();
@@ -59276,7 +59278,7 @@
     method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
   }
 
-  public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
+  public class HashSet<E> extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
     ctor public HashSet();
     ctor public HashSet(java.util.Collection<? extends E>);
     ctor public HashSet(int, float);
@@ -59287,7 +59289,7 @@
     method public java.util.Spliterator<E> spliterator();
   }
 
-  public class Hashtable extends java.util.Dictionary implements java.lang.Cloneable java.util.Map java.io.Serializable {
+  public class Hashtable<K, V> extends java.util.Dictionary implements java.lang.Cloneable java.util.Map java.io.Serializable {
     ctor public Hashtable(int, float);
     ctor public Hashtable(int);
     ctor public Hashtable();
@@ -59322,7 +59324,7 @@
     method public java.util.Collection<V> values();
   }
 
-  public class IdentityHashMap extends java.util.AbstractMap implements java.lang.Cloneable java.util.Map java.io.Serializable {
+  public class IdentityHashMap<K, V> extends java.util.AbstractMap implements java.lang.Cloneable java.util.Map java.io.Serializable {
     ctor public IdentityHashMap();
     ctor public IdentityHashMap(int);
     ctor public IdentityHashMap(java.util.Map<? extends K, ? extends V>);
@@ -59389,14 +59391,14 @@
     ctor public InvalidPropertiesFormatException(java.lang.String);
   }
 
-  public abstract interface Iterator {
+  public abstract interface Iterator<E> {
     method public default void forEachRemaining(java.util.function.Consumer<? super E>);
     method public abstract boolean hasNext();
     method public abstract E next();
     method public default void remove();
   }
 
-  public class LinkedHashMap extends java.util.HashMap implements java.util.Map {
+  public class LinkedHashMap<K, V> extends java.util.HashMap implements java.util.Map {
     ctor public LinkedHashMap(int, float);
     ctor public LinkedHashMap(int);
     ctor public LinkedHashMap();
@@ -59405,14 +59407,14 @@
     method protected boolean removeEldestEntry(java.util.Map.Entry<K, V>);
   }
 
-  public class LinkedHashSet extends java.util.HashSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
+  public class LinkedHashSet<E> extends java.util.HashSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
     ctor public LinkedHashSet(int, float);
     ctor public LinkedHashSet(int);
     ctor public LinkedHashSet();
     ctor public LinkedHashSet(java.util.Collection<? extends E>);
   }
 
-  public class LinkedList extends java.util.AbstractSequentialList implements java.lang.Cloneable java.util.Deque java.util.List java.io.Serializable {
+  public class LinkedList<E> extends java.util.AbstractSequentialList implements java.lang.Cloneable java.util.Deque java.util.List java.io.Serializable {
     ctor public LinkedList();
     ctor public LinkedList(java.util.Collection<? extends E>);
     method public void addFirst(E);
@@ -59443,7 +59445,7 @@
     method public java.util.Spliterator<E> spliterator();
   }
 
-  public abstract interface List implements java.util.Collection {
+  public abstract interface List<E> implements java.util.Collection {
     method public abstract boolean add(E);
     method public abstract void add(int, E);
     method public abstract boolean addAll(java.util.Collection<? extends E>);
@@ -59470,10 +59472,10 @@
     method public default void sort(java.util.Comparator<? super E>);
     method public abstract java.util.List<E> subList(int, int);
     method public abstract java.lang.Object[] toArray();
-    method public abstract T[] toArray(T[]);
+    method public abstract <T> T[] toArray(T[]);
   }
 
-  public abstract interface ListIterator implements java.util.Iterator {
+  public abstract interface ListIterator<E> implements java.util.Iterator {
     method public abstract void add(E);
     method public abstract boolean hasNext();
     method public abstract boolean hasPrevious();
@@ -59590,7 +59592,7 @@
     method public final long getSum();
   }
 
-  public abstract interface Map {
+  public abstract interface Map<K, V> {
     method public abstract void clear();
     method public default V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public default V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
@@ -59618,11 +59620,11 @@
     method public abstract java.util.Collection<V> values();
   }
 
-  public static abstract interface Map.Entry {
-    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey();
-    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>);
-    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue();
-    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(java.util.Comparator<? super V>);
+  public static abstract interface Map.Entry<K, V> {
+    method public static <K extends java.lang.Comparable<? super K>, V> java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey();
+    method public static <K, V> java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>);
+    method public static <K, V extends java.lang.Comparable<? super V>> java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue();
+    method public static <K, V> java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(java.util.Comparator<? super V>);
     method public abstract boolean equals(java.lang.Object);
     method public abstract K getKey();
     method public abstract V getValue();
@@ -59646,7 +59648,7 @@
     method public java.lang.String getKey();
   }
 
-  public abstract interface NavigableMap implements java.util.SortedMap {
+  public abstract interface NavigableMap<K, V> implements java.util.SortedMap {
     method public abstract java.util.Map.Entry<K, V> ceilingEntry(K);
     method public abstract K ceilingKey(K);
     method public abstract java.util.NavigableSet<K> descendingKeySet();
@@ -59670,7 +59672,7 @@
     method public abstract java.util.SortedMap<K, V> tailMap(K);
   }
 
-  public abstract interface NavigableSet implements java.util.SortedSet {
+  public abstract interface NavigableSet<E> implements java.util.SortedSet {
     method public abstract E ceiling(E);
     method public abstract java.util.Iterator<E> descendingIterator();
     method public abstract java.util.NavigableSet<E> descendingSet();
@@ -59694,16 +59696,16 @@
   }
 
   public final class Objects {
-    method public static int compare(T, T, java.util.Comparator<? super T>);
+    method public static <T> int compare(T, T, java.util.Comparator<? super T>);
     method public static boolean deepEquals(java.lang.Object, java.lang.Object);
     method public static boolean equals(java.lang.Object, java.lang.Object);
     method public static int hash(java.lang.Object...);
     method public static int hashCode(java.lang.Object);
     method public static boolean isNull(java.lang.Object);
     method public static boolean nonNull(java.lang.Object);
-    method public static T requireNonNull(T);
-    method public static T requireNonNull(T, java.lang.String);
-    method public static T requireNonNull(T, java.util.function.Supplier<java.lang.String>);
+    method public static <T> T requireNonNull(T);
+    method public static <T> T requireNonNull(T, java.lang.String);
+    method public static <T> T requireNonNull(T, java.util.function.Supplier<java.lang.String>);
     method public static java.lang.String toString(java.lang.Object);
     method public static java.lang.String toString(java.lang.Object, java.lang.String);
   }
@@ -59725,19 +59727,19 @@
     method public abstract void update(java.util.Observable, java.lang.Object);
   }
 
-  public final class Optional {
-    method public static java.util.Optional<T> empty();
+  public final class Optional<T> {
+    method public static <T> java.util.Optional<T> empty();
     method public java.util.Optional<T> filter(java.util.function.Predicate<? super T>);
-    method public java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
+    method public <U> java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
     method public T get();
     method public void ifPresent(java.util.function.Consumer<? super T>);
     method public boolean isPresent();
-    method public java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
-    method public static java.util.Optional<T> of(T);
-    method public static java.util.Optional<T> ofNullable(T);
+    method public <U> java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
+    method public static <T> java.util.Optional<T> of(T);
+    method public static <T> java.util.Optional<T> ofNullable(T);
     method public T orElse(T);
     method public T orElseGet(java.util.function.Supplier<? extends T>);
-    method public T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
+    method public <X extends java.lang.Throwable> T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
   }
 
   public final class OptionalDouble {
@@ -59748,7 +59750,7 @@
     method public static java.util.OptionalDouble of(double);
     method public double orElse(double);
     method public double orElseGet(java.util.function.DoubleSupplier);
-    method public double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+    method public <X extends java.lang.Throwable> double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
   }
 
   public final class OptionalInt {
@@ -59759,7 +59761,7 @@
     method public static java.util.OptionalInt of(int);
     method public int orElse(int);
     method public int orElseGet(java.util.function.IntSupplier);
-    method public int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+    method public <X extends java.lang.Throwable> int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
   }
 
   public final class OptionalLong {
@@ -59770,10 +59772,10 @@
     method public static java.util.OptionalLong of(long);
     method public long orElse(long);
     method public long orElseGet(java.util.function.LongSupplier);
-    method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+    method public <X extends java.lang.Throwable> long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
   }
 
-  public abstract interface PrimitiveIterator implements java.util.Iterator {
+  public abstract interface PrimitiveIterator<T, T_CONS> implements java.util.Iterator {
     method public abstract void forEachRemaining(T_CONS);
   }
 
@@ -59798,7 +59800,7 @@
     method public abstract long nextLong();
   }
 
-  public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
+  public class PriorityQueue<E> extends java.util.AbstractQueue implements java.io.Serializable {
     ctor public PriorityQueue();
     ctor public PriorityQueue(int);
     ctor public PriorityQueue(java.util.Comparator<? super E>);
@@ -59847,7 +59849,7 @@
     method public java.lang.Object handleGetObject(java.lang.String);
   }
 
-  public abstract interface Queue implements java.util.Collection {
+  public abstract interface Queue<E> implements java.util.Collection {
     method public abstract boolean add(E);
     method public abstract E element();
     method public abstract boolean offer(E);
@@ -59891,6 +59893,7 @@
     method public static final void clearCache();
     method public static final void clearCache(java.lang.ClassLoader);
     method public boolean containsKey(java.lang.String);
+    method public java.lang.String getBaseBundleName();
     method public static final java.util.ResourceBundle getBundle(java.lang.String);
     method public static final java.util.ResourceBundle getBundle(java.lang.String, java.util.ResourceBundle.Control);
     method public static final java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale);
@@ -59999,15 +60002,15 @@
     ctor public ServiceConfigurationError(java.lang.String, java.lang.Throwable);
   }
 
-  public final class ServiceLoader implements java.lang.Iterable {
+  public final class ServiceLoader<S> implements java.lang.Iterable {
     method public java.util.Iterator<S> iterator();
-    method public static java.util.ServiceLoader<S> load(java.lang.Class<S>, java.lang.ClassLoader);
-    method public static java.util.ServiceLoader<S> load(java.lang.Class<S>);
-    method public static java.util.ServiceLoader<S> loadInstalled(java.lang.Class<S>);
+    method public static <S> java.util.ServiceLoader<S> load(java.lang.Class<S>, java.lang.ClassLoader);
+    method public static <S> java.util.ServiceLoader<S> load(java.lang.Class<S>);
+    method public static <S> java.util.ServiceLoader<S> loadInstalled(java.lang.Class<S>);
     method public void reload();
   }
 
-  public abstract interface Set implements java.util.Collection {
+  public abstract interface Set<E> implements java.util.Collection {
     method public abstract boolean add(E);
     method public abstract boolean addAll(java.util.Collection<? extends E>);
     method public abstract void clear();
@@ -60022,7 +60025,7 @@
     method public abstract boolean retainAll(java.util.Collection<?>);
     method public abstract int size();
     method public abstract java.lang.Object[] toArray();
-    method public abstract T[] toArray(T[]);
+    method public abstract <T> T[] toArray(T[]);
   }
 
   public class SimpleTimeZone extends java.util.TimeZone {
@@ -60048,7 +60051,7 @@
     field public static final int WALL_TIME = 0; // 0x0
   }
 
-  public abstract interface SortedMap implements java.util.Map {
+  public abstract interface SortedMap<K, V> implements java.util.Map {
     method public abstract java.util.Comparator<? super K> comparator();
     method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public abstract K firstKey();
@@ -60060,7 +60063,7 @@
     method public abstract java.util.Collection<V> values();
   }
 
-  public abstract interface SortedSet implements java.util.Set {
+  public abstract interface SortedSet<E> implements java.util.Set {
     method public abstract java.util.Comparator<? super E> comparator();
     method public abstract E first();
     method public abstract java.util.SortedSet<E> headSet(E);
@@ -60069,7 +60072,7 @@
     method public abstract java.util.SortedSet<E> tailSet(E);
   }
 
-  public abstract interface Spliterator {
+  public abstract interface Spliterator<T> {
     method public abstract int characteristics();
     method public abstract long estimateSize();
     method public default void forEachRemaining(java.util.function.Consumer<? super T>);
@@ -60112,7 +60115,7 @@
     method public abstract java.util.Spliterator.OfLong trySplit();
   }
 
-  public static abstract interface Spliterator.OfPrimitive implements java.util.Spliterator {
+  public static abstract interface Spliterator.OfPrimitive<T, T_CONS, T_SPLITR extends java.util.Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>> implements java.util.Spliterator {
     method public default void forEachRemaining(T_CONS);
     method public abstract boolean tryAdvance(T_CONS);
     method public abstract T_SPLITR trySplit();
@@ -60122,25 +60125,25 @@
     method public static java.util.Spliterator.OfDouble emptyDoubleSpliterator();
     method public static java.util.Spliterator.OfInt emptyIntSpliterator();
     method public static java.util.Spliterator.OfLong emptyLongSpliterator();
-    method public static java.util.Spliterator<T> emptySpliterator();
-    method public static java.util.Iterator<T> iterator(java.util.Spliterator<? extends T>);
+    method public static <T> java.util.Spliterator<T> emptySpliterator();
+    method public static <T> java.util.Iterator<T> iterator(java.util.Spliterator<? extends T>);
     method public static java.util.PrimitiveIterator.OfInt iterator(java.util.Spliterator.OfInt);
     method public static java.util.PrimitiveIterator.OfLong iterator(java.util.Spliterator.OfLong);
     method public static java.util.PrimitiveIterator.OfDouble iterator(java.util.Spliterator.OfDouble);
-    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int);
-    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int, int, int);
+    method public static <T> java.util.Spliterator<T> spliterator(java.lang.Object[], int);
+    method public static <T> java.util.Spliterator<T> spliterator(java.lang.Object[], int, int, int);
     method public static java.util.Spliterator.OfInt spliterator(int[], int);
     method public static java.util.Spliterator.OfInt spliterator(int[], int, int, int);
     method public static java.util.Spliterator.OfLong spliterator(long[], int);
     method public static java.util.Spliterator.OfLong spliterator(long[], int, int, int);
     method public static java.util.Spliterator.OfDouble spliterator(double[], int);
     method public static java.util.Spliterator.OfDouble spliterator(double[], int, int, int);
-    method public static java.util.Spliterator<T> spliterator(java.util.Collection<? extends T>, int);
-    method public static java.util.Spliterator<T> spliterator(java.util.Iterator<? extends T>, long, int);
+    method public static <T> java.util.Spliterator<T> spliterator(java.util.Collection<? extends T>, int);
+    method public static <T> java.util.Spliterator<T> spliterator(java.util.Iterator<? extends T>, long, int);
     method public static java.util.Spliterator.OfInt spliterator(java.util.PrimitiveIterator.OfInt, long, int);
     method public static java.util.Spliterator.OfLong spliterator(java.util.PrimitiveIterator.OfLong, long, int);
     method public static java.util.Spliterator.OfDouble spliterator(java.util.PrimitiveIterator.OfDouble, long, int);
-    method public static java.util.Spliterator<T> spliteratorUnknownSize(java.util.Iterator<? extends T>, int);
+    method public static <T> java.util.Spliterator<T> spliteratorUnknownSize(java.util.Iterator<? extends T>, int);
     method public static java.util.Spliterator.OfInt spliteratorUnknownSize(java.util.PrimitiveIterator.OfInt, int);
     method public static java.util.Spliterator.OfLong spliteratorUnknownSize(java.util.PrimitiveIterator.OfLong, int);
     method public static java.util.Spliterator.OfDouble spliteratorUnknownSize(java.util.PrimitiveIterator.OfDouble, int);
@@ -60167,7 +60170,7 @@
     method public java.util.Spliterator.OfLong trySplit();
   }
 
-  public static abstract class Spliterators.AbstractSpliterator implements java.util.Spliterator {
+  public static abstract class Spliterators.AbstractSpliterator<T> implements java.util.Spliterator {
     ctor protected Spliterators.AbstractSpliterator(long, int);
     method public int characteristics();
     method public long estimateSize();
@@ -60202,7 +60205,7 @@
     method public java.util.SplittableRandom split();
   }
 
-  public class Stack extends java.util.Vector {
+  public class Stack<E> extends java.util.Vector {
     ctor public Stack();
     method public boolean empty();
     method public synchronized E peek();
@@ -60286,7 +60289,7 @@
     ctor public TooManyListenersException(java.lang.String);
   }
 
-  public class TreeMap extends java.util.AbstractMap implements java.lang.Cloneable java.util.NavigableMap java.io.Serializable {
+  public class TreeMap<K, V> extends java.util.AbstractMap implements java.lang.Cloneable java.util.NavigableMap java.io.Serializable {
     ctor public TreeMap();
     ctor public TreeMap(java.util.Comparator<? super K>);
     ctor public TreeMap(java.util.Map<? extends K, ? extends V>);
@@ -60323,7 +60326,7 @@
     method public java.util.SortedMap<K, V> tailMap(K);
   }
 
-  public class TreeSet extends java.util.AbstractSet implements java.lang.Cloneable java.util.NavigableSet java.io.Serializable {
+  public class TreeSet<E> extends java.util.AbstractSet implements java.lang.Cloneable java.util.NavigableSet java.io.Serializable {
     ctor public TreeSet();
     ctor public TreeSet(java.util.Comparator<? super E>);
     ctor public TreeSet(java.util.Collection<? extends E>);
@@ -60376,7 +60379,7 @@
     method public java.lang.String getFlags();
   }
 
-  public class Vector extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
+  public class Vector<E> extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
     ctor public Vector(int, int);
     ctor public Vector(int);
     ctor public Vector();
@@ -60411,7 +60414,7 @@
     field protected java.lang.Object[] elementData;
   }
 
-  public class WeakHashMap extends java.util.AbstractMap implements java.util.Map {
+  public class WeakHashMap<K, V> extends java.util.AbstractMap implements java.util.Map {
     ctor public WeakHashMap(int, float);
     ctor public WeakHashMap(int);
     ctor public WeakHashMap();
@@ -60427,18 +60430,18 @@
 
   public abstract class AbstractExecutorService implements java.util.concurrent.ExecutorService {
     ctor public AbstractExecutorService();
-    method public java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.lang.InterruptedException;
-    method public java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
-    method public T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
-    method public T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
-    method protected java.util.concurrent.RunnableFuture<T> newTaskFor(java.lang.Runnable, T);
-    method protected java.util.concurrent.RunnableFuture<T> newTaskFor(java.util.concurrent.Callable<T>);
+    method public <T> java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.lang.InterruptedException;
+    method public <T> java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public <T> T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public <T> T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method protected <T> java.util.concurrent.RunnableFuture<T> newTaskFor(java.lang.Runnable, T);
+    method protected <T> java.util.concurrent.RunnableFuture<T> newTaskFor(java.util.concurrent.Callable<T>);
     method public java.util.concurrent.Future<?> submit(java.lang.Runnable);
-    method public java.util.concurrent.Future<T> submit(java.lang.Runnable, T);
-    method public java.util.concurrent.Future<T> submit(java.util.concurrent.Callable<T>);
+    method public <T> java.util.concurrent.Future<T> submit(java.lang.Runnable, T);
+    method public <T> java.util.concurrent.Future<T> submit(java.util.concurrent.Callable<T>);
   }
 
-  public class ArrayBlockingQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
+  public class ArrayBlockingQueue<E> extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
     ctor public ArrayBlockingQueue(int);
     ctor public ArrayBlockingQueue(int, boolean);
     ctor public ArrayBlockingQueue(int, boolean, java.util.Collection<? extends E>);
@@ -60457,7 +60460,7 @@
     method public E take() throws java.lang.InterruptedException;
   }
 
-  public abstract interface BlockingDeque implements java.util.concurrent.BlockingQueue java.util.Deque {
+  public abstract interface BlockingDeque<E> implements java.util.concurrent.BlockingQueue java.util.Deque {
     method public abstract boolean add(E);
     method public abstract void addFirst(E);
     method public abstract void addLast(E);
@@ -60489,7 +60492,7 @@
     method public abstract E takeLast() throws java.lang.InterruptedException;
   }
 
-  public abstract interface BlockingQueue implements java.util.Queue {
+  public abstract interface BlockingQueue<E> implements java.util.Queue {
     method public abstract boolean add(E);
     method public abstract boolean contains(java.lang.Object);
     method public abstract int drainTo(java.util.Collection<? super E>);
@@ -60508,7 +60511,7 @@
     ctor public BrokenBarrierException(java.lang.String);
   }
 
-  public abstract interface Callable {
+  public abstract interface Callable<V> {
     method public abstract V call() throws java.lang.Exception;
   }
 
@@ -60517,28 +60520,28 @@
     ctor public CancellationException(java.lang.String);
   }
 
-  public class CompletableFuture implements java.util.concurrent.CompletionStage java.util.concurrent.Future {
+  public class CompletableFuture<T> implements java.util.concurrent.CompletionStage java.util.concurrent.Future {
     ctor public CompletableFuture();
     method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
     method public static java.util.concurrent.CompletableFuture<java.lang.Void> allOf(java.util.concurrent.CompletableFuture<?>...);
     method public static java.util.concurrent.CompletableFuture<java.lang.Object> anyOf(java.util.concurrent.CompletableFuture<?>...);
-    method public java.util.concurrent.CompletableFuture<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
-    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
-    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public <U> java.util.concurrent.CompletableFuture<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
     method public boolean cancel(boolean);
     method public boolean complete(T);
     method public boolean completeExceptionally(java.lang.Throwable);
-    method public static java.util.concurrent.CompletableFuture<U> completedFuture(U);
+    method public static <U> java.util.concurrent.CompletableFuture<U> completedFuture(U);
     method public java.util.concurrent.CompletableFuture<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
     method public T get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
     method public T get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
     method public T getNow(T);
     method public int getNumberOfDependents();
-    method public java.util.concurrent.CompletableFuture<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
-    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
-    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public <U> java.util.concurrent.CompletableFuture<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
     method public boolean isCancelled();
     method public boolean isCompletedExceptionally();
     method public boolean isDone();
@@ -60553,23 +60556,23 @@
     method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
     method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable);
     method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable, java.util.concurrent.Executor);
-    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>);
-    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>, java.util.concurrent.Executor);
+    method public static <U> java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>);
+    method public static <U> java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>, java.util.concurrent.Executor);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
-    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
-    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
-    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
-    method public java.util.concurrent.CompletableFuture<U> thenApply(java.util.function.Function<? super T, ? extends U>);
-    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
-    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
-    method public java.util.concurrent.CompletableFuture<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
-    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
-    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
-    method public java.util.concurrent.CompletableFuture<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
-    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
-    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public <U> java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public <U> java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public <U> java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public <U, V> java.util.concurrent.CompletableFuture<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public <U, V> java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public <U, V> java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public <U> java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRun(java.lang.Runnable);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable);
     method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
@@ -60589,7 +60592,7 @@
     ctor public CompletionException(java.lang.Throwable);
   }
 
-  public abstract interface CompletionService {
+  public abstract interface CompletionService<V> {
     method public abstract java.util.concurrent.Future<V> poll();
     method public abstract java.util.concurrent.Future<V> poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
     method public abstract java.util.concurrent.Future<V> submit(java.util.concurrent.Callable<V>);
@@ -60597,17 +60600,17 @@
     method public abstract java.util.concurrent.Future<V> take() throws java.lang.InterruptedException;
   }
 
-  public abstract interface CompletionStage {
+  public abstract interface CompletionStage<T> {
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
-    method public abstract java.util.concurrent.CompletionStage<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
-    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
-    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
     method public abstract java.util.concurrent.CompletionStage<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
-    method public abstract java.util.concurrent.CompletionStage<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
-    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
-    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
@@ -60617,18 +60620,18 @@
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
-    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
-    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
-    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
-    method public abstract java.util.concurrent.CompletionStage<U> thenApply(java.util.function.Function<? super T, ? extends U>);
-    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
-    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
-    method public abstract java.util.concurrent.CompletionStage<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
-    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
-    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
-    method public abstract java.util.concurrent.CompletionStage<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
-    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
-    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public abstract <U> java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public abstract <U, V> java.util.concurrent.CompletionStage<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract <U, V> java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract <U, V> java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract <U> java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRun(java.lang.Runnable);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable);
     method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
@@ -60638,7 +60641,7 @@
     method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor);
   }
 
-  public class ConcurrentHashMap extends java.util.AbstractMap implements java.util.concurrent.ConcurrentMap java.io.Serializable {
+  public class ConcurrentHashMap<K, V> extends java.util.AbstractMap implements java.util.concurrent.ConcurrentMap java.io.Serializable {
     ctor public ConcurrentHashMap();
     ctor public ConcurrentHashMap(int);
     ctor public ConcurrentHashMap(java.util.Map<? extends K, ? extends V>);
@@ -60652,29 +60655,29 @@
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public void forEach(long, java.util.function.BiConsumer<? super K, ? super V>);
-    method public void forEach(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public <U> void forEach(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.Consumer<? super U>);
     method public void forEachEntry(long, java.util.function.Consumer<? super java.util.Map.Entry<K, V>>);
-    method public void forEachEntry(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.Consumer<? super U>);
+    method public <U> void forEachEntry(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.Consumer<? super U>);
     method public void forEachKey(long, java.util.function.Consumer<? super K>);
-    method public void forEachKey(long, java.util.function.Function<? super K, ? extends U>, java.util.function.Consumer<? super U>);
+    method public <U> void forEachKey(long, java.util.function.Function<? super K, ? extends U>, java.util.function.Consumer<? super U>);
     method public void forEachValue(long, java.util.function.Consumer<? super V>);
-    method public void forEachValue(long, java.util.function.Function<? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public <U> void forEachValue(long, java.util.function.Function<? super V, ? extends U>, java.util.function.Consumer<? super U>);
     method public V getOrDefault(java.lang.Object, V);
     method public java.util.concurrent.ConcurrentHashMap.KeySetView<K, V> keySet(V);
     method public java.util.Enumeration<K> keys();
     method public long mappingCount();
     method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
-    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet();
-    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(int);
+    method public static <K> java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet();
+    method public static <K> java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(int);
     method public V putIfAbsent(K, V);
-    method public U reduce(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public <U> U reduce(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
     method public java.util.Map.Entry<K, V> reduceEntries(long, java.util.function.BiFunction<java.util.Map.Entry<K, V>, java.util.Map.Entry<K, V>, ? extends java.util.Map.Entry<K, V>>);
-    method public U reduceEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public <U> U reduceEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
     method public double reduceEntriesToDouble(long, java.util.function.ToDoubleFunction<java.util.Map.Entry<K, V>>, double, java.util.function.DoubleBinaryOperator);
     method public int reduceEntriesToInt(long, java.util.function.ToIntFunction<java.util.Map.Entry<K, V>>, int, java.util.function.IntBinaryOperator);
     method public long reduceEntriesToLong(long, java.util.function.ToLongFunction<java.util.Map.Entry<K, V>>, long, java.util.function.LongBinaryOperator);
     method public K reduceKeys(long, java.util.function.BiFunction<? super K, ? super K, ? extends K>);
-    method public U reduceKeys(long, java.util.function.Function<? super K, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public <U> U reduceKeys(long, java.util.function.Function<? super K, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
     method public double reduceKeysToDouble(long, java.util.function.ToDoubleFunction<? super K>, double, java.util.function.DoubleBinaryOperator);
     method public int reduceKeysToInt(long, java.util.function.ToIntFunction<? super K>, int, java.util.function.IntBinaryOperator);
     method public long reduceKeysToLong(long, java.util.function.ToLongFunction<? super K>, long, java.util.function.LongBinaryOperator);
@@ -60682,7 +60685,7 @@
     method public int reduceToInt(long, java.util.function.ToIntBiFunction<? super K, ? super V>, int, java.util.function.IntBinaryOperator);
     method public long reduceToLong(long, java.util.function.ToLongBiFunction<? super K, ? super V>, long, java.util.function.LongBinaryOperator);
     method public V reduceValues(long, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
-    method public U reduceValues(long, java.util.function.Function<? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public <U> U reduceValues(long, java.util.function.Function<? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
     method public double reduceValuesToDouble(long, java.util.function.ToDoubleFunction<? super V>, double, java.util.function.DoubleBinaryOperator);
     method public int reduceValuesToInt(long, java.util.function.ToIntFunction<? super V>, int, java.util.function.IntBinaryOperator);
     method public long reduceValuesToLong(long, java.util.function.ToLongFunction<? super V>, long, java.util.function.LongBinaryOperator);
@@ -60690,13 +60693,13 @@
     method public boolean replace(K, V, V);
     method public V replace(K, V);
     method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
-    method public U search(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>);
-    method public U searchEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>);
-    method public U searchKeys(long, java.util.function.Function<? super K, ? extends U>);
-    method public U searchValues(long, java.util.function.Function<? super V, ? extends U>);
+    method public <U> U search(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>);
+    method public <U> U searchEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>);
+    method public <U> U searchKeys(long, java.util.function.Function<? super K, ? extends U>);
+    method public <U> U searchValues(long, java.util.function.Function<? super V, ? extends U>);
   }
 
-   static abstract class ConcurrentHashMap.CollectionView implements java.util.Collection java.io.Serializable {
+   static abstract class ConcurrentHashMap.CollectionView<K, V, E> implements java.util.Collection java.io.Serializable {
     method public final void clear();
     method public abstract boolean contains(java.lang.Object);
     method public final boolean containsAll(java.util.Collection<?>);
@@ -60708,11 +60711,11 @@
     method public final boolean retainAll(java.util.Collection<?>);
     method public final int size();
     method public final java.lang.Object[] toArray();
-    method public final T[] toArray(T[]);
+    method public final <T> T[] toArray(T[]);
     method public final java.lang.String toString();
   }
 
-  public static class ConcurrentHashMap.KeySetView extends java.util.concurrent.ConcurrentHashMap.CollectionView implements java.io.Serializable java.util.Set {
+  public static class ConcurrentHashMap.KeySetView<K, V> extends java.util.concurrent.ConcurrentHashMap.CollectionView implements java.io.Serializable java.util.Set {
     method public boolean add(K);
     method public boolean addAll(java.util.Collection<? extends K>);
     method public boolean contains(java.lang.Object);
@@ -60723,7 +60726,7 @@
     method public java.util.Spliterator<K> spliterator();
   }
 
-  public class ConcurrentLinkedDeque extends java.util.AbstractCollection implements java.util.Deque java.io.Serializable {
+  public class ConcurrentLinkedDeque<E> extends java.util.AbstractCollection implements java.util.Deque java.io.Serializable {
     ctor public ConcurrentLinkedDeque();
     ctor public ConcurrentLinkedDeque(java.util.Collection<? extends E>);
     method public void addFirst(E);
@@ -60753,7 +60756,7 @@
     method public java.util.Spliterator<E> spliterator();
   }
 
-  public class ConcurrentLinkedQueue extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable {
+  public class ConcurrentLinkedQueue<E> extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable {
     ctor public ConcurrentLinkedQueue();
     ctor public ConcurrentLinkedQueue(java.util.Collection<? extends E>);
     method public java.util.Iterator<E> iterator();
@@ -60764,14 +60767,14 @@
     method public java.util.Spliterator<E> spliterator();
   }
 
-  public abstract interface ConcurrentMap implements java.util.Map {
+  public abstract interface ConcurrentMap<K, V> implements java.util.Map {
     method public abstract V putIfAbsent(K, V);
     method public abstract boolean remove(java.lang.Object, java.lang.Object);
     method public abstract boolean replace(K, V, V);
     method public abstract V replace(K, V);
   }
 
-  public abstract interface ConcurrentNavigableMap implements java.util.concurrent.ConcurrentMap java.util.NavigableMap {
+  public abstract interface ConcurrentNavigableMap<K, V> implements java.util.concurrent.ConcurrentMap java.util.NavigableMap {
     method public abstract java.util.NavigableSet<K> descendingKeySet();
     method public abstract java.util.concurrent.ConcurrentNavigableMap<K, V> descendingMap();
     method public abstract java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K, boolean);
@@ -60784,7 +60787,7 @@
     method public abstract java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K);
   }
 
-  public class ConcurrentSkipListMap extends java.util.AbstractMap implements java.lang.Cloneable java.util.concurrent.ConcurrentNavigableMap java.io.Serializable {
+  public class ConcurrentSkipListMap<K, V> extends java.util.AbstractMap implements java.lang.Cloneable java.util.concurrent.ConcurrentNavigableMap java.io.Serializable {
     ctor public ConcurrentSkipListMap();
     ctor public ConcurrentSkipListMap(java.util.Comparator<? super K>);
     ctor public ConcurrentSkipListMap(java.util.Map<? extends K, ? extends V>);
@@ -60828,7 +60831,7 @@
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K);
   }
 
-  public class ConcurrentSkipListSet extends java.util.AbstractSet implements java.lang.Cloneable java.util.NavigableSet java.io.Serializable {
+  public class ConcurrentSkipListSet<E> extends java.util.AbstractSet implements java.lang.Cloneable java.util.NavigableSet java.io.Serializable {
     ctor public ConcurrentSkipListSet();
     ctor public ConcurrentSkipListSet(java.util.Comparator<? super E>);
     ctor public ConcurrentSkipListSet(java.util.Collection<? extends E>);
@@ -60856,7 +60859,7 @@
     method public java.util.NavigableSet<E> tailSet(E);
   }
 
-  public class CopyOnWriteArrayList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
+  public class CopyOnWriteArrayList<E> implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
     ctor public CopyOnWriteArrayList();
     ctor public CopyOnWriteArrayList(java.util.Collection<? extends E>);
     ctor public CopyOnWriteArrayList(E[]);
@@ -60888,10 +60891,10 @@
     method public int size();
     method public java.util.List<E> subList(int, int);
     method public java.lang.Object[] toArray();
-    method public T[] toArray(T[]);
+    method public <T> T[] toArray(T[]);
   }
 
-  public class CopyOnWriteArraySet extends java.util.AbstractSet implements java.io.Serializable {
+  public class CopyOnWriteArraySet<E> extends java.util.AbstractSet implements java.io.Serializable {
     ctor public CopyOnWriteArraySet();
     ctor public CopyOnWriteArraySet(java.util.Collection<? extends E>);
     method public void forEach(java.util.function.Consumer<? super E>);
@@ -60909,7 +60912,7 @@
     method public long getCount();
   }
 
-  public abstract class CountedCompleter extends java.util.concurrent.ForkJoinTask {
+  public abstract class CountedCompleter<T> extends java.util.concurrent.ForkJoinTask {
     ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>, int);
     ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>);
     ctor protected CountedCompleter();
@@ -60946,7 +60949,7 @@
     method public void reset();
   }
 
-  public class DelayQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue {
+  public class DelayQueue<E extends java.util.concurrent.Delayed> extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue {
     ctor public DelayQueue();
     ctor public DelayQueue(java.util.Collection<? extends E>);
     method public int drainTo(java.util.Collection<? super E>);
@@ -60967,7 +60970,7 @@
     method public abstract long getDelay(java.util.concurrent.TimeUnit);
   }
 
-  public class Exchanger {
+  public class Exchanger<V> {
     ctor public Exchanger();
     method public V exchange(V) throws java.lang.InterruptedException;
     method public V exchange(V, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException, java.util.concurrent.TimeoutException;
@@ -60984,7 +60987,7 @@
     method public abstract void execute(java.lang.Runnable);
   }
 
-  public class ExecutorCompletionService implements java.util.concurrent.CompletionService {
+  public class ExecutorCompletionService<V> implements java.util.concurrent.CompletionService {
     ctor public ExecutorCompletionService(java.util.concurrent.Executor);
     ctor public ExecutorCompletionService(java.util.concurrent.Executor, java.util.concurrent.BlockingQueue<java.util.concurrent.Future<V>>);
     method public java.util.concurrent.Future<V> poll();
@@ -60996,21 +60999,21 @@
 
   public abstract interface ExecutorService implements java.util.concurrent.Executor {
     method public abstract boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
-    method public abstract java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.lang.InterruptedException;
-    method public abstract java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
-    method public abstract T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
-    method public abstract T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method public abstract <T> java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.lang.InterruptedException;
+    method public abstract <T> java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public abstract <T> T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public abstract <T> T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
     method public abstract boolean isShutdown();
     method public abstract boolean isTerminated();
     method public abstract void shutdown();
     method public abstract java.util.List<java.lang.Runnable> shutdownNow();
-    method public abstract java.util.concurrent.Future<T> submit(java.util.concurrent.Callable<T>);
-    method public abstract java.util.concurrent.Future<T> submit(java.lang.Runnable, T);
+    method public abstract <T> java.util.concurrent.Future<T> submit(java.util.concurrent.Callable<T>);
+    method public abstract <T> java.util.concurrent.Future<T> submit(java.lang.Runnable, T);
     method public abstract java.util.concurrent.Future<?> submit(java.lang.Runnable);
   }
 
   public class Executors {
-    method public static java.util.concurrent.Callable<T> callable(java.lang.Runnable, T);
+    method public static <T> java.util.concurrent.Callable<T> callable(java.lang.Runnable, T);
     method public static java.util.concurrent.Callable<java.lang.Object> callable(java.lang.Runnable);
     method public static java.util.concurrent.Callable<java.lang.Object> callable(java.security.PrivilegedAction<?>);
     method public static java.util.concurrent.Callable<java.lang.Object> callable(java.security.PrivilegedExceptionAction<?>);
@@ -61027,8 +61030,8 @@
     method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor(java.util.concurrent.ThreadFactory);
     method public static java.util.concurrent.ExecutorService newWorkStealingPool(int);
     method public static java.util.concurrent.ExecutorService newWorkStealingPool();
-    method public static java.util.concurrent.Callable<T> privilegedCallable(java.util.concurrent.Callable<T>);
-    method public static java.util.concurrent.Callable<T> privilegedCallableUsingCurrentClassLoader(java.util.concurrent.Callable<T>);
+    method public static <T> java.util.concurrent.Callable<T> privilegedCallable(java.util.concurrent.Callable<T>);
+    method public static <T> java.util.concurrent.Callable<T> privilegedCallableUsingCurrentClassLoader(java.util.concurrent.Callable<T>);
     method public static java.util.concurrent.ThreadFactory privilegedThreadFactory();
     method public static java.util.concurrent.ExecutorService unconfigurableExecutorService(java.util.concurrent.ExecutorService);
     method public static java.util.concurrent.ScheduledExecutorService unconfigurableScheduledExecutorService(java.util.concurrent.ScheduledExecutorService);
@@ -61056,7 +61059,7 @@
     method public long getStealCount();
     method public java.lang.Thread.UncaughtExceptionHandler getUncaughtExceptionHandler();
     method public boolean hasQueuedSubmissions();
-    method public T invoke(java.util.concurrent.ForkJoinTask<T>);
+    method public <T> T invoke(java.util.concurrent.ForkJoinTask<T>);
     method public boolean isQuiescent();
     method public boolean isShutdown();
     method public boolean isTerminated();
@@ -61065,7 +61068,7 @@
     method protected java.util.concurrent.ForkJoinTask<?> pollSubmission();
     method public void shutdown();
     method public java.util.List<java.lang.Runnable> shutdownNow();
-    method public java.util.concurrent.ForkJoinTask<T> submit(java.util.concurrent.ForkJoinTask<T>);
+    method public <T> java.util.concurrent.ForkJoinTask<T> submit(java.util.concurrent.ForkJoinTask<T>);
     field public static final java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory defaultForkJoinWorkerThreadFactory;
   }
 
@@ -61078,11 +61081,11 @@
     method public abstract boolean isReleasable();
   }
 
-  public abstract class ForkJoinTask implements java.util.concurrent.Future java.io.Serializable {
+  public abstract class ForkJoinTask<V> implements java.util.concurrent.Future java.io.Serializable {
     ctor public ForkJoinTask();
     method public static java.util.concurrent.ForkJoinTask<?> adapt(java.lang.Runnable);
-    method public static java.util.concurrent.ForkJoinTask<T> adapt(java.lang.Runnable, T);
-    method public static java.util.concurrent.ForkJoinTask<T> adapt(java.util.concurrent.Callable<? extends T>);
+    method public static <T> java.util.concurrent.ForkJoinTask<T> adapt(java.lang.Runnable, T);
+    method public static <T> java.util.concurrent.ForkJoinTask<T> adapt(java.util.concurrent.Callable<? extends T>);
     method public boolean cancel(boolean);
     method public final boolean compareAndSetForkJoinTaskTag(short, short);
     method public void complete(V);
@@ -61102,7 +61105,7 @@
     method public final V invoke();
     method public static void invokeAll(java.util.concurrent.ForkJoinTask<?>, java.util.concurrent.ForkJoinTask<?>);
     method public static void invokeAll(java.util.concurrent.ForkJoinTask<?>...);
-    method public static java.util.Collection<T> invokeAll(java.util.Collection<T>);
+    method public static <T extends java.util.concurrent.ForkJoinTask<?>> java.util.Collection<T> invokeAll(java.util.Collection<T>);
     method public final boolean isCancelled();
     method public final boolean isCompletedAbnormally();
     method public final boolean isCompletedNormally();
@@ -61128,7 +61131,7 @@
     method protected void onTermination(java.lang.Throwable);
   }
 
-  public abstract interface Future {
+  public abstract interface Future<V> {
     method public abstract boolean cancel(boolean);
     method public abstract V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
     method public abstract V get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
@@ -61136,7 +61139,7 @@
     method public abstract boolean isDone();
   }
 
-  public class FutureTask implements java.util.concurrent.RunnableFuture {
+  public class FutureTask<V> implements java.util.concurrent.RunnableFuture {
     ctor public FutureTask(java.util.concurrent.Callable<V>);
     ctor public FutureTask(java.lang.Runnable, V);
     method public boolean cancel(boolean);
@@ -61151,7 +61154,7 @@
     method protected void setException(java.lang.Throwable);
   }
 
-  public class LinkedBlockingDeque extends java.util.AbstractQueue implements java.util.concurrent.BlockingDeque java.io.Serializable {
+  public class LinkedBlockingDeque<E> extends java.util.AbstractQueue implements java.util.concurrent.BlockingDeque java.io.Serializable {
     ctor public LinkedBlockingDeque();
     ctor public LinkedBlockingDeque(int);
     ctor public LinkedBlockingDeque(java.util.Collection<? extends E>);
@@ -61195,7 +61198,7 @@
     method public E takeLast() throws java.lang.InterruptedException;
   }
 
-  public class LinkedBlockingQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
+  public class LinkedBlockingQueue<E> extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
     ctor public LinkedBlockingQueue();
     ctor public LinkedBlockingQueue(int);
     ctor public LinkedBlockingQueue(java.util.Collection<? extends E>);
@@ -61214,7 +61217,7 @@
     method public E take() throws java.lang.InterruptedException;
   }
 
-  public class LinkedTransferQueue extends java.util.AbstractQueue implements java.io.Serializable java.util.concurrent.TransferQueue {
+  public class LinkedTransferQueue<E> extends java.util.AbstractQueue implements java.io.Serializable java.util.concurrent.TransferQueue {
     ctor public LinkedTransferQueue();
     ctor public LinkedTransferQueue(java.util.Collection<? extends E>);
     method public int drainTo(java.util.Collection<? super E>);
@@ -61261,7 +61264,7 @@
     method public int register();
   }
 
-  public class PriorityBlockingQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
+  public class PriorityBlockingQueue<E> extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
     ctor public PriorityBlockingQueue();
     ctor public PriorityBlockingQueue(int);
     ctor public PriorityBlockingQueue(int, java.util.Comparator<? super E>);
@@ -61290,7 +61293,7 @@
     method protected final void setRawResult(java.lang.Void);
   }
 
-  public abstract class RecursiveTask extends java.util.concurrent.ForkJoinTask {
+  public abstract class RecursiveTask<V> extends java.util.concurrent.ForkJoinTask {
     ctor public RecursiveTask();
     method protected abstract V compute();
     method protected final boolean exec();
@@ -61309,22 +61312,22 @@
     method public abstract void rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor);
   }
 
-  public abstract interface RunnableFuture implements java.util.concurrent.Future java.lang.Runnable {
+  public abstract interface RunnableFuture<V> implements java.util.concurrent.Future java.lang.Runnable {
     method public abstract void run();
   }
 
-  public abstract interface RunnableScheduledFuture implements java.util.concurrent.RunnableFuture java.util.concurrent.ScheduledFuture {
+  public abstract interface RunnableScheduledFuture<V> implements java.util.concurrent.RunnableFuture java.util.concurrent.ScheduledFuture {
     method public abstract boolean isPeriodic();
   }
 
   public abstract interface ScheduledExecutorService implements java.util.concurrent.ExecutorService {
     method public abstract java.util.concurrent.ScheduledFuture<?> schedule(java.lang.Runnable, long, java.util.concurrent.TimeUnit);
-    method public abstract java.util.concurrent.ScheduledFuture<V> schedule(java.util.concurrent.Callable<V>, long, java.util.concurrent.TimeUnit);
+    method public abstract <V> java.util.concurrent.ScheduledFuture<V> schedule(java.util.concurrent.Callable<V>, long, java.util.concurrent.TimeUnit);
     method public abstract java.util.concurrent.ScheduledFuture<?> scheduleAtFixedRate(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
     method public abstract java.util.concurrent.ScheduledFuture<?> scheduleWithFixedDelay(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
   }
 
-  public abstract interface ScheduledFuture implements java.util.concurrent.Delayed java.util.concurrent.Future {
+  public abstract interface ScheduledFuture<V> implements java.util.concurrent.Delayed java.util.concurrent.Future {
   }
 
   public class ScheduledThreadPoolExecutor extends java.util.concurrent.ThreadPoolExecutor implements java.util.concurrent.ScheduledExecutorService {
@@ -61332,13 +61335,13 @@
     ctor public ScheduledThreadPoolExecutor(int, java.util.concurrent.ThreadFactory);
     ctor public ScheduledThreadPoolExecutor(int, java.util.concurrent.RejectedExecutionHandler);
     ctor public ScheduledThreadPoolExecutor(int, java.util.concurrent.ThreadFactory, java.util.concurrent.RejectedExecutionHandler);
-    method protected java.util.concurrent.RunnableScheduledFuture<V> decorateTask(java.lang.Runnable, java.util.concurrent.RunnableScheduledFuture<V>);
-    method protected java.util.concurrent.RunnableScheduledFuture<V> decorateTask(java.util.concurrent.Callable<V>, java.util.concurrent.RunnableScheduledFuture<V>);
+    method protected <V> java.util.concurrent.RunnableScheduledFuture<V> decorateTask(java.lang.Runnable, java.util.concurrent.RunnableScheduledFuture<V>);
+    method protected <V> java.util.concurrent.RunnableScheduledFuture<V> decorateTask(java.util.concurrent.Callable<V>, java.util.concurrent.RunnableScheduledFuture<V>);
     method public boolean getContinueExistingPeriodicTasksAfterShutdownPolicy();
     method public boolean getExecuteExistingDelayedTasksAfterShutdownPolicy();
     method public boolean getRemoveOnCancelPolicy();
     method public java.util.concurrent.ScheduledFuture<?> schedule(java.lang.Runnable, long, java.util.concurrent.TimeUnit);
-    method public java.util.concurrent.ScheduledFuture<V> schedule(java.util.concurrent.Callable<V>, long, java.util.concurrent.TimeUnit);
+    method public <V> java.util.concurrent.ScheduledFuture<V> schedule(java.util.concurrent.Callable<V>, long, java.util.concurrent.TimeUnit);
     method public java.util.concurrent.ScheduledFuture<?> scheduleAtFixedRate(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
     method public java.util.concurrent.ScheduledFuture<?> scheduleWithFixedDelay(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
     method public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean);
@@ -61368,7 +61371,7 @@
     method public boolean tryAcquire(int, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
   }
 
-  public class SynchronousQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
+  public class SynchronousQueue<E> extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
     ctor public SynchronousQueue();
     ctor public SynchronousQueue(boolean);
     method public int drainTo(java.util.Collection<? super E>);
@@ -61486,7 +61489,7 @@
     ctor public TimeoutException(java.lang.String);
   }
 
-  public abstract interface TransferQueue implements java.util.concurrent.BlockingQueue {
+  public abstract interface TransferQueue<E> implements java.util.concurrent.BlockingQueue {
     method public abstract int getWaitingConsumerCount();
     method public abstract boolean hasWaitingConsumer();
     method public abstract void transfer(E) throws java.lang.InterruptedException;
@@ -61556,7 +61559,7 @@
     method public final boolean weakCompareAndSet(int, int, int);
   }
 
-  public abstract class AtomicIntegerFieldUpdater {
+  public abstract class AtomicIntegerFieldUpdater<T> {
     ctor protected AtomicIntegerFieldUpdater();
     method public final int accumulateAndGet(T, int, java.util.function.IntBinaryOperator);
     method public int addAndGet(T, int);
@@ -61571,7 +61574,7 @@
     method public final int getAndUpdate(T, java.util.function.IntUnaryOperator);
     method public int incrementAndGet(T);
     method public abstract void lazySet(T, int);
-    method public static java.util.concurrent.atomic.AtomicIntegerFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
+    method public static <U> java.util.concurrent.atomic.AtomicIntegerFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, int);
     method public final int updateAndGet(T, java.util.function.IntUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, int, int);
@@ -61624,7 +61627,7 @@
     method public final boolean weakCompareAndSet(int, long, long);
   }
 
-  public abstract class AtomicLongFieldUpdater {
+  public abstract class AtomicLongFieldUpdater<T> {
     ctor protected AtomicLongFieldUpdater();
     method public final long accumulateAndGet(T, long, java.util.function.LongBinaryOperator);
     method public long addAndGet(T, long);
@@ -61639,13 +61642,13 @@
     method public final long getAndUpdate(T, java.util.function.LongUnaryOperator);
     method public long incrementAndGet(T);
     method public abstract void lazySet(T, long);
-    method public static java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
+    method public static <U> java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, long);
     method public final long updateAndGet(T, java.util.function.LongUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, long, long);
   }
 
-  public class AtomicMarkableReference {
+  public class AtomicMarkableReference<V> {
     ctor public AtomicMarkableReference(V, boolean);
     method public boolean attemptMark(V, boolean);
     method public boolean compareAndSet(V, V, boolean, boolean);
@@ -61656,7 +61659,7 @@
     method public boolean weakCompareAndSet(V, V, boolean, boolean);
   }
 
-  public class AtomicReference implements java.io.Serializable {
+  public class AtomicReference<V> implements java.io.Serializable {
     ctor public AtomicReference(V);
     ctor public AtomicReference();
     method public final V accumulateAndGet(V, java.util.function.BinaryOperator<V>);
@@ -61671,7 +61674,7 @@
     method public final boolean weakCompareAndSet(V, V);
   }
 
-  public class AtomicReferenceArray implements java.io.Serializable {
+  public class AtomicReferenceArray<E> implements java.io.Serializable {
     ctor public AtomicReferenceArray(int);
     ctor public AtomicReferenceArray(E[]);
     method public final E accumulateAndGet(int, E, java.util.function.BinaryOperator<E>);
@@ -61687,7 +61690,7 @@
     method public final boolean weakCompareAndSet(int, E, E);
   }
 
-  public abstract class AtomicReferenceFieldUpdater {
+  public abstract class AtomicReferenceFieldUpdater<T, V> {
     ctor protected AtomicReferenceFieldUpdater();
     method public final V accumulateAndGet(T, V, java.util.function.BinaryOperator<V>);
     method public abstract boolean compareAndSet(T, V, V);
@@ -61696,13 +61699,13 @@
     method public V getAndSet(T, V);
     method public final V getAndUpdate(T, java.util.function.UnaryOperator<V>);
     method public abstract void lazySet(T, V);
-    method public static java.util.concurrent.atomic.AtomicReferenceFieldUpdater<U, W> newUpdater(java.lang.Class<U>, java.lang.Class<W>, java.lang.String);
+    method public static <U, W> java.util.concurrent.atomic.AtomicReferenceFieldUpdater<U, W> newUpdater(java.lang.Class<U>, java.lang.Class<W>, java.lang.String);
     method public abstract void set(T, V);
     method public final V updateAndGet(T, java.util.function.UnaryOperator<V>);
     method public abstract boolean weakCompareAndSet(T, V, V);
   }
 
-  public class AtomicStampedReference {
+  public class AtomicStampedReference<V> {
     ctor public AtomicStampedReference(V, int);
     method public boolean attemptStamp(V, int);
     method public boolean compareAndSet(V, V, int, int);
@@ -62005,33 +62008,33 @@
 
 package java.util.function {
 
-  public abstract interface BiConsumer {
+  public abstract interface BiConsumer<T, U> {
     method public abstract void accept(T, U);
     method public default java.util.function.BiConsumer<T, U> andThen(java.util.function.BiConsumer<? super T, ? super U>);
   }
 
-  public abstract interface BiFunction {
-    method public default java.util.function.BiFunction<T, U, V> andThen(java.util.function.Function<? super R, ? extends V>);
+  public abstract interface BiFunction<T, U, R> {
+    method public default <V> java.util.function.BiFunction<T, U, V> andThen(java.util.function.Function<? super R, ? extends V>);
     method public abstract R apply(T, U);
   }
 
-  public abstract interface BiPredicate {
+  public abstract interface BiPredicate<T, U> {
     method public default java.util.function.BiPredicate<T, U> and(java.util.function.BiPredicate<? super T, ? super U>);
     method public default java.util.function.BiPredicate<T, U> negate();
     method public default java.util.function.BiPredicate<T, U> or(java.util.function.BiPredicate<? super T, ? super U>);
     method public abstract boolean test(T, U);
   }
 
-  public abstract interface BinaryOperator implements java.util.function.BiFunction {
-    method public static java.util.function.BinaryOperator<T> maxBy(java.util.Comparator<? super T>);
-    method public static java.util.function.BinaryOperator<T> minBy(java.util.Comparator<? super T>);
+  public abstract interface BinaryOperator<T> implements java.util.function.BiFunction {
+    method public static <T> java.util.function.BinaryOperator<T> maxBy(java.util.Comparator<? super T>);
+    method public static <T> java.util.function.BinaryOperator<T> minBy(java.util.Comparator<? super T>);
   }
 
   public abstract interface BooleanSupplier {
     method public abstract boolean getAsBoolean();
   }
 
-  public abstract interface Consumer {
+  public abstract interface Consumer<T> {
     method public abstract void accept(T);
     method public default java.util.function.Consumer<T> andThen(java.util.function.Consumer<? super T>);
   }
@@ -62045,7 +62048,7 @@
     method public default java.util.function.DoubleConsumer andThen(java.util.function.DoubleConsumer);
   }
 
-  public abstract interface DoubleFunction {
+  public abstract interface DoubleFunction<R> {
     method public abstract R apply(double);
   }
 
@@ -62075,11 +62078,11 @@
     method public static java.util.function.DoubleUnaryOperator identity();
   }
 
-  public abstract interface Function {
-    method public default java.util.function.Function<T, V> andThen(java.util.function.Function<? super R, ? extends V>);
+  public abstract interface Function<T, R> {
+    method public default <V> java.util.function.Function<T, V> andThen(java.util.function.Function<? super R, ? extends V>);
     method public abstract R apply(T);
-    method public default java.util.function.Function<V, R> compose(java.util.function.Function<? super V, ? extends T>);
-    method public static java.util.function.Function<T, T> identity();
+    method public default <V> java.util.function.Function<V, R> compose(java.util.function.Function<? super V, ? extends T>);
+    method public static <T> java.util.function.Function<T, T> identity();
   }
 
   public abstract interface IntBinaryOperator {
@@ -62091,7 +62094,7 @@
     method public default java.util.function.IntConsumer andThen(java.util.function.IntConsumer);
   }
 
-  public abstract interface IntFunction {
+  public abstract interface IntFunction<R> {
     method public abstract R apply(int);
   }
 
@@ -62130,7 +62133,7 @@
     method public default java.util.function.LongConsumer andThen(java.util.function.LongConsumer);
   }
 
-  public abstract interface LongFunction {
+  public abstract interface LongFunction<R> {
     method public abstract R apply(long);
   }
 
@@ -62160,56 +62163,56 @@
     method public static java.util.function.LongUnaryOperator identity();
   }
 
-  public abstract interface ObjDoubleConsumer {
+  public abstract interface ObjDoubleConsumer<T> {
     method public abstract void accept(T, double);
   }
 
-  public abstract interface ObjIntConsumer {
+  public abstract interface ObjIntConsumer<T> {
     method public abstract void accept(T, int);
   }
 
-  public abstract interface ObjLongConsumer {
+  public abstract interface ObjLongConsumer<T> {
     method public abstract void accept(T, long);
   }
 
-  public abstract interface Predicate {
+  public abstract interface Predicate<T> {
     method public default java.util.function.Predicate<T> and(java.util.function.Predicate<? super T>);
-    method public static java.util.function.Predicate<T> isEqual(java.lang.Object);
+    method public static <T> java.util.function.Predicate<T> isEqual(java.lang.Object);
     method public default java.util.function.Predicate<T> negate();
     method public default java.util.function.Predicate<T> or(java.util.function.Predicate<? super T>);
     method public abstract boolean test(T);
   }
 
-  public abstract interface Supplier {
+  public abstract interface Supplier<T> {
     method public abstract T get();
   }
 
-  public abstract interface ToDoubleBiFunction {
+  public abstract interface ToDoubleBiFunction<T, U> {
     method public abstract double applyAsDouble(T, U);
   }
 
-  public abstract interface ToDoubleFunction {
+  public abstract interface ToDoubleFunction<T> {
     method public abstract double applyAsDouble(T);
   }
 
-  public abstract interface ToIntBiFunction {
+  public abstract interface ToIntBiFunction<T, U> {
     method public abstract int applyAsInt(T, U);
   }
 
-  public abstract interface ToIntFunction {
+  public abstract interface ToIntFunction<T> {
     method public abstract int applyAsInt(T);
   }
 
-  public abstract interface ToLongBiFunction {
+  public abstract interface ToLongBiFunction<T, U> {
     method public abstract long applyAsLong(T, U);
   }
 
-  public abstract interface ToLongFunction {
+  public abstract interface ToLongFunction<T> {
     method public abstract long applyAsLong(T);
   }
 
-  public abstract interface UnaryOperator implements java.util.function.Function {
-    method public static java.util.function.UnaryOperator<T> identity();
+  public abstract interface UnaryOperator<T> implements java.util.function.Function {
+    method public static <T> java.util.function.UnaryOperator<T> identity();
   }
 
 }
@@ -62797,7 +62800,7 @@
 
 package java.util.stream {
 
-  public abstract interface BaseStream implements java.lang.AutoCloseable {
+  public abstract interface BaseStream<T, S extends java.util.stream.BaseStream<T, S>> implements java.lang.AutoCloseable {
     method public abstract void close();
     method public abstract boolean isParallel();
     method public abstract java.util.Iterator<T> iterator();
@@ -62808,13 +62811,13 @@
     method public abstract S unordered();
   }
 
-  public abstract interface Collector {
+  public abstract interface Collector<T, A, R> {
     method public abstract java.util.function.BiConsumer<A, T> accumulator();
     method public abstract java.util.Set<java.util.stream.Collector.Characteristics> characteristics();
     method public abstract java.util.function.BinaryOperator<A> combiner();
     method public abstract java.util.function.Function<A, R> finisher();
-    method public static java.util.stream.Collector<T, R, R> of(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, T>, java.util.function.BinaryOperator<R>, java.util.stream.Collector.Characteristics...);
-    method public static java.util.stream.Collector<T, A, R> of(java.util.function.Supplier<A>, java.util.function.BiConsumer<A, T>, java.util.function.BinaryOperator<A>, java.util.function.Function<A, R>, java.util.stream.Collector.Characteristics...);
+    method public static <T, R> java.util.stream.Collector<T, R, R> of(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, T>, java.util.function.BinaryOperator<R>, java.util.stream.Collector.Characteristics...);
+    method public static <T, A, R> java.util.stream.Collector<T, A, R> of(java.util.function.Supplier<A>, java.util.function.BiConsumer<A, T>, java.util.function.BinaryOperator<A>, java.util.function.Function<A, R>, java.util.stream.Collector.Characteristics...);
     method public abstract java.util.function.Supplier<A> supplier();
   }
 
@@ -62827,43 +62830,43 @@
   }
 
   public final class Collectors {
-    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingDouble(java.util.function.ToDoubleFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingInt(java.util.function.ToIntFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingLong(java.util.function.ToLongFunction<? super T>);
-    method public static java.util.stream.Collector<T, A, RR> collectingAndThen(java.util.stream.Collector<T, A, R>, java.util.function.Function<R, RR>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Long> counting();
-    method public static java.util.stream.Collector<T, ?, java.util.Map<K, java.util.List<T>>> groupingBy(java.util.function.Function<? super T, ? extends K>);
-    method public static java.util.stream.Collector<T, ?, java.util.Map<K, D>> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
-    method public static java.util.stream.Collector<T, ?, M> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
-    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, java.util.List<T>>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>);
-    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, D>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
-    method public static java.util.stream.Collector<T, ?, M> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Double> averagingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Double> averagingInt(java.util.function.ToIntFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Double> averagingLong(java.util.function.ToLongFunction<? super T>);
+    method public static <T, A, R, RR> java.util.stream.Collector<T, A, RR> collectingAndThen(java.util.stream.Collector<T, A, R>, java.util.function.Function<R, RR>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Long> counting();
+    method public static <T, K> java.util.stream.Collector<T, ?, java.util.Map<K, java.util.List<T>>> groupingBy(java.util.function.Function<? super T, ? extends K>);
+    method public static <T, K, A, D> java.util.stream.Collector<T, ?, java.util.Map<K, D>> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
+    method public static <T, K, D, A, M extends java.util.Map<K, D>> java.util.stream.Collector<T, ?, M> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
+    method public static <T, K> java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, java.util.List<T>>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>);
+    method public static <T, K, A, D> java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, D>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
+    method public static <T, K, A, D, M extends java.util.concurrent.ConcurrentMap<K, D>> java.util.stream.Collector<T, ?, M> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
     method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining();
     method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining(java.lang.CharSequence);
     method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining(java.lang.CharSequence, java.lang.CharSequence, java.lang.CharSequence);
-    method public static java.util.stream.Collector<T, ?, R> mapping(java.util.function.Function<? super T, ? extends U>, java.util.stream.Collector<? super U, A, R>);
-    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> maxBy(java.util.Comparator<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> minBy(java.util.Comparator<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, java.util.List<T>>> partitioningBy(java.util.function.Predicate<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, D>> partitioningBy(java.util.function.Predicate<? super T>, java.util.stream.Collector<? super T, A, D>);
-    method public static java.util.stream.Collector<T, ?, T> reducing(T, java.util.function.BinaryOperator<T>);
-    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> reducing(java.util.function.BinaryOperator<T>);
-    method public static java.util.stream.Collector<T, ?, U> reducing(U, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
-    method public static java.util.stream.Collector<T, ?, java.util.DoubleSummaryStatistics> summarizingDouble(java.util.function.ToDoubleFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.util.IntSummaryStatistics> summarizingInt(java.util.function.ToIntFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.util.LongSummaryStatistics> summarizingLong(java.util.function.ToLongFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Double> summingDouble(java.util.function.ToDoubleFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Integer> summingInt(java.util.function.ToIntFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, java.lang.Long> summingLong(java.util.function.ToLongFunction<? super T>);
-    method public static java.util.stream.Collector<T, ?, C> toCollection(java.util.function.Supplier<C>);
-    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
-    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
-    method public static java.util.stream.Collector<T, ?, M> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
-    method public static java.util.stream.Collector<T, ?, java.util.List<T>> toList();
-    method public static java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
-    method public static java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
-    method public static java.util.stream.Collector<T, ?, M> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
-    method public static java.util.stream.Collector<T, ?, java.util.Set<T>> toSet();
+    method public static <T, U, A, R> java.util.stream.Collector<T, ?, R> mapping(java.util.function.Function<? super T, ? extends U>, java.util.stream.Collector<? super U, A, R>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.Optional<T>> maxBy(java.util.Comparator<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.Optional<T>> minBy(java.util.Comparator<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, java.util.List<T>>> partitioningBy(java.util.function.Predicate<? super T>);
+    method public static <T, D, A> java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, D>> partitioningBy(java.util.function.Predicate<? super T>, java.util.stream.Collector<? super T, A, D>);
+    method public static <T> java.util.stream.Collector<T, ?, T> reducing(T, java.util.function.BinaryOperator<T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.Optional<T>> reducing(java.util.function.BinaryOperator<T>);
+    method public static <T, U> java.util.stream.Collector<T, ?, U> reducing(U, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.DoubleSummaryStatistics> summarizingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.IntSummaryStatistics> summarizingInt(java.util.function.ToIntFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.LongSummaryStatistics> summarizingLong(java.util.function.ToLongFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Double> summingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Integer> summingInt(java.util.function.ToIntFunction<? super T>);
+    method public static <T> java.util.stream.Collector<T, ?, java.lang.Long> summingLong(java.util.function.ToLongFunction<? super T>);
+    method public static <T, C extends java.util.Collection<T>> java.util.stream.Collector<T, ?, C> toCollection(java.util.function.Supplier<C>);
+    method public static <T, K, U> java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
+    method public static <T, K, U> java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static <T, K, U, M extends java.util.concurrent.ConcurrentMap<K, U>> java.util.stream.Collector<T, ?, M> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.List<T>> toList();
+    method public static <T, K, U> java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
+    method public static <T, K, U> java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static <T, K, U, M extends java.util.Map<K, U>> java.util.stream.Collector<T, ?, M> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
+    method public static <T> java.util.stream.Collector<T, ?, java.util.Set<T>> toSet();
   }
 
   public abstract interface DoubleStream implements java.util.stream.BaseStream {
@@ -62872,7 +62875,7 @@
     method public abstract java.util.OptionalDouble average();
     method public abstract java.util.stream.Stream<java.lang.Double> boxed();
     method public static java.util.stream.DoubleStream.Builder builder();
-    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjDoubleConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public abstract <R> R collect(java.util.function.Supplier<R>, java.util.function.ObjDoubleConsumer<R>, java.util.function.BiConsumer<R, R>);
     method public static java.util.stream.DoubleStream concat(java.util.stream.DoubleStream, java.util.stream.DoubleStream);
     method public abstract long count();
     method public abstract java.util.stream.DoubleStream distinct();
@@ -62890,7 +62893,7 @@
     method public abstract java.util.stream.DoubleStream map(java.util.function.DoubleUnaryOperator);
     method public abstract java.util.stream.IntStream mapToInt(java.util.function.DoubleToIntFunction);
     method public abstract java.util.stream.LongStream mapToLong(java.util.function.DoubleToLongFunction);
-    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.DoubleFunction<? extends U>);
+    method public abstract <U> java.util.stream.Stream<U> mapToObj(java.util.function.DoubleFunction<? extends U>);
     method public abstract java.util.OptionalDouble max();
     method public abstract java.util.OptionalDouble min();
     method public abstract boolean noneMatch(java.util.function.DoublePredicate);
@@ -62923,7 +62926,7 @@
     method public abstract java.util.OptionalDouble average();
     method public abstract java.util.stream.Stream<java.lang.Integer> boxed();
     method public static java.util.stream.IntStream.Builder builder();
-    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjIntConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public abstract <R> R collect(java.util.function.Supplier<R>, java.util.function.ObjIntConsumer<R>, java.util.function.BiConsumer<R, R>);
     method public static java.util.stream.IntStream concat(java.util.stream.IntStream, java.util.stream.IntStream);
     method public abstract long count();
     method public abstract java.util.stream.IntStream distinct();
@@ -62941,7 +62944,7 @@
     method public abstract java.util.stream.IntStream map(java.util.function.IntUnaryOperator);
     method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.IntToDoubleFunction);
     method public abstract java.util.stream.LongStream mapToLong(java.util.function.IntToLongFunction);
-    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.IntFunction<? extends U>);
+    method public abstract <U> java.util.stream.Stream<U> mapToObj(java.util.function.IntFunction<? extends U>);
     method public abstract java.util.OptionalInt max();
     method public abstract java.util.OptionalInt min();
     method public abstract boolean noneMatch(java.util.function.IntPredicate);
@@ -62975,7 +62978,7 @@
     method public abstract java.util.OptionalDouble average();
     method public abstract java.util.stream.Stream<java.lang.Long> boxed();
     method public static java.util.stream.LongStream.Builder builder();
-    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjLongConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public abstract <R> R collect(java.util.function.Supplier<R>, java.util.function.ObjLongConsumer<R>, java.util.function.BiConsumer<R, R>);
     method public static java.util.stream.LongStream concat(java.util.stream.LongStream, java.util.stream.LongStream);
     method public abstract long count();
     method public abstract java.util.stream.LongStream distinct();
@@ -62993,7 +62996,7 @@
     method public abstract java.util.stream.LongStream map(java.util.function.LongUnaryOperator);
     method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.LongToDoubleFunction);
     method public abstract java.util.stream.IntStream mapToInt(java.util.function.LongToIntFunction);
-    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.LongFunction<? extends U>);
+    method public abstract <U> java.util.stream.Stream<U> mapToObj(java.util.function.LongFunction<? extends U>);
     method public abstract java.util.OptionalLong max();
     method public abstract java.util.OptionalLong min();
     method public abstract boolean noneMatch(java.util.function.LongPredicate);
@@ -63020,49 +63023,49 @@
     method public abstract java.util.stream.LongStream build();
   }
 
-  public abstract interface Stream implements java.util.stream.BaseStream {
+  public abstract interface Stream<T> implements java.util.stream.BaseStream {
     method public abstract boolean allMatch(java.util.function.Predicate<? super T>);
     method public abstract boolean anyMatch(java.util.function.Predicate<? super T>);
-    method public static java.util.stream.Stream.Builder<T> builder();
-    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, ? super T>, java.util.function.BiConsumer<R, R>);
-    method public abstract R collect(java.util.stream.Collector<? super T, A, R>);
-    method public static java.util.stream.Stream<T> concat(java.util.stream.Stream<? extends T>, java.util.stream.Stream<? extends T>);
+    method public static <T> java.util.stream.Stream.Builder<T> builder();
+    method public abstract <R> R collect(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, ? super T>, java.util.function.BiConsumer<R, R>);
+    method public abstract <R, A> R collect(java.util.stream.Collector<? super T, A, R>);
+    method public static <T> java.util.stream.Stream<T> concat(java.util.stream.Stream<? extends T>, java.util.stream.Stream<? extends T>);
     method public abstract long count();
     method public abstract java.util.stream.Stream<T> distinct();
-    method public static java.util.stream.Stream<T> empty();
+    method public static <T> java.util.stream.Stream<T> empty();
     method public abstract java.util.stream.Stream<T> filter(java.util.function.Predicate<? super T>);
     method public abstract java.util.Optional<T> findAny();
     method public abstract java.util.Optional<T> findFirst();
-    method public abstract java.util.stream.Stream<R> flatMap(java.util.function.Function<? super T, ? extends java.util.stream.Stream<? extends R>>);
+    method public abstract <R> java.util.stream.Stream<R> flatMap(java.util.function.Function<? super T, ? extends java.util.stream.Stream<? extends R>>);
     method public abstract java.util.stream.DoubleStream flatMapToDouble(java.util.function.Function<? super T, ? extends java.util.stream.DoubleStream>);
     method public abstract java.util.stream.IntStream flatMapToInt(java.util.function.Function<? super T, ? extends java.util.stream.IntStream>);
     method public abstract java.util.stream.LongStream flatMapToLong(java.util.function.Function<? super T, ? extends java.util.stream.LongStream>);
     method public abstract void forEach(java.util.function.Consumer<? super T>);
     method public abstract void forEachOrdered(java.util.function.Consumer<? super T>);
-    method public static java.util.stream.Stream<T> generate(java.util.function.Supplier<T>);
-    method public static java.util.stream.Stream<T> iterate(T, java.util.function.UnaryOperator<T>);
+    method public static <T> java.util.stream.Stream<T> generate(java.util.function.Supplier<T>);
+    method public static <T> java.util.stream.Stream<T> iterate(T, java.util.function.UnaryOperator<T>);
     method public abstract java.util.stream.Stream<T> limit(long);
-    method public abstract java.util.stream.Stream<R> map(java.util.function.Function<? super T, ? extends R>);
+    method public abstract <R> java.util.stream.Stream<R> map(java.util.function.Function<? super T, ? extends R>);
     method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.ToDoubleFunction<? super T>);
     method public abstract java.util.stream.IntStream mapToInt(java.util.function.ToIntFunction<? super T>);
     method public abstract java.util.stream.LongStream mapToLong(java.util.function.ToLongFunction<? super T>);
     method public abstract java.util.Optional<T> max(java.util.Comparator<? super T>);
     method public abstract java.util.Optional<T> min(java.util.Comparator<? super T>);
     method public abstract boolean noneMatch(java.util.function.Predicate<? super T>);
-    method public static java.util.stream.Stream<T> of(T);
-    method public static java.util.stream.Stream<T> of(T...);
+    method public static <T> java.util.stream.Stream<T> of(T);
+    method public static <T> java.util.stream.Stream<T> of(T...);
     method public abstract java.util.stream.Stream<T> peek(java.util.function.Consumer<? super T>);
     method public abstract T reduce(T, java.util.function.BinaryOperator<T>);
     method public abstract java.util.Optional<T> reduce(java.util.function.BinaryOperator<T>);
-    method public abstract U reduce(U, java.util.function.BiFunction<U, ? super T, U>, java.util.function.BinaryOperator<U>);
+    method public abstract <U> U reduce(U, java.util.function.BiFunction<U, ? super T, U>, java.util.function.BinaryOperator<U>);
     method public abstract java.util.stream.Stream<T> skip(long);
     method public abstract java.util.stream.Stream<T> sorted();
     method public abstract java.util.stream.Stream<T> sorted(java.util.Comparator<? super T>);
     method public abstract java.lang.Object[] toArray();
-    method public abstract A[] toArray(java.util.function.IntFunction<A[]>);
+    method public abstract <A> A[] toArray(java.util.function.IntFunction<A[]>);
   }
 
-  public static abstract interface Stream.Builder implements java.util.function.Consumer {
+  public static abstract interface Stream.Builder<T> implements java.util.function.Consumer {
     method public abstract void accept(T);
     method public default java.util.stream.Stream.Builder<T> add(T);
     method public abstract java.util.stream.Stream<T> build();
@@ -63075,8 +63078,8 @@
     method public static java.util.stream.IntStream intStream(java.util.function.Supplier<? extends java.util.Spliterator.OfInt>, int, boolean);
     method public static java.util.stream.LongStream longStream(java.util.Spliterator.OfLong, boolean);
     method public static java.util.stream.LongStream longStream(java.util.function.Supplier<? extends java.util.Spliterator.OfLong>, int, boolean);
-    method public static java.util.stream.Stream<T> stream(java.util.Spliterator<T>, boolean);
-    method public static java.util.stream.Stream<T> stream(java.util.function.Supplier<? extends java.util.Spliterator<T>>, int, boolean);
+    method public static <T> java.util.stream.Stream<T> stream(java.util.Spliterator<T>, boolean);
+    method public static <T> java.util.stream.Stream<T> stream(java.util.function.Supplier<? extends java.util.Spliterator<T>>, int, boolean);
   }
 
 }
@@ -65249,16 +65252,16 @@
   public final class Subject implements java.io.Serializable {
     ctor public Subject();
     ctor public Subject(boolean, java.util.Set<? extends java.security.Principal>, java.util.Set<?>, java.util.Set<?>);
-    method public static T doAs(javax.security.auth.Subject, java.security.PrivilegedAction<T>);
-    method public static T doAs(javax.security.auth.Subject, java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
-    method public static T doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedAction<T>, java.security.AccessControlContext);
-    method public static T doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedExceptionAction<T>, java.security.AccessControlContext) throws java.security.PrivilegedActionException;
+    method public static <T> T doAs(javax.security.auth.Subject, java.security.PrivilegedAction<T>);
+    method public static <T> T doAs(javax.security.auth.Subject, java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
+    method public static <T> T doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedAction<T>, java.security.AccessControlContext);
+    method public static <T> T doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedExceptionAction<T>, java.security.AccessControlContext) throws java.security.PrivilegedActionException;
     method public java.util.Set<java.security.Principal> getPrincipals();
-    method public java.util.Set<T> getPrincipals(java.lang.Class<T>);
+    method public <T extends java.security.Principal> java.util.Set<T> getPrincipals(java.lang.Class<T>);
     method public java.util.Set<java.lang.Object> getPrivateCredentials();
-    method public java.util.Set<T> getPrivateCredentials(java.lang.Class<T>);
+    method public <T> java.util.Set<T> getPrivateCredentials(java.lang.Class<T>);
     method public java.util.Set<java.lang.Object> getPublicCredentials();
-    method public java.util.Set<T> getPublicCredentials(java.lang.Class<T>);
+    method public <T> java.util.Set<T> getPublicCredentials(java.lang.Class<T>);
     method public static javax.security.auth.Subject getSubject(java.security.AccessControlContext);
     method public boolean isReadOnly();
     method public void setReadOnly();
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 239eab6..683a695 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -167,6 +167,13 @@
 
 package android.net {
 
+  public abstract class PskKeyManager {
+    ctor public PskKeyManager();
+    field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
+    field public static final int MAX_IDENTITY_LENGTH_BYTES = 128; // 0x80
+    field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100
+  }
+
   public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
     method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
   }
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index d6c0058..3759de2 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -26,7 +26,6 @@
 import android.app.ActivityManager;
 import android.app.ActivityManager.StackInfo;
 import android.app.ActivityManagerNative;
-import android.app.ActivityOptions;
 import android.app.IActivityContainer;
 import android.app.IActivityController;
 import android.app.IActivityManager;
@@ -46,7 +45,6 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.ParceledListSlice;
-import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
 import android.graphics.Rect;
@@ -55,10 +53,11 @@
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
 import android.os.SELinux;
 import android.os.ServiceManager;
+import android.os.ShellCallback;
 import android.os.ShellCommand;
-import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.text.TextUtils;
@@ -72,6 +71,7 @@
 
 import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStreamReader;
@@ -96,6 +96,7 @@
     // Amount we reduce the stack size by when testing a task re-size.
     private static final int STACK_BOUNDS_INSET = 10;
 
+    public static final String NO_CLASS_ERROR_CODE = "Error type 3";
     private IActivityManager mAm;
     private IPackageManager mPm;
 
@@ -198,7 +199,7 @@
                 "    --track-allocation: enable tracking of object allocations\n" +
                 "    --user <USER_ID> | current: Specify which user to run as; if not\n" +
                 "        specified then run as the current user.\n" +
-                "    --stack <STACK_ID>: Specify into which stack should the activity be put." +
+                "    --stack <STACK_ID>: Specify into which stack should the activity be put.\n" +
                 "\n" +
                 "am startservice: start a Service.  Options are:\n" +
                 "    --user <USER_ID> | current: Specify which user to run as; if not\n" +
@@ -385,17 +386,13 @@
         String op = nextArgRequired();
 
         if (op.equals("start")) {
-            runStart();
+            runAmCmd(getRawArgs());
         } else if (op.equals("startservice")) {
             runStartService();
         } else if (op.equals("stopservice")) {
             runStopService();
-        } else if (op.equals("force-stop")) {
-            runForceStop();
-        } else if (op.equals("kill")) {
-            runKill();
-        } else if (op.equals("kill-all")) {
-            runKillAll();
+        } else if (op.equals("force-stop") || op.equals("kill") || op.equals("kill-all")) {
+            runAmCmd(getRawArgs());
         } else if (op.equals("instrument")) {
             runInstrument();
         } else if (op.equals("trace-ipc")) {
@@ -475,6 +472,49 @@
         return userId;
     }
 
+    static final class MyShellCallback extends ShellCallback {
+        @Override public ParcelFileDescriptor onOpenOutputFile(String path, String seLinuxContext) {
+            File file = new File(path);
+            //System.err.println("Opening file: " + file.getAbsolutePath());
+            //Log.i("Am", "Opening file: " + file.getAbsolutePath());
+            final ParcelFileDescriptor fd;
+            try {
+                fd = ParcelFileDescriptor.open(file,
+                        ParcelFileDescriptor.MODE_CREATE |
+                        ParcelFileDescriptor.MODE_TRUNCATE |
+                        ParcelFileDescriptor.MODE_WRITE_ONLY);
+            } catch (FileNotFoundException e) {
+                String msg = "Unable to open file " + path + ": " + e;
+                System.err.println(msg);
+                throw new IllegalArgumentException(msg);
+            }
+            if (seLinuxContext != null) {
+                final String tcon = SELinux.getFileContext(file.getAbsolutePath());
+                if (!SELinux.checkSELinuxAccess(seLinuxContext, tcon, "file", "write")) {
+                    try {
+                        fd.close();
+                    } catch (IOException e) {
+                    }
+                    String msg = "System server has no access to file context " + tcon;
+                    System.err.println(msg + " (from path " + file.getAbsolutePath()
+                            + ", context " + seLinuxContext + ")");
+                    throw new IllegalArgumentException(msg);
+                }
+            }
+            return fd;
+        }
+    }
+
+    void runAmCmd(String[] args) throws AndroidException {
+        try {
+            mAm.asBinder().shellCommand(FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
+                    args, new MyShellCallback(), new ResultReceiver(null) { });
+        } catch (RemoteException e) {
+            System.err.println(NO_SYSTEM_ERROR_CODE);
+            throw new AndroidException("Can't call activity manager; is the system running?");
+        }
+    }
+
     private Intent makeIntent(int defUser) throws URISyntaxException {
         mStartFlags = 0;
         mWaitOption = false;
@@ -558,211 +598,6 @@
         }
     }
 
-    private void runStart() throws Exception {
-        Intent intent = makeIntent(UserHandle.USER_CURRENT);
-
-        if (mUserId == UserHandle.USER_ALL) {
-            System.err.println("Error: Can't start service with user 'all'");
-            return;
-        }
-
-        String mimeType = intent.getType();
-        if (mimeType == null && intent.getData() != null
-                && "content".equals(intent.getData().getScheme())) {
-            mimeType = mAm.getProviderMimeType(intent.getData(), mUserId);
-        }
-
-
-        do {
-            if (mStopOption) {
-                String packageName;
-                if (intent.getComponent() != null) {
-                    packageName = intent.getComponent().getPackageName();
-                } else {
-                    List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType, 0,
-                            mUserId).getList();
-                    if (activities == null || activities.size() <= 0) {
-                        System.err.println("Error: Intent does not match any activities: "
-                                + intent);
-                        return;
-                    } else if (activities.size() > 1) {
-                        System.err.println("Error: Intent matches multiple activities; can't stop: "
-                                + intent);
-                        return;
-                    }
-                    packageName = activities.get(0).activityInfo.packageName;
-                }
-                System.out.println("Stopping: " + packageName);
-                mAm.forceStopPackage(packageName, mUserId);
-                Thread.sleep(250);
-            }
-
-            System.out.println("Starting: " + intent);
-            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
-            ParcelFileDescriptor fd = null;
-            ProfilerInfo profilerInfo = null;
-
-            if (mProfileFile != null) {
-                try {
-                    fd = openForSystemServer(
-                            new File(mProfileFile),
-                            ParcelFileDescriptor.MODE_CREATE |
-                            ParcelFileDescriptor.MODE_TRUNCATE |
-                            ParcelFileDescriptor.MODE_WRITE_ONLY);
-                } catch (FileNotFoundException e) {
-                    System.err.println("Error: Unable to open file: " + mProfileFile);
-                    System.err.println("Consider using a file under /data/local/tmp/");
-                    return;
-                }
-                profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop);
-            }
-
-            IActivityManager.WaitResult result = null;
-            int res;
-            final long startTime = SystemClock.uptimeMillis();
-            ActivityOptions options = null;
-            if (mStackId != INVALID_STACK_ID) {
-                options = ActivityOptions.makeBasic();
-                options.setLaunchStackId(mStackId);
-            }
-            if (mWaitOption) {
-                result = mAm.startActivityAndWait(null, null, intent, mimeType,
-                        null, null, 0, mStartFlags, profilerInfo,
-                        options != null ? options.toBundle() : null, mUserId);
-                res = result.result;
-            } else {
-                res = mAm.startActivityAsUser(null, null, intent, mimeType,
-                        null, null, 0, mStartFlags, profilerInfo,
-                        options != null ? options.toBundle() : null, mUserId);
-            }
-            final long endTime = SystemClock.uptimeMillis();
-            PrintStream out = mWaitOption ? System.out : System.err;
-            boolean launched = false;
-            switch (res) {
-                case ActivityManager.START_SUCCESS:
-                    launched = true;
-                    break;
-                case ActivityManager.START_SWITCHES_CANCELED:
-                    launched = true;
-                    out.println(
-                            "Warning: Activity not started because the "
-                            + " current activity is being kept for the user.");
-                    break;
-                case ActivityManager.START_DELIVERED_TO_TOP:
-                    launched = true;
-                    out.println(
-                            "Warning: Activity not started, intent has "
-                            + "been delivered to currently running "
-                            + "top-most instance.");
-                    break;
-                case ActivityManager.START_RETURN_INTENT_TO_CALLER:
-                    launched = true;
-                    out.println(
-                            "Warning: Activity not started because intent "
-                            + "should be handled by the caller");
-                    break;
-                case ActivityManager.START_TASK_TO_FRONT:
-                    launched = true;
-                    out.println(
-                            "Warning: Activity not started, its current "
-                            + "task has been brought to the front");
-                    break;
-                case ActivityManager.START_INTENT_NOT_RESOLVED:
-                    out.println(
-                            "Error: Activity not started, unable to "
-                            + "resolve " + intent.toString());
-                    break;
-                case ActivityManager.START_CLASS_NOT_FOUND:
-                    out.println(NO_CLASS_ERROR_CODE);
-                    out.println("Error: Activity class " +
-                            intent.getComponent().toShortString()
-                            + " does not exist.");
-                    break;
-                case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
-                    out.println(
-                            "Error: Activity not started, you requested to "
-                            + "both forward and receive its result");
-                    break;
-                case ActivityManager.START_PERMISSION_DENIED:
-                    out.println(
-                            "Error: Activity not started, you do not "
-                            + "have permission to access it.");
-                    break;
-                case ActivityManager.START_NOT_VOICE_COMPATIBLE:
-                    out.println(
-                            "Error: Activity not started, voice control not allowed for: "
-                                    + intent);
-                    break;
-                case ActivityManager.START_NOT_CURRENT_USER_ACTIVITY:
-                    out.println(
-                            "Error: Not allowed to start background user activity"
-                            + " that shouldn't be displayed for all users.");
-                    break;
-                default:
-                    out.println(
-                            "Error: Activity not started, unknown error code " + res);
-                    break;
-            }
-            if (mWaitOption && launched) {
-                if (result == null) {
-                    result = new IActivityManager.WaitResult();
-                    result.who = intent.getComponent();
-                }
-                System.out.println("Status: " + (result.timeout ? "timeout" : "ok"));
-                if (result.who != null) {
-                    System.out.println("Activity: " + result.who.flattenToShortString());
-                }
-                if (result.thisTime >= 0) {
-                    System.out.println("ThisTime: " + result.thisTime);
-                }
-                if (result.totalTime >= 0) {
-                    System.out.println("TotalTime: " + result.totalTime);
-                }
-                System.out.println("WaitTime: " + (endTime-startTime));
-                System.out.println("Complete");
-            }
-            mRepeat--;
-            if (mRepeat > 0) {
-                mAm.unhandledBack();
-            }
-        } while (mRepeat > 0);
-    }
-
-    private void runForceStop() throws Exception {
-        int userId = UserHandle.USER_ALL;
-
-        String opt;
-        while ((opt=nextOption()) != null) {
-            if (opt.equals("--user")) {
-                userId = parseUserArg(nextArgRequired());
-            } else {
-                System.err.println("Error: Unknown option: " + opt);
-                return;
-            }
-        }
-        mAm.forceStopPackage(nextArgRequired(), userId);
-    }
-
-    private void runKill() throws Exception {
-        int userId = UserHandle.USER_ALL;
-
-        String opt;
-        while ((opt=nextOption()) != null) {
-            if (opt.equals("--user")) {
-                userId = parseUserArg(nextArgRequired());
-            } else {
-                System.err.println("Error: Unknown option: " + opt);
-                return;
-            }
-        }
-        mAm.killBackgroundProcesses(nextArgRequired(), userId);
-    }
-
-    private void runKillAll() throws Exception {
-        mAm.killAllBackgroundProcesses();
-    }
-
     private void sendBroadcast() throws Exception {
         Intent intent = makeIntent(UserHandle.USER_CURRENT);
         IntentReceiver receiver = new IntentReceiver();
@@ -2523,8 +2358,7 @@
                 return;
         }
         if (!mAm.setProcessMemoryTrimLevel(proc, userId, level)) {
-            System.err.println("Error: Failure to set the level - probably Unknown Process: " +
-                               proc);
+            System.err.println("Unknown error: failed to set trim level");
         }
     }
 
diff --git a/cmds/input/src/com/android/commands/input/Input.java b/cmds/input/src/com/android/commands/input/Input.java
index 754d3f5..9ee11f8 100644
--- a/cmds/input/src/com/android/commands/input/Input.java
+++ b/cmds/input/src/com/android/commands/input/Input.java
@@ -23,6 +23,7 @@
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
+import android.view.ViewConfiguration;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -118,6 +119,19 @@
                                 duration);
                         return;
                 }
+            } else if (command.equals("draganddrop")) {
+                int duration = -1;
+                inputSource = getSource(inputSource, InputDevice.SOURCE_TOUCHSCREEN);
+                switch (length) {
+                    case 6:
+                        duration = Integer.parseInt(args[index+5]);
+                    case 5:
+                        sendDragAndDrop(inputSource,
+                                Float.parseFloat(args[index+1]), Float.parseFloat(args[index+2]),
+                                Float.parseFloat(args[index+3]), Float.parseFloat(args[index+4]),
+                                duration);
+                        return;
+                }
             } else if (command.equals("press")) {
                 inputSource = getSource(inputSource, InputDevice.SOURCE_TRACKBALL);
                 if (length == 1) {
@@ -216,6 +230,31 @@
         injectMotionEvent(inputSource, MotionEvent.ACTION_UP, now, x2, y2, 0.0f);
     }
 
+    private void sendDragAndDrop(int inputSource, float x1, float y1, float x2, float y2,
+            int dragDuration) {
+        if (dragDuration < 0) {
+            dragDuration = 300;
+        }
+        long now = SystemClock.uptimeMillis();
+        injectMotionEvent(inputSource, MotionEvent.ACTION_DOWN, now, x1, y1, 1.0f);
+        try {
+            Thread.sleep(ViewConfiguration.getLongPressTimeout());
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+        now = SystemClock.uptimeMillis();
+        long startTime = now;
+        long endTime = startTime + dragDuration;
+        while (now < endTime) {
+            long elapsedTime = now - startTime;
+            float alpha = (float) elapsedTime / dragDuration;
+            injectMotionEvent(inputSource, MotionEvent.ACTION_MOVE, now, lerp(x1, x2, alpha),
+                    lerp(y1, y2, alpha), 1.0f);
+            now = SystemClock.uptimeMillis();
+        }
+        injectMotionEvent(inputSource, MotionEvent.ACTION_UP, now, x2, y2, 0.0f);
+    }
+
     /**
      * Sends a simple zero-pressure move event.
      *
@@ -294,6 +333,8 @@
         System.err.println("      tap <x> <y> (Default: touchscreen)");
         System.err.println("      swipe <x1> <y1> <x2> <y2> [duration(ms)]"
                 + " (Default: touchscreen)");
+        System.err.println("      draganddrop <x1> <y1> <x2> <y2> [duration(ms)]"
+                + " (Default: touchscreen)");
         System.err.println("      press (Default: trackball)");
         System.err.println("      roll <dx> <dy> (Default: trackball)");
     }
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 32a8088..ace4e32 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -49,9 +49,12 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IUserManager;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
+import android.os.SELinux;
 import android.os.ServiceManager;
+import android.os.ShellCallback;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -68,6 +71,7 @@
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -284,13 +288,45 @@
         }
     }
 
+    static final class MyShellCallback extends ShellCallback {
+        @Override public ParcelFileDescriptor onOpenOutputFile(String path, String seLinuxContext) {
+            File file = new File(path);
+            final ParcelFileDescriptor fd;
+            try {
+                fd = ParcelFileDescriptor.open(file,
+                            ParcelFileDescriptor.MODE_CREATE |
+                            ParcelFileDescriptor.MODE_TRUNCATE |
+                            ParcelFileDescriptor.MODE_WRITE_ONLY);
+            } catch (FileNotFoundException e) {
+                String msg = "Unable to open file " + path + ": " + e;
+                System.err.println(msg);
+                throw new IllegalArgumentException(msg);
+            }
+            if (seLinuxContext != null) {
+                final String tcon = SELinux.getFileContext(file.getAbsolutePath());
+                if (!SELinux.checkSELinuxAccess(seLinuxContext, tcon, "file", "write")) {
+                    try {
+                        fd.close();
+                    } catch (IOException e) {
+                    }
+                    String msg = "System server has no access to file context " + tcon;
+                    System.err.println(msg + " (from path " + file.getAbsolutePath()
+                            + ", context " + seLinuxContext + ")");
+                    throw new IllegalArgumentException(msg);
+                }
+            }
+            return fd;
+        }
+    }
+
     private int runShellCommand(String serviceName, String[] args) {
         final HandlerThread handlerThread = new HandlerThread("results");
         handlerThread.start();
         try {
             ServiceManager.getService(serviceName).shellCommand(
                     FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
-                    args, new ResultReceiver(new Handler(handlerThread.getLooper())));
+                    args, new MyShellCallback(),
+                    new ResultReceiver(new Handler(handlerThread.getLooper())));
             return 0;
         } catch (RemoteException e) {
             e.printStackTrace();
diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java
index 6c16e32..b6e85f1 100644
--- a/core/java/android/accounts/Account.java
+++ b/core/java/android/accounts/Account.java
@@ -18,9 +18,11 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.Context;
 import android.os.Parcelable;
 import android.os.Parcel;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
@@ -41,7 +43,7 @@
 
     public final String name;
     public final String type;
-    private final @Nullable IAccountAccessTracker mAccessTracker;
+    private final @Nullable String accessId;
 
     public boolean equals(Object o) {
         if (o == this) return true;
@@ -64,14 +66,14 @@
     /**
      * @hide
      */
-    public Account(@NonNull Account other, @Nullable IAccountAccessTracker accessTracker) {
-        this(other.name, other.type, accessTracker);
+    public Account(@NonNull Account other, @NonNull String accessId) {
+        this(other.name, other.type, accessId);
     }
 
     /**
      * @hide
      */
-    public Account(String name, String type, IAccountAccessTracker accessTracker) {
+    public Account(String name, String type, String accessId) {
         if (TextUtils.isEmpty(name)) {
             throw new IllegalArgumentException("the name must not be empty: " + name);
         }
@@ -80,18 +82,20 @@
         }
         this.name = name;
         this.type = type;
-        this.mAccessTracker = accessTracker;
+        this.accessId = accessId;
     }
 
     public Account(Parcel in) {
         this.name = in.readString();
         this.type = in.readString();
-        this.mAccessTracker = IAccountAccessTracker.Stub.asInterface(in.readStrongBinder());
-        if (mAccessTracker != null) {
+        this.accessId = in.readString();
+        if (accessId != null) {
             synchronized (sAccessedAccounts) {
                 if (sAccessedAccounts.add(this)) {
                     try {
-                        mAccessTracker.onAccountAccessed();
+                        IAccountManager accountManager = IAccountManager.Stub.asInterface(
+                                ServiceManager.getService(Context.ACCOUNT_SERVICE));
+                        accountManager.onAccountAccessed(accessId);
                     } catch (RemoteException e) {
                         Log.e(TAG, "Error noting account access", e);
                     }
@@ -101,8 +105,8 @@
     }
 
     /** @hide */
-    public IAccountAccessTracker getAccessTracker() {
-        return mAccessTracker;
+    public String getAccessId() {
+        return accessId;
     }
 
     public int describeContents() {
@@ -112,7 +116,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(name);
         dest.writeString(type);
-        dest.writeStrongInterface(mAccessTracker);
+        dest.writeString(accessId);
     }
 
     public static final Creator<Account> CREATOR = new Creator<Account>() {
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 1eb63e0..1ad43fa 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -179,12 +179,12 @@
     public static final String KEY_ACCOUNT_TYPE = "accountType";
 
     /**
-     * Bundle key used for the {@link IAccountAccessTracker} account access tracker
-     * used for noting the account was accessed when unmarshalled from a parcel.
+     * Bundle key used for the account access id used for noting the
+     * account was accessed when unmarshaled from a parcel.
      *
      * @hide
      */
-    public static final String KEY_ACCOUNT_ACCESS_TRACKER = "accountAccessTracker";
+    public static final String KEY_ACCOUNT_ACCESS_ID = "accountAccessId";
 
     /**
      * Bundle key used for the auth token value in results
@@ -926,9 +926,8 @@
             public Account bundleToResult(Bundle bundle) throws AuthenticatorException {
                 String name = bundle.getString(KEY_ACCOUNT_NAME);
                 String type = bundle.getString(KEY_ACCOUNT_TYPE);
-                IAccountAccessTracker tracker = IAccountAccessTracker.Stub.asInterface(
-                        bundle.getBinder(KEY_ACCOUNT_ACCESS_TRACKER));
-                return new Account(name, type, tracker);
+                String accessId = bundle.getString(KEY_ACCOUNT_ACCESS_ID);
+                return new Account(name, type, accessId);
             }
         }.start();
     }
@@ -2388,7 +2387,7 @@
                                     result.putString(KEY_ACCOUNT_NAME, null);
                                     result.putString(KEY_ACCOUNT_TYPE, null);
                                     result.putString(KEY_AUTHTOKEN, null);
-                                    result.putBinder(KEY_ACCOUNT_ACCESS_TRACKER, null);
+                                    result.putBinder(KEY_ACCOUNT_ACCESS_ID, null);
                                     try {
                                         mResponse.onResult(result);
                                     } catch (RemoteException e) {
@@ -2415,9 +2414,7 @@
                                             Account account = new Account(
                                                     value.getString(KEY_ACCOUNT_NAME),
                                                     value.getString(KEY_ACCOUNT_TYPE),
-                                                    IAccountAccessTracker.Stub.asInterface(
-                                                            value.getBinder(
-                                                                    KEY_ACCOUNT_ACCESS_TRACKER)));
+                                                    value.getString(KEY_ACCOUNT_ACCESS_ID));
                                             mFuture = getAuthToken(account, mAuthTokenType,
                                                     mLoginOptions,  mActivity, mMyCallback,
                                                     mHandler);
@@ -2467,9 +2464,8 @@
                         setException(new AuthenticatorException("account not in result"));
                         return;
                     }
-                    final IAccountAccessTracker tracker = IAccountAccessTracker.Stub.asInterface(
-                            result.getBinder(KEY_ACCOUNT_ACCESS_TRACKER));
-                    final Account account = new Account(accountName, accountType, tracker);
+                    final String accessId = result.getString(KEY_ACCOUNT_ACCESS_ID);
+                    final Account account = new Account(accountName, accountType, accessId);
                     mNumAccounts = 1;
                     getAuthToken(account, mAuthTokenType, null /* options */, mActivity,
                             mMyCallback, mHandler);
diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
index 133df2b..aed7a36 100644
--- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java
+++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
@@ -399,7 +399,7 @@
      * useless.
      */
     private void setNonLabelThemeAndCallSuperCreate(Bundle savedInstanceState) {
-        setTheme(R.style.Theme_Material_Light_Dialog_NoActionBar);
+        setTheme(R.style.Theme_DeviceDefault_Light_Dialog_NoActionBar);
         super.onCreate(savedInstanceState);
     }
 
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index e5183b2..fc10990 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -124,4 +124,6 @@
     /* Crate an intent to request account access for package and a given user id */
     IntentSender createRequestAccountAccessIntentSenderAsUser(in Account account,
         String packageName, in UserHandle userHandle);
+
+    void onAccountAccessed(String token);
 }
diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java
index cdd72be..5a23fdd 100644
--- a/core/java/android/animation/LayoutTransition.java
+++ b/core/java/android/animation/LayoutTransition.java
@@ -62,7 +62,11 @@
  * layout will run (closing the gap created in the layout when the item was removed). If this
  * default choreography behavior is not desired, the {@link #setDuration(int, long)} and
  * {@link #setStartDelay(int, long)} of any or all of the animations can be changed as
- * appropriate.</p>
+ * appropriate. Keep in mind, however, that if you start an APPEARING animation before a
+ * DISAPPEARING animation is completed, the DISAPPEARING animation stops, and any effects from
+ * the DISAPPEARING animation are reverted. If you instead start a DISAPPEARING animation
+ * before an APPEARING animation is completed, a similar set of effects occurs for the
+ * APPEARING animation.</p>
  *
  * <p>The animations specified for the transition, both the defaults and any custom animations
  * set on the transition object, are templates only. That is, these animations exist to hold the
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 9a2aa30..0c21c4f 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -977,8 +977,9 @@
     @Override
     void animateValue(float fraction) {
         final Object target = getTarget();
-        if (target == null) {
-            // We lost the target reference, cancel and clean up.
+        if (mTarget != null && target == null) {
+            // We lost the target reference, cancel and clean up. Note: we allow null target if the
+            /// target has never been set.
             cancel();
             return;
         }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index a0408c9..3a8b6c7 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -108,6 +108,7 @@
 import android.system.Os;
 import android.system.OsConstants;
 import android.system.ErrnoException;
+import android.webkit.WebView;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IVoiceInteractor;
@@ -1046,10 +1047,21 @@
             long dalvikMax = runtime.totalMemory() / 1024;
             long dalvikFree = runtime.freeMemory() / 1024;
             long dalvikAllocated = dalvikMax - dalvikFree;
+
+            Class[] classesToCount = new Class[] {
+                    ContextImpl.class,
+                    Activity.class,
+                    WebView.class,
+                    OpenSSLSocketImpl.class
+            };
+            long[] instanceCounts = VMDebug.countInstancesOfClasses(classesToCount, true);
+            long appContextInstanceCount = instanceCounts[0];
+            long activityInstanceCount = instanceCounts[1];
+            long webviewInstanceCount = instanceCounts[2];
+            long openSslSocketCount = instanceCounts[3];
+
             long viewInstanceCount = ViewDebug.getViewInstanceCount();
             long viewRootInstanceCount = ViewDebug.getViewRootImplCount();
-            long appContextInstanceCount = Debug.countInstancesOfClass(ContextImpl.class);
-            long activityInstanceCount = Debug.countInstancesOfClass(Activity.class);
             int globalAssetCount = AssetManager.getGlobalAssetCount();
             int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
             int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
@@ -1057,7 +1069,6 @@
             int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
             long parcelSize = Parcel.getGlobalAllocSize();
             long parcelCount = Parcel.getGlobalAllocCount();
-            long openSslSocketCount = Debug.countInstancesOfClass(OpenSSLSocketImpl.class);
             SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo();
 
             dumpMemInfoTable(pw, memInfo, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly,
@@ -1120,6 +1131,7 @@
                     "Parcel count:", parcelCount);
             printRow(pw, TWO_COUNT_COLUMNS, "Death Recipients:", binderDeathObjectCount,
                     "OpenSSL Sockets:", openSslSocketCount);
+            printRow(pw, ONE_COUNT_COLUMN, "WebViews:", webviewInstanceCount);
 
             // SQLite mem info
             pw.println(" ");
@@ -3809,7 +3821,7 @@
      * than our client -- for the server, stop means to save state and give
      * it the result when it is done, but the window may still be visible.
      * For the client, we want to call onStop()/onStart() to indicate when
-     * the activity's UI visibillity changes.
+     * the activity's UI visibility changes.
      */
     private void performStopActivityInner(ActivityClientRecord r,
             StopInfo info, boolean keepShown, boolean saveState, String reason) {
@@ -3983,6 +3995,9 @@
         mSomeActivitiesChanged = true;
     }
 
+    // TODO: This method should be changed to use {@link #performStopActivityInner} to perform to
+    // stop operation on the activity to reduce code duplication and the chance of fixing a bug in
+    // one place and missing the other.
     private void handleSleeping(IBinder token, boolean sleeping) {
         ActivityClientRecord r = mActivities.get(token);
 
@@ -3993,6 +4008,10 @@
 
         if (sleeping) {
             if (!r.stopped && !r.isPreHoneycomb()) {
+                if (!r.activity.mFinished && r.state == null) {
+                    callCallActivityOnSaveInstanceState(r);
+                }
+
                 try {
                     // Now we are idle.
                     r.activity.performStop(false /*preserveWindow*/);
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index aef1d0c..60046b5 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -15,6 +15,7 @@
  */
 package android.app;
 
+import android.content.Intent;
 import android.os.Bundle;
 import android.os.ResultReceiver;
 import android.transition.Transition;
@@ -166,7 +167,11 @@
                 restoreExitedViews();
                 int result = mEnterActivityOptions.getResultCode();
                 if (result != 0) {
-                    activity.onActivityReenter(result, mEnterActivityOptions.getResultData());
+                    Intent intent = mEnterActivityOptions.getResultData();
+                    if (intent != null) {
+                        intent.setExtrasClassLoader(activity.getClassLoader());
+                    }
+                    activity.onActivityReenter(result, intent);
                 }
             }
         }
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 440ddd6..191cc49 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -311,6 +311,9 @@
     /** Access APIs for SIP calling over VOIP or WiFi */
     public static final String OPSTR_USE_SIP
             = "android:use_sip";
+    /** Access APIs for diverting outgoing calls */
+    public static final String OPSTR_PROCESS_OUTGOING_CALLS
+            = "android:process_outgoing_calls";
     /** Use the fingerprint API. */
     public static final String OPSTR_USE_FINGERPRINT
             = "android:use_fingerprint";
@@ -510,7 +513,7 @@
             OPSTR_READ_PHONE_STATE,
             OPSTR_ADD_VOICEMAIL,
             OPSTR_USE_SIP,
-            null,
+            OPSTR_PROCESS_OUTGOING_CALLS,
             OPSTR_USE_FINGERPRINT,
             OPSTR_BODY_SENSORS,
             OPSTR_READ_CELL_BROADCASTS,
diff --git a/core/java/android/app/FragmentHostCallback.java b/core/java/android/app/FragmentHostCallback.java
index b6aad3b..d869168 100644
--- a/core/java/android/app/FragmentHostCallback.java
+++ b/core/java/android/app/FragmentHostCallback.java
@@ -340,8 +340,10 @@
     }
 
     void restoreLoaderNonConfig(ArrayMap<String, LoaderManager> loaderManagers) {
-        for (int i = 0, N = loaderManagers.size(); i < N; i++) {
-            ((LoaderManagerImpl) loaderManagers.valueAt(i)).updateHostController(this);
+        if (loaderManagers != null) {
+            for (int i = 0, N = loaderManagers.size(); i < N; i++) {
+                ((LoaderManagerImpl) loaderManagers.valueAt(i)).updateHostController(this);
+            }
         }
         mAllLoaderManagers = loaderManagers;
     }
diff --git a/core/java/android/app/IUserSwitchObserver.aidl b/core/java/android/app/IUserSwitchObserver.aidl
index caee14f..234da8f 100644
--- a/core/java/android/app/IUserSwitchObserver.aidl
+++ b/core/java/android/app/IUserSwitchObserver.aidl
@@ -23,4 +23,5 @@
     void onUserSwitching(int newUserId, IRemoteCallback reply);
     void onUserSwitchComplete(int newUserId);
     void onForegroundProfileSwitch(int newProfileId);
+    void onLockedBootComplete(int newUserId);
 }
diff --git a/core/java/android/app/SynchronousUserSwitchObserver.java b/core/java/android/app/SynchronousUserSwitchObserver.java
index 6d929f9..3a73888 100644
--- a/core/java/android/app/SynchronousUserSwitchObserver.java
+++ b/core/java/android/app/SynchronousUserSwitchObserver.java
@@ -25,7 +25,7 @@
  *
  * @hide
  */
-public abstract class SynchronousUserSwitchObserver extends IUserSwitchObserver.Stub {
+public abstract class SynchronousUserSwitchObserver extends UserSwitchObserver {
     /**
      * Calls {@link #onUserSwitching(int)} and notifies {@code reply} by calling
      * {@link IRemoteCallback#sendResult(Bundle)}.
diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java
index aca0763..3f467a0 100644
--- a/core/java/android/app/TimePickerDialog.java
+++ b/core/java/android/app/TimePickerDialog.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.TestApi;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
@@ -91,6 +92,12 @@
 
     /**
      * Creates a new time picker dialog with the specified theme.
+     * <p>
+     * The theme is overlaid on top of the theme of the parent {@code context}.
+     * If {@code themeResId} is 0, the dialog will be inflated using the theme
+     * specified by the
+     * {@link android.R.attr#timePickerDialogTheme android:timePickerDialogTheme}
+     * attribute on the parent {@code context}'s theme.
      *
      * @param context the parent context
      * @param themeResId the resource ID of the theme to apply to this dialog
@@ -109,11 +116,6 @@
         mIs24HourView = is24HourView;
 
         final Context themeContext = getContext();
-
-
-        final TypedValue outValue = new TypedValue();
-        context.getTheme().resolveAttribute(R.attr.timePickerDialogTheme, outValue, true);
-
         final LayoutInflater inflater = LayoutInflater.from(themeContext);
         final View view = inflater.inflate(R.layout.time_picker_dialog, null);
         setView(view);
@@ -128,6 +130,15 @@
         mTimePicker.setOnTimeChangedListener(this);
     }
 
+    /**
+     * @return the time picker displayed in the dialog
+     * @hide For testing only.
+     */
+    @TestApi
+    public TimePicker getTimePicker() {
+        return mTimePicker;
+    }
+
     @Override
     public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
         /* do nothing */
diff --git a/core/java/android/app/UserSwitchObserver.java b/core/java/android/app/UserSwitchObserver.java
new file mode 100644
index 0000000..c0f7a4c
--- /dev/null
+++ b/core/java/android/app/UserSwitchObserver.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.app;
+
+import android.os.IRemoteCallback;
+import android.os.RemoteException;
+
+/**
+ * @hide
+ */
+public class UserSwitchObserver extends IUserSwitchObserver.Stub {
+    @Override
+    public void onUserSwitching(int newUserId, IRemoteCallback reply) throws RemoteException {
+        if (reply != null) {
+            reply.sendResult(null);
+        }
+    }
+
+    @Override
+    public void onUserSwitchComplete(int newUserId) throws RemoteException {}
+
+    @Override
+    public void onForegroundProfileSwitch(int newProfileId) throws RemoteException {}
+
+    @Override
+    public void onLockedBootComplete(int newUserId) throws RemoteException {}
+}
\ No newline at end of file
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index a7ad619..aa0eaae 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1393,7 +1393,8 @@
      */
     @SystemApi
     public void clearWallpaper() {
-        clearWallpaper(FLAG_SYSTEM | FLAG_LOCK, mContext.getUserId());
+        clearWallpaper(FLAG_LOCK, mContext.getUserId());
+        clearWallpaper(FLAG_SYSTEM, mContext.getUserId());
     }
 
     /**
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 540678e..a207a52 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -5498,6 +5498,7 @@
 
     /**
      * Called by profile or device owners to set the master volume mute on or off.
+     * This has no effect when set on a managed profile.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param on {@code true} to mute master volume, {@code false} to turn mute off.
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 7fcca09..80bc136 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -128,6 +128,14 @@
     @SystemApi
     public static final int ERROR_AGENT_FAILURE = BackupTransport.AGENT_ERROR;
 
+    /**
+     * Intent extra when any subsidiary backup-related UI is launched from Settings:  does
+     * device policy or configuration permit backup operations to run at all?
+     *
+     * @hide
+     */
+    public static final String EXTRA_BACKUP_SERVICES_AVAILABLE = "backup_services_available";
+
     private Context mContext;
     private static IBackupManager sService;
 
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 6d6dfeb..cd5eff2 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1596,7 +1596,7 @@
                 // BLE is not supported
                 return null;
             }
-            BluetoothGatt gatt = new BluetoothGatt(context, iGatt, this, transport);
+            BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport);
             gatt.connect(autoConnect, callback);
             return gatt;
         } catch (RemoteException e) {Log.e(TAG, "", e);}
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 17145f2..2bb9012 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -41,7 +41,6 @@
     private static final boolean DBG = true;
     private static final boolean VDBG = false;
 
-    private final Context mContext;
     private IBluetoothGatt mService;
     private BluetoothGattCallback mCallback;
     private int mClientIf;
@@ -492,9 +491,8 @@
             }
         };
 
-    /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device,
+    /*package*/ BluetoothGatt(IBluetoothGatt iGatt, BluetoothDevice device,
                                 int transport) {
-        mContext = context;
         mService = iGatt;
         mDevice = device;
         mTransport = transport;
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index c2bcbb2..5ffceba 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -44,7 +44,6 @@
     private static final boolean DBG = true;
     private static final boolean VDBG = false;
 
-    private final Context mContext;
     private BluetoothAdapter mAdapter;
     private IBluetoothGatt mService;
     private BluetoothGattServerCallback mCallback;
@@ -298,8 +297,7 @@
     /**
      * Create a BluetoothGattServer proxy object.
      */
-    /*package*/ BluetoothGattServer(Context context, IBluetoothGatt iGatt, int transport) {
-        mContext = context;
+    /*package*/ BluetoothGattServer(IBluetoothGatt iGatt, int transport) {
         mService = iGatt;
         mAdapter = BluetoothAdapter.getDefaultAdapter();
         mCallback = null;
diff --git a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
index 15a9101..1717a1e 100644
--- a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
+++ b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
@@ -68,7 +68,9 @@
     public boolean equals(Object o) {
         if (o instanceof BluetoothHealthAppConfiguration) {
             BluetoothHealthAppConfiguration config = (BluetoothHealthAppConfiguration) o;
-            // config.getName() can never be NULL
+
+            if (mName == null) return false;
+
             return mName.equals(config.getName()) &&
                     mDataType == config.getDataType() &&
                     mRole == config.getRole() &&
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index 00058a9..29283e7 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -236,7 +236,7 @@
                 Log.e(TAG, "Fail to get GATT Server connection");
                 return null;
             }
-            BluetoothGattServer mGattServer = new BluetoothGattServer(context, iGatt,transport);
+            BluetoothGattServer mGattServer = new BluetoothGattServer(iGatt,transport);
             Boolean regStatus = mGattServer.registerCallback(callback);
             return regStatus? mGattServer : null;
         } catch (RemoteException e) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 457866b..2f2ffc9 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1130,7 +1130,9 @@
      * <strong>Note: you should not <em>rely</em> on the system deleting these
      * files for you; you should always have a reasonable maximum, such as 1 MB,
      * for the amount of space you consume with cache files, and prune those
-     * files when exceeding that space.</strong>
+     * files when exceeding that space.</strong> If your app requires a larger
+     * cache (larger than 1 MB), you should use {@link #getExternalCacheDir()}
+     * instead.
      * <p>
      * The returned path may change over time if the calling app is moved to an
      * adopted storage device, so only relative paths should be persisted.
@@ -1142,6 +1144,7 @@
      * @see #openFileOutput
      * @see #getFileStreamPath
      * @see #getDir
+     * @see #getExternalCacheDir
      */
     public abstract File getCacheDir();
 
@@ -1190,7 +1193,7 @@
      * </ul>
      * <p>
      * If a shared storage device is emulated (as determined by
-     * {@link Environment#isExternalStorageEmulated(File)}), it's contents are
+     * {@link Environment#isExternalStorageEmulated(File)}), its contents are
      * backed by a private user data partition, which means there is little
      * benefit to storing data here instead of the private directory returned by
      * {@link #getCacheDir()}.
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 70010b2..74f48c6 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -128,7 +128,7 @@
  *     a list of people, which the user can browse through.  This example is a
  *     typical top-level entry into the Contacts application, showing you the
  *     list of people. Selecting a particular person to view would result in a
- *     new intent { <b>{@link #ACTION_VIEW} <i>content://contacts/N</i></b> }
+ *     new intent { <b>{@link #ACTION_VIEW} <i>content://contacts/people/N</i></b> }
  *     being used to start an activity to display that person.</p>
  *   </li>
  * </ul>
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index d07b5457..f5a79c8 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -124,7 +124,7 @@
  * <em>Note that authority matching here is <b>case sensitive</b>, unlike
  * formal RFC host names!</em>  You should thus always use lower case letters
  * for your authority.
- * 
+ *
  * <p><strong>Data Path</strong> matches if any of the given values match the
  * Intent's data path <em>and</em> both a scheme and authority in the filter
  * has matched against the Intent, <em>or</em> no paths were supplied in the
@@ -359,8 +359,8 @@
      * the {@link MalformedMimeTypeException} exception that the constructor
      * can call and turns it into a runtime exception.
      *
-     * @param action The action to match, i.e. Intent.ACTION_VIEW.
-     * @param dataType The type to match, i.e. "vnd.android.cursor.dir/person".
+     * @param action The action to match, such as Intent.ACTION_VIEW.
+     * @param dataType The type to match, such as "vnd.android.cursor.dir/person".
      *
      * @return A new IntentFilter for the given action and type.
      *
@@ -387,7 +387,7 @@
      * no data characteristics are subsequently specified, then the
      * filter will only match intents that contain no data.
      *
-     * @param action The action to match, i.e. Intent.ACTION_MAIN.
+     * @param action The action to match, such as Intent.ACTION_MAIN.
      */
     public IntentFilter(String action) {
         mPriority = 0;
@@ -407,8 +407,8 @@
      * <p>Throws {@link MalformedMimeTypeException} if the given MIME type is
      * not syntactically correct.
      *
-     * @param action The action to match, i.e. Intent.ACTION_VIEW.
-     * @param dataType The type to match, i.e. "vnd.android.cursor.dir/person".
+     * @param action The action to match, such as Intent.ACTION_VIEW.
+     * @param dataType The type to match, such as "vnd.android.cursor.dir/person".
      *
      */
     public IntentFilter(String action, String dataType)
@@ -652,7 +652,7 @@
      * in the filter, then an Intent's action must be one of those values for
      * it to match.  If no actions are included, the Intent action is ignored.
      *
-     * @param action Name of the action to match, i.e. Intent.ACTION_VIEW.
+     * @param action Name of the action to match, such as Intent.ACTION_VIEW.
      */
     public final void addAction(String action) {
         if (!mActions.contains(action)) {
@@ -721,7 +721,7 @@
      * <p>Throws {@link MalformedMimeTypeException} if the given MIME type is
      * not syntactically correct.
      *
-     * @param type Name of the data type to match, i.e. "vnd.android.cursor.dir/person".
+     * @param type Name of the data type to match, such as "vnd.android.cursor.dir/person".
      *
      * @see #matchData
      */
@@ -798,7 +798,7 @@
      * and any schemes you receive from outside of Android should be
      * converted to lower case before supplying them here.</em></p>
      *
-     * @param scheme Name of the scheme to match, i.e. "http".
+     * @param scheme Name of the scheme to match, such as "http".
      *
      * @see #matchData
      */
@@ -909,7 +909,7 @@
          * Determine whether this AuthorityEntry matches the given data Uri.
          * <em>Note that this comparison is case-sensitive, unlike formal
          * RFC host names.  You thus should always normalize to lower-case.</em>
-         * 
+         *
          * @param data The Uri to match.
          * @return Returns either {@link IntentFilter#NO_MATCH_DATA},
          * {@link IntentFilter#MATCH_CATEGORY_PORT}, or
@@ -1364,7 +1364,7 @@
      * filter has no impact on matching unless that category is specified in
      * the intent.
      *
-     * @param category Name of category to match, i.e. Intent.CATEGORY_EMBED.
+     * @param category Name of category to match, such as Intent.CATEGORY_EMBED.
      */
     public final void addCategory(String category) {
         if (mCategories == null) mCategories = new ArrayList<String>();
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a6f6220..26e0346 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5428,7 +5428,7 @@
      * {@link #COMPONENT_ENABLED_STATE_DISABLED}, or
      * {@link #COMPONENT_ENABLED_STATE_DEFAULT}.  The last one means the
      * application's enabled state is based on the original information in
-     * the manifest as found in {@link ComponentInfo}.
+     * the manifest as found in {@link ApplicationInfo}.
      * @throws IllegalArgumentException if the named package does not exist.
      */
     public abstract int getApplicationEnabledSetting(String packageName);
diff --git a/core/java/android/database/CursorJoiner.java b/core/java/android/database/CursorJoiner.java
index e3c2988..a95263b 100644
--- a/core/java/android/database/CursorJoiner.java
+++ b/core/java/android/database/CursorJoiner.java
@@ -27,7 +27,7 @@
  *
  * <pre>
  * CursorJoiner joiner = new CursorJoiner(cursorA, keyColumnsofA, cursorB, keyColumnsofB);
- * for (CursorJointer.Result joinerResult : joiner) {
+ * for (CursorJoiner.Result joinerResult : joiner) {
  *     switch (joinerResult) {
  *         case LEFT:
  *             // handle case where a row in cursorA is unique
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 0f64b92..8e17832 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -1371,6 +1371,7 @@
 
     /**
      * Convenience method for replacing a row in the database.
+     * Inserts a new row if a row does not already exist.
      *
      * @param table the table in which to replace the row
      * @param nullColumnHack optional; may be <code>null</code>.
@@ -1381,7 +1382,7 @@
      *            provides the name of nullable column name to explicitly insert a NULL into
      *            in the case where your <code>initialValues</code> is empty.
      * @param initialValues this map contains the initial column values for
-     *   the row.
+     *   the row. The keys should be the column names and the values the column values.
      * @return the row ID of the newly inserted row, or -1 if an error occurred
      */
     public long replace(String table, String nullColumnHack, ContentValues initialValues) {
@@ -1396,6 +1397,7 @@
 
     /**
      * Convenience method for replacing a row in the database.
+     * Inserts a new row if a row does not already exist.
      *
      * @param table the table in which to replace the row
      * @param nullColumnHack optional; may be <code>null</code>.
@@ -1406,7 +1408,7 @@
      *            provides the name of nullable column name to explicitly insert a NULL into
      *            in the case where your <code>initialValues</code> is empty.
      * @param initialValues this map contains the initial column values for
-     *   the row. The key
+     *   the row. The keys should be the column names and the values the column values.
      * @throws SQLException
      * @return the row ID of the newly inserted row, or -1 if an error occurred
      */
@@ -1740,7 +1742,7 @@
      * Returns true if the new version code is greater than the current database version.
      *
      * @param newVersion The new version code.
-     * @return True if the new version code is greater than the current database version. 
+     * @return True if the new version code is greater than the current database version.
      */
     public boolean needUpgrade(int newVersion) {
         return newVersion > getVersion();
diff --git a/core/java/android/database/sqlite/package.html b/core/java/android/database/sqlite/package.html
index ceed171..864a9bb 100644
--- a/core/java/android/database/sqlite/package.html
+++ b/core/java/android/database/sqlite/package.html
@@ -6,15 +6,44 @@
 Applications use these classes to manage private databases. If creating a
 content provider, you will probably have to use these classes to create and
 manage your own database to store content. See <a
-href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a> to learn
-the conventions for implementing a content provider. See the
-NotePadProvider class in the NotePad sample application in the SDK for an
-example of a content provider. Android ships with SQLite version 3.4.0
-<p>If you are working with data sent to you by a provider, you will not use
-these SQLite classes, but instead use the generic {@link android.database}
-classes.
-<p>Android ships with the sqlite3 database tool in the <code>tools/</code>
-folder. You can use this tool to browse or run SQL commands on the device. Run by
-typing <code>sqlite3</code> in a shell window.
+href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
+to learn the conventions for implementing a content provider. If you are working
+with data sent to you by a provider, you do not use these SQLite classes, but
+instead use the generic {@link android.database} classes.
+
+<p>The Android SDK and Android emulators both include the
+<a href="{@docRoot}studio/command-line/sqlite3.html">sqlite3</a> command-line
+database tool. On your development machine, run the tool from the
+<code>platform-tools/</code> folder of your SDK. On the emulator, run the tool
+with adb shell, for example, <code>adb -e shell sqlite3</code>.
+
+<p>The version of SQLite depends on the version of Android. See the following table:
+<table style="width:auto;">
+  <tr><th>Android API</th><th>SQLite Version</th></tr>
+  <tr><td>API 24</td><td>3.9</td></tr>
+  <tr><td>API 21</td><td>3.8</td></tr>
+  <tr><td>API 11</td><td>3.7</td></tr>
+  <tr><td>API 8</td><td>3.6</td></tr>
+  <tr><td>API 3</td><td>3.5</td></tr>
+  <tr><td>API 1</td><td>3.4</td></tr>
+</table>
+
+<p>Some device manufacturers include different versions of SQLite on their devices.
+  There are two ways to programmatically determine the version number.
+
+<ul>
+  <li>If available, use the sqlite3 tool, for example:
+    <code>adb -e shell sqlite3 --version</code>.</li>
+  <li>Create and query an in-memory database as shown in the following code sample:
+    <pre>
+    String query = "select sqlite_version() AS sqlite_version";
+    SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(":memory:", null);
+    Cursor cursor = db.rawQuery(query, null);
+    String sqliteVersion = "";
+    if (cursor.moveToNext()) {
+        sqliteVersion = cursor.getString(0);
+    }</pre>
+  </li>
+</ul>
 </BODY>
 </HTML>
diff --git a/core/java/android/hardware/camera2/DngCreator.java b/core/java/android/hardware/camera2/DngCreator.java
index 45fa15e..1a51acd 100644
--- a/core/java/android/hardware/camera2/DngCreator.java
+++ b/core/java/android/hardware/camera2/DngCreator.java
@@ -119,8 +119,14 @@
             captureTime = timestamp / 1000000 + timeOffset;
         }
 
+        // Create this fresh each time since the time zone may change while a long-running application
+        // is active.
+        final DateFormat dateTimeStampFormat =
+            new SimpleDateFormat(TIFF_DATETIME_FORMAT);
+        dateTimeStampFormat.setTimeZone(TimeZone.getDefault());
+
         // Format for metadata
-        String formattedCaptureTime = sDateTimeStampFormat.format(captureTime);
+        String formattedCaptureTime = dateTimeStampFormat.format(captureTime);
 
         nativeInit(characteristics.getNativeCopy(), metadata.getNativeCopy(),
                 formattedCaptureTime);
@@ -467,13 +473,10 @@
     private static final String GPS_DATE_FORMAT_STR = "yyyy:MM:dd";
     private static final String TIFF_DATETIME_FORMAT = "yyyy:MM:dd HH:mm:ss";
     private static final DateFormat sExifGPSDateStamp = new SimpleDateFormat(GPS_DATE_FORMAT_STR);
-    private static final DateFormat sDateTimeStampFormat =
-            new SimpleDateFormat(TIFF_DATETIME_FORMAT);
     private final Calendar mGPSTimeStampCalendar = Calendar
             .getInstance(TimeZone.getTimeZone("UTC"));
 
     static {
-        sDateTimeStampFormat.setTimeZone(TimeZone.getDefault());
         sExifGPSDateStamp.setTimeZone(TimeZone.getTimeZone("UTC"));
     }
 
diff --git a/core/java/android/hardware/camera2/utils/TaskDrainer.java b/core/java/android/hardware/camera2/utils/TaskDrainer.java
index 7c46e50..ed30ff3 100644
--- a/core/java/android/hardware/camera2/utils/TaskDrainer.java
+++ b/core/java/android/hardware/camera2/utils/TaskDrainer.java
@@ -29,8 +29,9 @@
  * (and new ones won't begin).
  *
  * <p>The initial state is to allow all tasks to be started and finished. A task may only be started
- * once, after which it must be finished before starting again. Likewise, finishing a task
- * that hasn't been started is also not allowed.</p>
+ * once, after which it must be finished before starting again. Likewise, a task may only be
+ * finished once, after which it must be started before finishing again. It is okay to finish a
+ * task before starting it due to different threads handling starting and finishing.</p>
  *
  * <p>When draining begins, no more new tasks can be started. This guarantees that at some
  * point when all the tasks are finished there will be no more collective new tasks,
@@ -60,6 +61,11 @@
 
     /** Set of tasks which have been started but not yet finished with #taskFinished */
     private final Set<T> mTaskSet = new HashSet<T>();
+    /**
+     * Set of tasks which have been finished but not yet started with #taskStarted. This may happen
+     * if taskStarted and taskFinished are called from two different threads.
+     */
+    private final Set<T> mEarlyFinishedTaskSet = new HashSet<T>();
     private final Object mLock = new Object();
 
     private boolean mDraining = false;
@@ -118,8 +124,12 @@
                 throw new IllegalStateException("Can't start more tasks after draining has begun");
             }
 
-            if (!mTaskSet.add(task)) {
-                throw new IllegalStateException("Task " + task + " was already started");
+            // Try to remove the task from the early finished set.
+            if (!mEarlyFinishedTaskSet.remove(task)) {
+                // The task is not finished early. Add it to the started set.
+                if (!mTaskSet.add(task)) {
+                    throw new IllegalStateException("Task " + task + " was already started");
+                }
             }
         }
     }
@@ -128,8 +138,7 @@
     /**
      * Mark an asynchronous task as having finished.
      *
-     * <p>A task cannot be finished if it hasn't started. Once finished, a task
-     * cannot be finished again (unless it's started again).</p>
+     * <p>A task cannot be finished more than once without first having started.</p>
      *
      * @param task a key to identify a task
      *
@@ -137,7 +146,7 @@
      * @see #beginDrain
      *
      * @throws IllegalStateException
-     *          If attempting to start a task which is already finished (and not re-started),
+     *          If attempting to finish a task which is already finished (and not started),
      */
     public void taskFinished(T task) {
         synchronized (mLock) {
@@ -145,8 +154,12 @@
                 Log.v(TAG + "[" + mName + "]", "taskFinished " + task);
             }
 
+            // Try to remove the task from started set.
             if (!mTaskSet.remove(task)) {
-                throw new IllegalStateException("Task " + task + " was already finished");
+                // Task is not started yet. Add it to the early finished set.
+                if (!mEarlyFinishedTaskSet.add(task)) {
+                    throw new IllegalStateException("Task " + task + " was already finished");
+                }
             }
 
             // If this is the last finished task and draining has already begun, fire #onDrained
diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java
index 19c82a5..35df015 100644
--- a/core/java/android/hardware/location/ContextHubService.java
+++ b/core/java/android/hardware/location/ContextHubService.java
@@ -18,6 +18,8 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 import java.util.ArrayList;
 import java.util.HashMap;
 
@@ -146,6 +148,36 @@
         return mContextHubInfo[contextHubHandle];
     }
 
+    // TODO(b/30808791): Remove this when NanoApp's API is correctly treating
+    // app IDs as 64-bits.
+    private static long parseAppId(NanoApp app) {
+        // NOTE: If this shifting seems odd (since it's actually "ONAN"), note
+        //     that it matches how this is defined in context_hub.h.
+        final int HEADER_MAGIC =
+            (((int)'N' <<  0) |
+             ((int)'A' <<  8) |
+             ((int)'N' << 16) |
+             ((int)'O' << 24));
+        final int HEADER_MAGIC_OFFSET = 4;
+        final int HEADER_APP_ID_OFFSET = 8;
+
+        ByteBuffer header = ByteBuffer.wrap(app.getAppBinary())
+            .order(ByteOrder.LITTLE_ENDIAN);
+
+        try {
+            if (header.getInt(HEADER_MAGIC_OFFSET) == HEADER_MAGIC) {
+                // This is a legitimate nanoapp header.  Let's grab the app ID.
+                return header.getLong(HEADER_APP_ID_OFFSET);
+            }
+        } catch (IndexOutOfBoundsException e) {
+            // The header is undersized.  We'll fall through to our code
+            // path below, which handles being unable to parse the header.
+        }
+        // We failed to parse the header.  Even through it's probably wrong,
+        // let's give NanoApp's idea of our ID.  This is at least consistent.
+        return app.getAppId();
+    }
+
     @Override
     public int loadNanoApp(int contextHubHandle, NanoApp app) throws RemoteException {
         checkPermissions();
@@ -165,27 +197,14 @@
         msgHeader[HEADER_FIELD_MSG_TYPE] = MSG_LOAD_NANO_APP;
 
         long appId = app.getAppId();
-        // TODO(b/30808791): Remove this hack when the NanoApp API is fixed.
-        // Due to a bug in the NanoApp API, only the least significant four
-        // bytes of the app ID can be stored.  The most significant five
-        // bytes of a normal app ID are the "vendor", and thus the most
-        // significant of the bytes we have is the least significant byte
-        // of the vendor.  In the case that byte is the ASCII value for
-        // lower-case 'L', we assume the vendor is supposed to be "Googl"
-        // and fill in the four most significant bytes accordingly.
+        // TODO(b/30808791): Remove this hack when the NanoApp API is fixed,
+        //     and getAppId() returns a 'long' instead of an 'int'.
         if ((appId >> 32) != 0) {
             // We're unlikely to notice this warning, but at least
             // we can avoid running our hack logic.
             Log.w(TAG, "Code has not been updated since API fix.");
         } else {
-            // Note: Lower-case 'L', not the number 1.
-            if (((appId >> 24) & 0xFF) == (long)'l') {
-                // Assume we're a Google nanoapp.
-                appId |= ((long)'G') << 56;
-                appId |= ((long)'o') << 48;
-                appId |= ((long)'o') << 40;
-                appId |= ((long)'g') << 32;
-            }
+            appId = parseAppId(app);
         }
 
         msgHeader[HEADER_FIELD_LOAD_APP_ID_LO] = (int)(appId & 0xFFFFFFFF);
diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
index a2677c6..160e261 100644
--- a/core/java/android/hardware/usb/UsbDeviceConnection.java
+++ b/core/java/android/hardware/usb/UsbDeviceConnection.java
@@ -24,7 +24,7 @@
 import dalvik.system.CloseGuard;
 
 import java.io.FileDescriptor;
-
+import java.nio.ByteBuffer;
 
 /**
  * This class is used for sending and receiving data and control messages to a USB device.
@@ -213,9 +213,10 @@
      * </p>
      *
      * @param endpoint the endpoint for this transaction
-     * @param buffer buffer for data to send or receive
+     * @param buffer buffer for data to send or receive; can be {@code null} to wait for next
+     *               transaction without reading data
      * @param length the length of the data to send or receive
-     * @param timeout in milliseconds
+     * @param timeout in milliseconds, 0 is infinite
      * @return length of data transferred (or zero) for success,
      * or negative value for failure
      */
@@ -232,7 +233,7 @@
      * @param buffer buffer for data to send or receive
      * @param offset the index of the first byte in the buffer to send or receive
      * @param length the length of the data to send or receive
-     * @param timeout in milliseconds
+     * @param timeout in milliseconds, 0 is infinite
      * @return length of data transferred (or zero) for success,
      * or negative value for failure
      */
@@ -256,13 +257,20 @@
 
     /**
      * Waits for the result of a {@link android.hardware.usb.UsbRequest#queue} operation
-     * Note that this may return requests queued on multiple
-     * {@link android.hardware.usb.UsbEndpoint}s.
-     * When multiple endpoints are in use, {@link android.hardware.usb.UsbRequest#getEndpoint} and
-     * {@link android.hardware.usb.UsbRequest#getClientData} can be useful in determining
-     * how to process the result of this function.
+     * <p>Note that this may return requests queued on multiple
+     * {@link android.hardware.usb.UsbEndpoint}s. When multiple endpoints are in use,
+     * {@link android.hardware.usb.UsbRequest#getEndpoint} and {@link
+     * android.hardware.usb.UsbRequest#getClientData} can be useful in determining how to process
+     * the result of this function.</p>
+     * <p>Position and array offset of the request's buffer are ignored and assumed to be 0. The
+     * position will be set to the number of bytes read/written.</p>
      *
      * @return a completed USB request, or null if an error occurred
+     *
+     * @throws IllegalArgumentException if the number of bytes read or written is more than the
+     *                                  limit of the request's buffer. The number of bytes is
+     *                                  determined by the {@code length} parameter of
+     *                                  {@link UsbRequest#queue(ByteBuffer, int)}
      */
     public UsbRequest requestWait() {
         UsbRequest request = native_request_wait();
@@ -284,7 +292,7 @@
 
     private static void checkBounds(byte[] buffer, int start, int length) {
         final int bufferLength = (buffer != null ? buffer.length : 0);
-        if (start < 0 || start + length > bufferLength) {
+        if (length < 0 || start < 0 || start + length > bufferLength) {
             throw new IllegalArgumentException("Buffer start or length out of bounds.");
         }
     }
diff --git a/core/java/android/hardware/usb/UsbRequest.java b/core/java/android/hardware/usb/UsbRequest.java
index b531e5f..9f7592f 100644
--- a/core/java/android/hardware/usb/UsbRequest.java
+++ b/core/java/android/hardware/usb/UsbRequest.java
@@ -17,6 +17,7 @@
 package android.hardware.usb;
 
 import android.util.Log;
+import com.android.internal.util.Preconditions;
 import dalvik.system.CloseGuard;
 
 import java.nio.ByteBuffer;
@@ -66,7 +67,7 @@
      */
     public boolean initialize(UsbDeviceConnection connection, UsbEndpoint endpoint) {
         mEndpoint = endpoint;
-        mConnection = connection;
+        mConnection = Preconditions.checkNotNull(connection);
 
         boolean wasInitialized = native_init(connection, endpoint.getAddress(),
                 endpoint.getAttributes(), endpoint.getMaxPacketSize(), endpoint.getInterval());
@@ -137,15 +138,16 @@
 
     /**
      * Queues the request to send or receive data on its endpoint.
-     * For OUT endpoints, the given buffer data will be sent on the endpoint.
-     * For IN endpoints, the endpoint will attempt to read the given number of bytes
-     * into the specified buffer.
-     * If the queueing operation is successful, we return true and the result will be
-     * returned via {@link android.hardware.usb.UsbDeviceConnection#requestWait}
+     * <p>For OUT endpoints, the given buffer data will be sent on the endpoint. For IN endpoints,
+     * the endpoint will attempt to read the given number of bytes into the specified buffer. If the
+     * queueing operation is successful, we return true and the result will be returned via {@link
+     * android.hardware.usb.UsbDeviceConnection#requestWait}</p>
      *
-     * @param buffer the buffer containing the bytes to write, or location to store
-     * the results of a read
-     * @param length number of bytes to read or write
+     * @param buffer the buffer containing the bytes to write, or location to store the results of a
+     *               read. Position and array offset will be ignored and assumed to be 0. Limit and
+     *               capacity will be ignored.
+     * @param length number of bytes to read or write.
+     *
      * @return true if the queueing operation succeeded
      */
     public boolean queue(ByteBuffer buffer, int length) {
@@ -155,6 +157,9 @@
         mBuffer = buffer;
         mLength = length;
 
+        // Note: On a buffer slice we lost the capacity information about the underlying buffer,
+        // hence we cannot check if the access would be a data leak/memory corruption.
+
         boolean result;
         if (buffer.isDirect()) {
             result = native_queue_direct(buffer, length, out);
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index c793a6e..9e5aaf5 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1840,6 +1840,16 @@
         return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
     }
 
+    /* TODO: These permissions checks don't belong in client-side code. Move them to
+     * services.jar, possibly in com.android.server.net. */
+
+    /** {@hide} */
+    public static final boolean checkChangePermission(Context context) {
+        int uid = Binder.getCallingUid();
+        return Settings.checkAndNoteChangeNetworkStateOperation(context, uid, Settings
+                .getPackageNameForUid(context, uid), false /* throwException */);
+    }
+
     /** {@hide} */
     public static final void enforceChangePermission(Context context) {
         int uid = Binder.getCallingUid();
diff --git a/core/java/android/accounts/IAccountAccessTracker.aidl b/core/java/android/net/IIpConnectivityMetrics.aidl
similarity index 68%
rename from core/java/android/accounts/IAccountAccessTracker.aidl
rename to core/java/android/net/IIpConnectivityMetrics.aidl
index e12b3d1..8f634bb 100644
--- a/core/java/android/accounts/IAccountAccessTracker.aidl
+++ b/core/java/android/net/IIpConnectivityMetrics.aidl
@@ -14,13 +14,16 @@
  * limitations under the License.
  */
 
-package android.accounts;
+package android.net;
 
-/**
- * Interface to track which apps accessed an account
- *
- * @hide
- */
-oneway interface IAccountAccessTracker {
-    void onAccountAccessed();
+import android.os.Parcelable;
+import android.net.ConnectivityMetricsEvent;
+
+/** {@hide} */
+interface IIpConnectivityMetrics {
+
+    /**
+     * @return number of remaining available slots in buffer.
+     */
+    int logEvent(in ConnectivityMetricsEvent event);
 }
diff --git a/core/java/android/net/PskKeyManager.java b/core/java/android/net/PskKeyManager.java
index 667abb4..f5167ea 100644
--- a/core/java/android/net/PskKeyManager.java
+++ b/core/java/android/net/PskKeyManager.java
@@ -104,6 +104,8 @@
  *
  * SSLSocket sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket(...);
  * }</pre>
+ *
+ * @removed This class is removed because it does not work with TLS 1.3.
  */
 public abstract class PskKeyManager implements PSKKeyManager {
     // IMPLEMENTATION DETAILS: This class exists only because the default implemenetation of the
diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java
index dd7bd1b..173e5fd 100644
--- a/core/java/android/net/metrics/IpConnectivityLog.java
+++ b/core/java/android/net/metrics/IpConnectivityLog.java
@@ -17,63 +17,65 @@
 package android.net.metrics;
 
 import android.net.ConnectivityMetricsEvent;
-import android.net.ConnectivityMetricsLogger;
-import android.net.IConnectivityMetricsLogger;
+import android.net.IIpConnectivityMetrics;
 import android.os.Parcelable;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.util.Log;
-
 import com.android.internal.annotations.VisibleForTesting;
 
 /**
- * Specialization of the ConnectivityMetricsLogger class for recording IP connectivity events.
+ * Class for logging IpConnectvity events with IpConnectivityMetrics
  * {@hide}
  */
-public class IpConnectivityLog extends ConnectivityMetricsLogger {
-    private static String TAG = "IpConnectivityMetricsLogger";
-    private static final boolean DBG = true;
+public class IpConnectivityLog {
+    private static final String TAG = IpConnectivityLog.class.getSimpleName();
+    private static final boolean DBG = false;
+
+    public static final String SERVICE_NAME = "connmetrics";
+
+    private IIpConnectivityMetrics mService;
 
     public IpConnectivityLog() {
-        // mService initialized in super constructor.
     }
 
     @VisibleForTesting
-    public IpConnectivityLog(IConnectivityMetricsLogger service) {
-        super(service);
+    public IpConnectivityLog(IIpConnectivityMetrics service) {
+        mService = service;
+    }
+
+    private boolean checkLoggerService() {
+        if (mService != null) {
+            return true;
+        }
+        final IIpConnectivityMetrics service =
+                IIpConnectivityMetrics.Stub.asInterface(ServiceManager.getService(SERVICE_NAME));
+        if (service == null) {
+            return false;
+        }
+        // Two threads racing here will write the same pointer because getService
+        // is idempotent once MetricsLoggerService is initialized.
+        mService = service;
+        return true;
     }
 
     /**
-     * Log an IpConnectivity event. Contrary to logEvent(), this method does not
-     * keep track of skipped events and is thread-safe for callers.
-     *
+     * Log an IpConnectivity event.
      * @param timestamp is the epoch timestamp of the event in ms.
      * @param data is a Parcelable instance representing the event.
-     *
      * @return true if the event was successfully logged.
      */
     public boolean log(long timestamp, Parcelable data) {
         if (!checkLoggerService()) {
             if (DBG) {
-                Log.d(TAG, CONNECTIVITY_METRICS_LOGGER_SERVICE + " service was not ready");
-            }
-            return false;
-        }
-
-        if (System.currentTimeMillis() < mServiceUnblockedTimestampMillis) {
-            if (DBG) {
-                Log.d(TAG, "skipping logging due to throttling for IpConnectivity component");
+                Log.d(TAG, SERVICE_NAME + " service was not ready");
             }
             return false;
         }
 
         try {
-            final ConnectivityMetricsEvent event =
-                new ConnectivityMetricsEvent(timestamp, COMPONENT_TAG_CONNECTIVITY, 0, data);
-            final long result = mService.logEvent(event);
-            if (result >= 0) {
-                mServiceUnblockedTimestampMillis = result;
-            }
-            return (result == 0);
+            int left = mService.logEvent(new ConnectivityMetricsEvent(timestamp, 0, 0, data));
+            return left >= 0;
         } catch (RemoteException e) {
             Log.e(TAG, "Error logging event", e);
             return false;
diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java
index 331cf0c..1a31b56 100644
--- a/core/java/android/net/metrics/ValidationProbeEvent.java
+++ b/core/java/android/net/metrics/ValidationProbeEvent.java
@@ -34,10 +34,12 @@
 @SystemApi
 public final class ValidationProbeEvent implements Parcelable {
 
-    public static final int PROBE_DNS   = 0;
-    public static final int PROBE_HTTP  = 1;
-    public static final int PROBE_HTTPS = 2;
-    public static final int PROBE_PAC   = 3;
+    public static final int PROBE_DNS       = 0;
+    public static final int PROBE_HTTP      = 1;
+    public static final int PROBE_HTTPS     = 2;
+    public static final int PROBE_PAC       = 3;
+    /** {@hide} */
+    public static final int PROBE_FALLBACK  = 4;
 
     public static final int DNS_FAILURE = 0;
     public static final int DNS_SUCCESS = 1;
@@ -57,7 +59,7 @@
     public final @ProbeType int probeType;
     public final @ReturnCode int returnCode;
 
-    /** @hide */
+    /** {@hide} */
     public ValidationProbeEvent(
             int netId, long durationMs, @ProbeType int probeType, @ReturnCode int returnCode) {
         this.netId = netId;
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index 9a4b599..fea64ec 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -304,6 +304,9 @@
                     //noinspection unchecked
                     result = doInBackground(mParams);
                     Binder.flushPendingCommands();
+                } catch (Throwable tr) {
+                    mCancelled.set(true);
+                    throw tr;
                 } finally {
                     postResult(result);
                 }
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index ea8ba2f..cf77567 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -23,7 +23,6 @@
 
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Modifier;
@@ -361,13 +360,14 @@
             ParcelFileDescriptor out = data.readFileDescriptor();
             ParcelFileDescriptor err = data.readFileDescriptor();
             String[] args = data.readStringArray();
+            ShellCallback shellCallback = ShellCallback.CREATOR.createFromParcel(data);
             ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(data);
             try {
                 if (out != null) {
                     shellCommand(in != null ? in.getFileDescriptor() : null,
                             out.getFileDescriptor(),
                             err != null ? err.getFileDescriptor() : out.getFileDescriptor(),
-                            args, resultReceiver);
+                            args, shellCallback, resultReceiver);
                 }
             } finally {
                 IoUtils.closeQuietly(in);
@@ -459,13 +459,15 @@
      * @param out The raw file descriptor that normal command messages should be written to.
      * @param err The raw file descriptor that command error messages should be written to.
      * @param args Command-line arguments.
+     * @param callback Callback through which to interact with the invoking shell.
      * @param resultReceiver Called when the command has finished executing, with the result code.
      * @throws RemoteException
      * @hide
      */
     public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
-            String[] args, ResultReceiver resultReceiver) throws RemoteException {
-        onShellCommand(in, out, err, args, resultReceiver);
+            String[] args, ShellCallback callback,
+            ResultReceiver resultReceiver) throws RemoteException {
+        onShellCommand(in, out, err, args, callback, resultReceiver);
     }
 
     /**
@@ -477,7 +479,7 @@
      * @hide
      */
     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
-            String[] args, ResultReceiver resultReceiver) throws RemoteException {
+            String[] args, ShellCallback callback, ResultReceiver resultReceiver) throws RemoteException {
         FileOutputStream fout = new FileOutputStream(err != null ? err : out);
         PrintWriter pw = new FastPrintWriter(fout);
         pw.println("No shell command implementation.");
@@ -650,13 +652,15 @@
     }
 
     public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
-            String[] args, ResultReceiver resultReceiver) throws RemoteException {
+            String[] args, ShellCallback callback,
+            ResultReceiver resultReceiver) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeFileDescriptor(in);
         data.writeFileDescriptor(out);
         data.writeFileDescriptor(err);
         data.writeStringArray(args);
+        ShellCallback.writeToParcel(callback, data);
         resultReceiver.writeToParcel(data, 0);
         try {
             transact(SHELL_COMMAND_TRANSACTION, data, reply, 0);
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 0191589..312a098 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -739,6 +739,14 @@
          * {@link android.widget.LinearLayout.LayoutParams LinearLayout.LayoutParams} to
          * {@link android.widget.RelativeLayout.LayoutParams RelativeLayout.LayoutParams}).</li>
          * <li>Your application processes will not be killed when the device density changes.</li>
+         * <li>Drag and drop. After a view receives the
+         * {@link android.view.DragEvent#ACTION_DRAG_ENTERED} event, when the drag shadow moves into
+         * a descendant view that can accept the data, the view receives the
+         * {@link android.view.DragEvent#ACTION_DRAG_EXITED} event and won’t receive
+         * {@link android.view.DragEvent#ACTION_DRAG_LOCATION} and
+         * {@link android.view.DragEvent#ACTION_DROP} events while the drag shadow is within that
+         * descendant view, even if the descendant view returns <code>false</code> from its handler
+         * for these events.</li>
          * </ul>
          */
         public static final int N = 24;
diff --git a/core/java/android/os/HwBlob.java b/core/java/android/os/HwBlob.java
index 153c6e6..88226f0 100644
--- a/core/java/android/os/HwBlob.java
+++ b/core/java/android/os/HwBlob.java
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import android.annotation.NonNull;
+
 import libcore.util.NativeAllocationRegistry;
 
 /** @hide */
@@ -54,6 +56,69 @@
 
     public native final long handle();
 
+    public static Boolean[] wrapArray(@NonNull boolean[] array) {
+        final int n = array.length;
+        Boolean[] wrappedArray = new Boolean[n];
+        for (int i = 0; i < n; ++i) {
+          wrappedArray[i] = array[i];
+        }
+        return wrappedArray;
+    }
+
+    public static Long[] wrapArray(@NonNull long[] array) {
+        final int n = array.length;
+        Long[] wrappedArray = new Long[n];
+        for (int i = 0; i < n; ++i) {
+          wrappedArray[i] = array[i];
+        }
+        return wrappedArray;
+    }
+
+    public static Byte[] wrapArray(@NonNull byte[] array) {
+        final int n = array.length;
+        Byte[] wrappedArray = new Byte[n];
+        for (int i = 0; i < n; ++i) {
+          wrappedArray[i] = array[i];
+        }
+        return wrappedArray;
+    }
+
+    public static Short[] wrapArray(@NonNull short[] array) {
+        final int n = array.length;
+        Short[] wrappedArray = new Short[n];
+        for (int i = 0; i < n; ++i) {
+          wrappedArray[i] = array[i];
+        }
+        return wrappedArray;
+    }
+
+    public static Integer[] wrapArray(@NonNull int[] array) {
+        final int n = array.length;
+        Integer[] wrappedArray = new Integer[n];
+        for (int i = 0; i < n; ++i) {
+          wrappedArray[i] = array[i];
+        }
+        return wrappedArray;
+    }
+
+    public static Float[] wrapArray(@NonNull float[] array) {
+        final int n = array.length;
+        Float[] wrappedArray = new Float[n];
+        for (int i = 0; i < n; ++i) {
+          wrappedArray[i] = array[i];
+        }
+        return wrappedArray;
+    }
+
+    public static Double[] wrapArray(@NonNull double[] array) {
+        final int n = array.length;
+        Double[] wrappedArray = new Double[n];
+        for (int i = 0; i < n; ++i) {
+          wrappedArray[i] = array[i];
+        }
+        return wrappedArray;
+    }
+
     // Returns address of the "freeFunction".
     private static native final long native_init();
 
diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java
index 0fa8750..f762a05 100644
--- a/core/java/android/os/IBinder.java
+++ b/core/java/android/os/IBinder.java
@@ -220,11 +220,13 @@
      * @param out The raw file descriptor that normal command messages should be written to.
      * @param err The raw file descriptor that command error messages should be written to.
      * @param args Command-line arguments.
+     * @param shellCallback Optional callback to the caller's shell to perform operations in it.
      * @param resultReceiver Called when the command has finished executing, with the result code.
      * @hide
      */
     public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
-            String[] args, ResultReceiver resultReceiver) throws RemoteException;
+            String[] args, ShellCallback shellCallback,
+            ResultReceiver resultReceiver) throws RemoteException;
 
     /**
      * Perform a generic operation with the object.
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 1aed9b3..8d4d0a5 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -1340,6 +1340,11 @@
         }
 
         /** @hide */
+        public String getTag() {
+            return mTag;
+        }
+
+        /** @hide */
         public void setHistoryTag(String tag) {
             mHistoryTag = tag;
         }
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 90bd11f..0b3abaa 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -93,6 +93,14 @@
      */
     public static final File UNCRYPT_PACKAGE_FILE = new File(RECOVERY_DIR, "uncrypt_file");
 
+    /**
+     * UNCRYPT_STATUS_FILE stores the time cost (and error code in the case of a failure)
+     * of uncrypt.
+     *
+     * @hide
+     */
+    public static final File UNCRYPT_STATUS_FILE = new File(RECOVERY_DIR, "uncrypt_status");
+
     // Length limits for reading files.
     private static final int LOG_FILE_MAX_LENGTH = 64 * 1024;
 
diff --git a/core/java/android/os/ShellCallback.java b/core/java/android/os/ShellCallback.java
new file mode 100644
index 0000000..e7fe697
--- /dev/null
+++ b/core/java/android/os/ShellCallback.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.util.Log;
+
+import com.android.internal.os.IShellCallback;
+
+/**
+ * Special-purpose API for use with {@link IBinder#shellCommand IBinder.shellCommand} for
+ * performing operations back on the invoking shell.
+ * @hide
+ */
+public class ShellCallback implements Parcelable {
+    final static String TAG = "ShellCallback";
+
+    final static boolean DEBUG = false;
+
+    final boolean mLocal;
+
+    IShellCallback mShellCallback;
+
+    class MyShellCallback extends IShellCallback.Stub {
+        public ParcelFileDescriptor openOutputFile(String path, String seLinuxContext) {
+            return onOpenOutputFile(path, seLinuxContext);
+        }
+    }
+
+    /**
+     * Create a new ShellCallback to receive requests.
+     */
+    public ShellCallback() {
+        mLocal = true;
+    }
+
+    /**
+     * Ask the shell to open a file for writing.  This will truncate the file if it
+     * already exists.  It will create the file if it doesn't exist.
+     * @param path Path of the file to be opened/created.
+     * @param seLinuxContext Optional SELinux context that must be allowed to have
+     * access to the file; if null, nothing is required.
+     */
+    public ParcelFileDescriptor openOutputFile(String path, String seLinuxContext) {
+        if (DEBUG) Log.d(TAG, "openOutputFile " + this + ": mLocal=" + mLocal
+                + " mShellCallback=" + mShellCallback);
+
+        if (mLocal) {
+            return onOpenOutputFile(path, seLinuxContext);
+        }
+
+        if (mShellCallback != null) {
+            try {
+                return mShellCallback.openOutputFile(path, seLinuxContext);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failure opening " + path, e);
+            }
+        }
+        return null;
+    }
+
+    public ParcelFileDescriptor onOpenOutputFile(String path, String seLinuxContext) {
+        return null;
+    }
+
+    public static void writeToParcel(ShellCallback callback, Parcel out) {
+        if (callback == null) {
+            out.writeStrongBinder(null);
+        } else {
+            callback.writeToParcel(out, 0);
+        }
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        synchronized (this) {
+            if (mShellCallback == null) {
+                mShellCallback = new MyShellCallback();
+            }
+            out.writeStrongBinder(mShellCallback.asBinder());
+        }
+    }
+
+    ShellCallback(Parcel in) {
+        mLocal = false;
+        mShellCallback = IShellCallback.Stub.asInterface(in.readStrongBinder());
+    }
+
+    public static final Parcelable.Creator<ShellCallback> CREATOR
+            = new Parcelable.Creator<ShellCallback>() {
+        public ShellCallback createFromParcel(Parcel in) {
+            return new ShellCallback(in);
+        }
+        public ShellCallback[] newArray(int size) {
+            return new ShellCallback[size];
+        }
+    };
+}
diff --git a/core/java/android/os/ShellCommand.java b/core/java/android/os/ShellCommand.java
index fc804e5..831c9b2 100644
--- a/core/java/android/os/ShellCommand.java
+++ b/core/java/android/os/ShellCommand.java
@@ -40,6 +40,7 @@
     private FileDescriptor mOut;
     private FileDescriptor mErr;
     private String[] mArgs;
+    private ShellCallback mShellCallback;
     private ResultReceiver mResultReceiver;
 
     private String mCmd;
@@ -55,12 +56,13 @@
     private InputStream mInputStream;
 
     public void init(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
-            String[] args, int firstArgPos) {
+            String[] args, ShellCallback callback, int firstArgPos) {
         mTarget = target;
         mIn = in;
         mOut = out;
         mErr = err;
         mArgs = args;
+        mShellCallback = callback;
         mResultReceiver = null;
         mCmd = null;
         mArgPos = firstArgPos;
@@ -74,7 +76,7 @@
     }
 
     public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
-            String[] args, ResultReceiver resultReceiver) {
+            String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
         String cmd;
         int start;
         if (args != null && args.length > 0) {
@@ -84,7 +86,7 @@
             cmd = null;
             start = 0;
         }
-        init(target, in, out, err, args, start);
+        init(target, in, out, err, args, callback, start);
         mCmd = cmd;
         mResultReceiver = resultReceiver;
 
@@ -105,7 +107,7 @@
             // go.
             PrintWriter eout = getErrPrintWriter();
             eout.println();
-            eout.println("Exception occurred while dumping:");
+            eout.println("Exception occurred while executing:");
             e.printStackTrace(eout);
         } finally {
             if (DEBUG) Slog.d(TAG, "Flushing output streams on " + mTarget);
@@ -257,6 +259,13 @@
         return arg;
     }
 
+    /**
+     * Return the {@link ShellCallback} for communicating back with the calling shell.
+     */
+    public ShellCallback getShellCallback() {
+        return mShellCallback;
+    }
+
     public int handleDefaultCommands(String cmd) {
         if ("dump".equals(cmd)) {
             String[] newArgs = new String[mArgs.length-1];
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 12a76c5..f8b9361 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -44,7 +44,6 @@
 import android.net.Uri;
 import android.net.wifi.WifiManager;
 import android.os.BatteryManager;
-import android.os.Binder;
 import android.os.Bundle;
 import android.os.DropBoxManager;
 import android.os.IBinder;
@@ -1284,6 +1283,19 @@
             = "android.settings.VR_LISTENER_SETTINGS";
 
     /**
+     * Activity Action: Show Storage Manager settings.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_STORAGE_MANAGER_SETTINGS
+            = "android.settings.STORAGE_MANAGER_SETTINGS";
+
+    /**
      * Activity Action: Allows user to select current webview implementation.
      * <p>
      * Input: Nothing.
@@ -8055,12 +8067,37 @@
         /**
          * The server used for captive portal detection upon a new conection. A
          * 204 response code from the server is used for validation.
+         * TODO: remove this deprecated symbol.
          *
          * @hide
          */
         public static final String CAPTIVE_PORTAL_SERVER = "captive_portal_server";
 
         /**
+         * The URL used for HTTPS captive portal detection upon a new connection.
+         * A 204 response code from the server is used for validation.
+         *
+         * @hide
+         */
+        public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url";
+
+        /**
+         * The URL used for HTTP captive portal detection upon a new connection.
+         * A 204 response code from the server is used for validation.
+         *
+         * @hide
+         */
+        public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
+
+        /**
+         * The URL used for fallback HTTP captive portal detection when previous HTTP
+         * and HTTPS captive portal detection attemps did not return a conclusive answer.
+         *
+         * @hide
+         */
+        public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
+
+        /**
          * Whether to use HTTPS for network validation. This is enabled by default and the setting
          * needs to be set to 0 to disable it. This setting is a misnomer because captive portals
          * don't actually use HTTPS, but it's consistent with the other settings.
@@ -8070,6 +8107,14 @@
         public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
 
         /**
+         * Which User-Agent string to use in the header of the captive portal detection probes.
+         * The User-Agent field is unset when this setting has no value (HttpUrlConnection default).
+         *
+         * @hide
+         */
+        public static final String CAPTIVE_PORTAL_USER_AGENT = "captive_portal_user_agent";
+
+        /**
          * Whether network service discovery is enabled.
          *
          * @hide
@@ -8442,6 +8487,13 @@
         public static final String CALL_AUTO_RETRY = "call_auto_retry";
 
         /**
+         * A setting that can be read whether the emergency affordance is currently needed.
+         * The value is a boolean (1 or 0).
+         * @hide
+         */
+        public static final String EMERGENCY_AFFORDANCE_NEEDED = "emergency_affordance_needed";
+
+        /**
          * See RIL_PreferredNetworkType in ril.h
          * @hide
          */
@@ -8773,7 +8825,7 @@
         public static final String WFC_IMS_ENABLED = "wfc_ims_enabled";
 
         /**
-         * WFC Mode.
+         * WFC mode on home/non-roaming network.
          * <p>
          * Type: int - 2=Wi-Fi preferred, 1=Cellular preferred, 0=Wi-Fi only
          *
@@ -8782,6 +8834,15 @@
         public static final String WFC_IMS_MODE = "wfc_ims_mode";
 
         /**
+         * WFC mode on roaming network.
+         * <p>
+         * Type: int - see {@link WFC_IMS_MODE} for values
+         *
+         * @hide
+         */
+        public static final String WFC_IMS_ROAMING_MODE = "wfc_ims_roaming_mode";
+
+        /**
          * Whether WFC roaming is enabled
          * <p>
          * Type: int (0 for false, 1 for true)
@@ -8809,6 +8870,16 @@
                 "ephemeral_cookie_max_size_bytes";
 
         /**
+         * Toggle to enable/disable the entire ephemeral feature. By default, ephemeral is
+         * enabled. Set to zero to disable.
+         * <p>
+         * Type: int (0 for false, 1 for true)
+         *
+         * @hide
+         */
+        public static final String ENABLE_EPHEMERAL_FEATURE = "enable_ephemeral_feature";
+
+        /**
          * A mask applied to the ephemeral hash to generate the hash prefix.
          * <p>
          * Type: int
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index e958fbe..94505d3 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -27,6 +27,7 @@
 import android.graphics.drawable.ColorDrawable;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.IRemoteCallback;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -192,9 +193,6 @@
 
     private boolean mDebug = false;
 
-    private PowerManager.WakeLock mWakeLock;
-    private boolean mWakeLockAcquired;
-
     public DreamService() {
         mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
     }
@@ -789,8 +787,6 @@
     public void onCreate() {
         if (mDebug) Slog.v(TAG, "onCreate()");
         super.onCreate();
-        mWakeLock = getSystemService(PowerManager.class)
-                .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DreamService");
     }
 
     /**
@@ -830,21 +826,9 @@
     @Override
     public final IBinder onBind(Intent intent) {
         if (mDebug) Slog.v(TAG, "onBind() intent = " + intent);
-
-        // Need to stay awake until we dispatch onDreamingStarted. This is released either in
-        // attach() or onDestroy().
-        mWakeLock.acquire(5000);
-        mWakeLockAcquired = true;
         return new DreamServiceWrapper();
     }
 
-    private void releaseWakeLockIfNeeded() {
-        if (mWakeLockAcquired) {
-            mWakeLock.release();
-            mWakeLockAcquired = false;
-        }
-    }
-
     /**
      * Stops the dream and detaches from the window.
      * <p>
@@ -921,8 +905,6 @@
         detach();
 
         super.onDestroy();
-
-        releaseWakeLockIfNeeded(); // for acquire in onBind()
     }
 
     // end public api
@@ -961,90 +943,94 @@
      * Must run on mHandler.
      *
      * @param windowToken A window token that will allow a window to be created in the correct layer.
+     * @param started A callback that will be invoked once onDreamingStarted has completed.
      */
-    private final void attach(IBinder windowToken, boolean canDoze) {
-        try {
-            if (mWindowToken != null) {
-                Slog.e(TAG, "attach() called when already attached with token=" + mWindowToken);
-                return;
-            }
-            if (mFinished || mWaking) {
-                Slog.w(TAG, "attach() called after dream already finished");
-                try {
-                    mSandman.finishSelf(windowToken, true /*immediate*/);
-                } catch (RemoteException ex) {
-                    // system server died
-                }
-                return;
-            }
-
-            mWindowToken = windowToken;
-            mCanDoze = canDoze;
-            if (mWindowless && !mCanDoze) {
-                throw new IllegalStateException("Only doze dreams can be windowless");
-            }
-            if (!mWindowless) {
-                mWindow = new PhoneWindow(this);
-                mWindow.setCallback(this);
-                mWindow.requestFeature(Window.FEATURE_NO_TITLE);
-                mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
-                mWindow.setFormat(PixelFormat.OPAQUE);
-
-                if (mDebug) {
-                    Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
-                            windowToken, WindowManager.LayoutParams.TYPE_DREAM));
-                }
-
-                WindowManager.LayoutParams lp = mWindow.getAttributes();
-                lp.type = WindowManager.LayoutParams.TYPE_DREAM;
-                lp.token = windowToken;
-                lp.windowAnimations = com.android.internal.R.style.Animation_Dream;
-                lp.flags |= (WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                            | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
-                            | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
-                            | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
-                            | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
-                            | (mFullscreen ? WindowManager.LayoutParams.FLAG_FULLSCREEN : 0)
-                            | (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0)
-                            );
-                mWindow.setAttributes(lp);
-                // Workaround: Currently low-profile and in-window system bar backgrounds don't go
-                // along well. Dreams usually don't need such bars anyways, so disable them by default.
-                mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
-                mWindow.setWindowManager(null, windowToken, "dream", true);
-
-                applySystemUiVisibilityFlags(
-                        (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0),
-                        View.SYSTEM_UI_FLAG_LOW_PROFILE);
-
-                try {
-                    getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
-                } catch (WindowManager.BadTokenException ex) {
-                    // This can happen because the dream manager service will remove the token
-                    // immediately without necessarily waiting for the dream to start.
-                    // We should receive a finish message soon.
-                    Slog.i(TAG, "attach() called after window token already removed, dream will "
-                            + "finish soon");
-                    mWindow = null;
-                    return;
-                }
-            }
-            // We need to defer calling onDreamingStarted until after onWindowAttached,
-            // which is posted to the handler by addView, so we post onDreamingStarted
-            // to the handler also.  Need to watch out here in case detach occurs before
-            // this callback is invoked.
-            mHandler.post(mWakeLock.wrap(() -> {
-                if (mWindow != null || mWindowless) {
-                    if (mDebug) {
-                        Slog.v(TAG, "Calling onDreamingStarted()");
-                    }
-                    mStarted = true;
-                    onDreamingStarted();
-                }
-            }));
-        } finally {
-            releaseWakeLockIfNeeded(); // for acquire in onBind
+    private final void attach(IBinder windowToken, boolean canDoze, IRemoteCallback started) {
+        if (mWindowToken != null) {
+            Slog.e(TAG, "attach() called when already attached with token=" + mWindowToken);
+            return;
         }
+        if (mFinished || mWaking) {
+            Slog.w(TAG, "attach() called after dream already finished");
+            try {
+                mSandman.finishSelf(windowToken, true /*immediate*/);
+            } catch (RemoteException ex) {
+                // system server died
+            }
+            return;
+        }
+
+        mWindowToken = windowToken;
+        mCanDoze = canDoze;
+        if (mWindowless && !mCanDoze) {
+            throw new IllegalStateException("Only doze dreams can be windowless");
+        }
+        if (!mWindowless) {
+            mWindow = new PhoneWindow(this);
+            mWindow.setCallback(this);
+            mWindow.requestFeature(Window.FEATURE_NO_TITLE);
+            mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
+            mWindow.setFormat(PixelFormat.OPAQUE);
+
+            if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
+                    windowToken, WindowManager.LayoutParams.TYPE_DREAM));
+
+            WindowManager.LayoutParams lp = mWindow.getAttributes();
+            lp.type = WindowManager.LayoutParams.TYPE_DREAM;
+            lp.token = windowToken;
+            lp.windowAnimations = com.android.internal.R.style.Animation_Dream;
+            lp.flags |= ( WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                        | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
+                        | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+                        | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
+                        | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
+                        | (mFullscreen ? WindowManager.LayoutParams.FLAG_FULLSCREEN : 0)
+                        | (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0)
+                        );
+            mWindow.setAttributes(lp);
+            // Workaround: Currently low-profile and in-window system bar backgrounds don't go
+            // along well. Dreams usually don't need such bars anyways, so disable them by default.
+            mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+            mWindow.setWindowManager(null, windowToken, "dream", true);
+
+            applySystemUiVisibilityFlags(
+                    (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0),
+                    View.SYSTEM_UI_FLAG_LOW_PROFILE);
+
+            try {
+                getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
+            } catch (WindowManager.BadTokenException ex) {
+                // This can happen because the dream manager service will remove the token
+                // immediately without necessarily waiting for the dream to start.
+                // We should receive a finish message soon.
+                Slog.i(TAG, "attach() called after window token already removed, dream will "
+                        + "finish soon");
+                mWindow = null;
+                return;
+            }
+        }
+        // We need to defer calling onDreamingStarted until after onWindowAttached,
+        // which is posted to the handler by addView, so we post onDreamingStarted
+        // to the handler also.  Need to watch out here in case detach occurs before
+        // this callback is invoked.
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                if (mWindow != null || mWindowless) {
+                    if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()");
+                    mStarted = true;
+                    try {
+                        onDreamingStarted();
+                    } finally {
+                        try {
+                            started.sendResult(null);
+                        } catch (RemoteException e) {
+                            throw e.rethrowFromSystemServer();
+                        }
+                    }
+                }
+            }
+        });
     }
 
     private boolean getWindowFlagValue(int flag, boolean defaultValue) {
@@ -1116,11 +1102,12 @@
 
     private final class DreamServiceWrapper extends IDreamService.Stub {
         @Override
-        public void attach(final IBinder windowToken, final boolean canDoze) {
+        public void attach(final IBinder windowToken, final boolean canDoze,
+                IRemoteCallback started) {
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    DreamService.this.attach(windowToken, canDoze);
+                    DreamService.this.attach(windowToken, canDoze, started);
                 }
             });
         }
diff --git a/core/java/android/service/dreams/IDreamService.aidl b/core/java/android/service/dreams/IDreamService.aidl
index 9bb1804..ce04354 100644
--- a/core/java/android/service/dreams/IDreamService.aidl
+++ b/core/java/android/service/dreams/IDreamService.aidl
@@ -16,11 +16,13 @@
 
 package android.service.dreams;
 
+import android.os.IRemoteCallback;
+
 /**
  * @hide
  */
 oneway interface IDreamService {
-    void attach(IBinder windowToken, boolean canDoze);
+    void attach(IBinder windowToken, boolean canDoze, IRemoteCallback started);
     void detach();
     void wakeUp();
 }
diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java
index 691a385..2baa0b4 100644
--- a/core/java/android/view/DragEvent.java
+++ b/core/java/android/view/DragEvent.java
@@ -153,12 +153,16 @@
      * if it can accept a drop. The onDragEvent() or onDrag() methods usually inspect the metadata
      * from {@link #getClipDescription()} to determine if they can accept the data contained in
      * this drag. For an operation that doesn't represent data transfer, these methods may
-     * perform other actions to determine whether or not the View should accept the drag.
+     * perform other actions to determine whether or not the View should accept the data.
      * If the View wants to indicate that it is a valid drop target, it can also react by
      * changing its appearance.
      * <p>
-     * A View only receives further drag events if it returns {@code true} in response to
-     * ACTION_DRAG_STARTED.
+     *  Views added or becoming visible for the first time during a drag operation receive this
+     *  event when they are added or becoming visible.
+     * </p>
+     * <p>
+     *  A View only receives further drag events if it returns {@code true} in response to
+     *  ACTION_DRAG_STARTED.
      * </p>
      * @see #ACTION_DRAG_ENDED
      * @see #getX()
@@ -177,9 +181,10 @@
      * </p>
      * <p>
      * The system stops sending ACTION_DRAG_LOCATION events to a View once the user moves the
-     * drag shadow out of the View object's bounding box. If the user moves the drag shadow back
-     * into the View object's bounding box, the View receives an ACTION_DRAG_ENTERED again before
-     * receiving any more ACTION_DRAG_LOCATION events.
+     * drag shadow out of the View object's bounding box or into a descendant view that can accept
+     * the data. If the user moves the drag shadow back into the View object's bounding box or out
+     * of a descendant view that can accept the data, the View receives an ACTION_DRAG_ENTERED again
+     * before receiving any more ACTION_DRAG_LOCATION events.
      * </p>
      * @see #ACTION_DRAG_ENTERED
      * @see #getX()
@@ -189,7 +194,8 @@
 
     /**
      * Action constant returned by {@link #getAction()}: Signals to a View that the user
-     * has released the drag shadow, and the drag point is within the bounding box of the View.
+     * has released the drag shadow, and the drag point is within the bounding box of the View and
+     * not within a descendant view that can accept the data.
      * The View should retrieve the data from the DragEvent by calling {@link #getClipData()}.
      * The methods {@link #getX()} and {@link #getY()} return the X and Y position of the drop point
      * within the View object's bounding box.
@@ -212,8 +218,10 @@
      * operation has concluded.  A View that changed its appearance during the operation should
      * return to its usual drawing state in response to this event.
      * <p>
-     * All views that received an ACTION_DRAG_STARTED event will receive the
-     * ACTION_DRAG_ENDED event even if they are not currently visible when the drag ends.
+     *  All views with listeners that returned boolean <code>true</code> for the ACTION_DRAG_STARTED
+     *  event will receive the ACTION_DRAG_ENDED event even if they are not currently visible when
+     *  the drag ends. Views removed during the drag operation won't receive the ACTION_DRAG_ENDED
+     *  event.
      * </p>
      * <p>
      *  The View object can call {@link #getResult()} to see the result of the operation.
@@ -234,9 +242,10 @@
      *  drop target.
      * </p>
      * The system stops sending ACTION_DRAG_LOCATION events to a View once the user moves the
-     * drag shadow out of the View object's bounding box. If the user moves the drag shadow back
-     * into the View object's bounding box, the View receives an ACTION_DRAG_ENTERED again before
-     * receiving any more ACTION_DRAG_LOCATION events.
+     * drag shadow out of the View object's bounding box or into a descendant view that can accept
+     * the data. If the user moves the drag shadow back into the View object's bounding box or out
+     * of a descendant view that can accept the data, the View receives an ACTION_DRAG_ENTERED again
+     * before receiving any more ACTION_DRAG_LOCATION events.
      * </p>
      * @see #ACTION_DRAG_ENTERED
      * @see #ACTION_DRAG_LOCATION
@@ -245,7 +254,8 @@
 
     /**
      * Action constant returned by {@link #getAction()}: Signals that the user has moved the
-     * drag shadow outside the bounding box of the View.
+     * drag shadow out of the bounding box of the View or into a descendant view that can accept
+     * the data.
      * The View can react by changing its appearance in a way that tells the user that
      * View is no longer the immediate drop target.
      * <p>
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 990d553..b73acda 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1289,8 +1289,9 @@
         boolean onKeyUp(int keyCode, KeyEvent event);
 
         /**
-         * Called when multiple down/up pairs of the same key have occurred
-         * in a row.
+         * Called when a user's interaction with an analog control, such as
+         * flinging a trackball, generates simulated down/up events for the same
+         * key multiple times in quick succession.
          *
          * @param keyCode The value in event.getKeyCode().
          * @param count Number of pairs as returned by event.getRepeatCount().
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 9019e87..fab5364 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -2334,6 +2334,7 @@
      * @see #getButtonState()
      * @hide
      */
+    @TestApi
     public final void setButtonState(int buttonState) {
         nativeSetButtonState(mNativePtr, buttonState);
     }
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 9f46f3f..22e68a3 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -71,6 +71,7 @@
     private static native long nativeGetNextFrameNumber(long nativeObject);
     private static native int nativeSetScalingMode(long nativeObject, int scalingMode);
     private static native void nativeSetBuffersTransform(long nativeObject, long transform);
+    private static native int nativeForceScopedDisconnect(long nativeObject);
 
     public static final Parcelable.Creator<Surface> CREATOR =
             new Parcelable.Creator<Surface>() {
@@ -550,6 +551,16 @@
         }
     }
 
+    void forceScopedDisconnect() {
+        synchronized (mLock) {
+            checkNotReleasedLocked();
+            int err = nativeForceScopedDisconnect(mNativeObject);
+            if (err != 0) {
+                throw new RuntimeException("Failed to disconnect Surface instance (bad object?)");
+            }
+        }
+    }
+
     /**
      * Returns whether or not this Surface is backed by a single-buffered SurfaceTexture
      * @hide
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 802eb19..2a2f659 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -589,6 +589,18 @@
                             for (SurfaceHolder.Callback c : callbacks) {
                                 c.surfaceDestroyed(mSurfaceHolder);
                             }
+                            // Since Android N the same surface may be reused and given to us
+                            // again by the system server at a later point. However
+                            // as we didn't do this in previous releases, clients weren't
+                            // necessarily required to clean up properly in
+                            // surfaceDestroyed. This leads to problems for example when
+                            // clients don't destroy their EGL context, and try
+                            // and create a new one on the same surface following reuse.
+                            // Since there is no valid use of the surface in-between
+                            // surfaceDestroyed and surfaceCreated, we force a disconnect,
+                            // so the next connect will always work if we end up reusing
+                            // the surface.
+                            mSurface.forceScopedDisconnect();
                         }
                     }
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d070823..d060aac 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2450,9 +2450,7 @@
      *                     1             PFLAG3_SCROLL_INDICATOR_START
      *                    1              PFLAG3_SCROLL_INDICATOR_END
      *                   1               PFLAG3_ASSIST_BLOCKED
-     *                  1                PFLAG3_POINTER_ICON_NULL
-     *                 1                 PFLAG3_POINTER_ICON_VALUE_START
-     *           11111111                PFLAG3_POINTER_ICON_MASK
+     *           xxxxxxxx                * NO LONGER NEEDED, SHOULD BE REUSED *
      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
      *        1                          PFLAG3_TEMPORARY_DETACH
@@ -2651,31 +2649,6 @@
     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
 
     /**
-     * The mask for use with private flags indicating bits used for pointer icon shapes.
-     */
-    static final int PFLAG3_POINTER_ICON_MASK = 0x7f8000;
-
-    /**
-     * Left-shift used for pointer icon shape values in private flags.
-     */
-    static final int PFLAG3_POINTER_ICON_LSHIFT = 15;
-
-    /**
-     * Value indicating no specific pointer icons.
-     */
-    private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT;
-
-    /**
-     * Value indicating {@link PointerIcon.TYPE_NULL}.
-     */
-    private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT;
-
-    /**
-     * The base value for other pointer icon shapes.
-     */
-    private static final int PFLAG3_POINTER_ICON_VALUE_START = 2 << PFLAG3_POINTER_ICON_LSHIFT;
-
-    /**
      * Whether this view has rendered elements that overlap (see {@link
      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
@@ -8057,7 +8030,7 @@
     }
 
     /**
-     * Set the enabled state of this view.
+     * Set the visibility state of this view.
      *
      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
      * @attr ref android.R.styleable#View_visibility
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 080bc32..83fc362 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -335,20 +335,17 @@
             mViews.add(view);
             mRoots.add(root);
             mParams.add(wparams);
-        }
 
-        // do this last because it fires off messages to start doing things
-        try {
-            root.setView(view, wparams, panelParentView);
-        } catch (RuntimeException e) {
-            // BadTokenException or InvalidDisplayException, clean up.
-            synchronized (mLock) {
-                final int index = findViewLocked(view, false);
+            // do this last because it fires off messages to start doing things
+            try {
+                root.setView(view, wparams, panelParentView);
+            } catch (RuntimeException e) {
+                // BadTokenException or InvalidDisplayException, clean up.
                 if (index >= 0) {
                     removeViewLocked(index, true);
                 }
+                throw e;
             }
-            throw e;
         }
     }
 
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 92ba408..aaa7b26 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -188,7 +188,7 @@
  * <p>By default, requests by the HTML to open new windows are
  * ignored. This is true whether they be opened by JavaScript or by
  * the target attribute on a link. You can customize your
- * {@link WebChromeClient} to provide your own behaviour for opening multiple windows,
+ * {@link WebChromeClient} to provide your own behavior for opening multiple windows,
  * and render them in whatever manner you want.</p>
  *
  * <p>The standard behavior for an Activity is to be destroyed and
@@ -281,7 +281,7 @@
  * <ul>
  * <li>The HTML body layout height is set to a fixed value. This means that elements with a height
  * relative to the HTML body may not be sized correctly. </li>
- * <li>For applications targetting {@link android.os.Build.VERSION_CODES#KITKAT} and earlier SDKs the
+ * <li>For applications targeting {@link android.os.Build.VERSION_CODES#KITKAT} and earlier SDKs the
  * HTML viewport meta tag will be ignored in order to preserve backwards compatibility. </li>
  * </ul>
  * </p>
@@ -596,7 +596,7 @@
 
     /**
      * Constructs a new WebView with layout parameters, a default style and a set
-     * of custom Javscript interfaces to be added to this WebView at initialization
+     * of custom JavaScript interfaces to be added to this WebView at initialization
      * time. This guarantees that these interfaces will be available when the JS
      * context is initialized.
      *
@@ -610,7 +610,7 @@
      *                             values
      * @param privateBrowsing whether this WebView will be initialized in
      *                        private mode
-     * @hide This is used internally by dumprendertree, as it requires the javaScript interfaces to
+     * @hide This is used internally by dumprendertree, as it requires the JavaScript interfaces to
      *       be added synchronously, before a subsequent loadUrl call takes effect.
      */
     protected WebView(Context context, AttributeSet attrs, int defStyleAttr,
@@ -723,7 +723,7 @@
 
     /**
      * Sets a username and password pair for the specified host. This data is
-     * used by the Webview to autocomplete username and password fields in web
+     * used by the WebView to autocomplete username and password fields in web
      * forms. Note that this is unrelated to the credentials used for HTTP
      * authentication.
      *
@@ -743,33 +743,14 @@
     /**
      * Stores HTTP authentication credentials for a given host and realm to the {@link WebViewDatabase}
      * instance.
-     * <p>
-     * To use HTTP authentication, the embedder application has to implement
-     * {@link WebViewClient#onReceivedHttpAuthRequest}, and call {@link HttpAuthHandler#proceed}
-     * with the correct username and password.
-     * <p>
-     * The embedder app can get the username and password any way it chooses, and does not have to
-     * use {@link WebViewDatabase}.
-     * <p>
-     * Notes:
-     * <li>
-     * {@link WebViewDatabase} is provided only as a convenience to store and retrieve http
-     * authentication credentials. WebView does not read from it during HTTP authentication.
-     * </li>
-     * <li>
-     * WebView does not provide a special mechanism to clear HTTP authentication credentials for
-     * implementing client logout. The client logout mechanism should be implemented by the Web site
-     * designer (such as server sending a HTTP 401 for invalidating credentials).
-     * </li>
      *
      * @param host the host to which the credentials apply
      * @param realm the realm to which the credentials apply
      * @param username the username
      * @param password the password
-     * @see #getHttpAuthUsernamePassword
-     * @see WebViewDatabase#hasHttpAuthUsernamePassword
-     * @see WebViewDatabase#clearHttpAuthUsernamePassword
+     * @deprecated Use {@link WebViewDatabase#setHttpAuthUsernamePassword} instead
      */
+    @Deprecated
     public void setHttpAuthUsernamePassword(String host, String realm,
             String username, String password) {
         checkThread();
@@ -779,16 +760,14 @@
     /**
      * Retrieves HTTP authentication credentials for a given host and realm from the {@link
      * WebViewDatabase} instance.
-     *
      * @param host the host to which the credentials apply
      * @param realm the realm to which the credentials apply
      * @return the credentials as a String array, if found. The first element
      *         is the username and the second element is the password. Null if
      *         no credentials are found.
-     * @see #setHttpAuthUsernamePassword
-     * @see WebViewDatabase#hasHttpAuthUsernamePassword
-     * @see WebViewDatabase#clearHttpAuthUsernamePassword
+     * @deprecated Use {@link WebViewDatabase#getHttpAuthUsernamePassword} instead
      */
+    @Deprecated
     public String[] getHttpAuthUsernamePassword(String host, String realm) {
         checkThread();
         return mProvider.getHttpAuthUsernamePassword(host, realm);
@@ -926,7 +905,7 @@
      *            value. Note that if this map contains any of the headers
      *            that are set by default by this WebView, such as those
      *            controlling caching, accept types or the User-Agent, their
-     *            values may be overriden by this WebView's defaults.
+     *            values may be overridden by this WebView's defaults.
      */
     public void loadUrl(String url, Map<String, String> additionalHttpHeaders) {
         checkThread();
@@ -1047,7 +1026,7 @@
      * @param script the JavaScript to execute.
      * @param resultCallback A callback to be invoked when the script execution
      *                       completes with the result of the execution (if any).
-     *                       May be null if no notificaion of the result is required.
+     *                       May be null if no notification of the result is required.
      */
     public void evaluateJavascript(String script, ValueCallback<String> resultCallback) {
         checkThread();
@@ -1118,7 +1097,7 @@
     /**
      * Gets whether this WebView has a forward history item.
      *
-     * @return true iff this Webview has a forward history item
+     * @return true iff this WebView has a forward history item
      */
     public boolean canGoForward() {
         checkThread();
@@ -1192,14 +1171,14 @@
      * Posts a {@link VisualStateCallback}, which will be called when
      * the current state of the WebView is ready to be drawn.
      *
-     * <p>Because updates to the the DOM are processed asynchronously, updates to the DOM may not
+     * <p>Because updates to the DOM are processed asynchronously, updates to the DOM may not
      * immediately be reflected visually by subsequent {@link WebView#onDraw} invocations. The
      * {@link VisualStateCallback} provides a mechanism to notify the caller when the contents of
      * the DOM at the current time are ready to be drawn the next time the {@link WebView}
      * draws.</p>
      *
      * <p>The next draw after the callback completes is guaranteed to reflect all the updates to the
-     * DOM up to the the point at which the {@link VisualStateCallback} was posted, but it may also
+     * DOM up to the point at which the {@link VisualStateCallback} was posted, but it may also
      * contain updates applied after the callback was posted.</p>
      *
      * <p>The state of the DOM covered by this API includes the following:
@@ -1232,7 +1211,7 @@
      * </ul></p>
      *
      * <p>When using this API it is also recommended to enable pre-rasterization if the {@link
-     * WebView} is offscreen to avoid flickering. See {@link WebSettings#setOffscreenPreRaster} for
+     * WebView} is off screen to avoid flickering. See {@link WebSettings#setOffscreenPreRaster} for
      * more details and do consider its caveats.</p>
      *
      * @param requestId An id that will be returned in the callback to allow callers to match
@@ -1297,11 +1276,11 @@
     }
 
     /**
-     * Creates a PrintDocumentAdapter that provides the content of this Webview for printing.
+     * Creates a PrintDocumentAdapter that provides the content of this WebView for printing.
      *
-     * The adapter works by converting the Webview contents to a PDF stream. The Webview cannot
+     * The adapter works by converting the WebView contents to a PDF stream. The WebView cannot
      * be drawn during the conversion process - any such draws are undefined. It is recommended
-     * to use a dedicated off screen Webview for the printing. If necessary, an application may
+     * to use a dedicated off screen WebView for the printing. If necessary, an application may
      * temporarily hide a visible WebView by using a custom PrintDocumentAdapter instance
      * wrapped around the object returned and observing the onStart and onFinish methods. See
      * {@link android.print.PrintDocumentAdapter} for more information.
@@ -1336,7 +1315,7 @@
      * {@link WebSettings#getUseWideViewPort()} and
      * {@link WebSettings#getLoadWithOverviewMode()}.
      * If the content fits into the WebView control by width, then
-     * the zoom is set to 100%. For wide content, the behavor
+     * the zoom is set to 100%. For wide content, the behavior
      * depends on the state of {@link WebSettings#getLoadWithOverviewMode()}.
      * If its value is true, the content will be zoomed out to be fit
      * by width into the WebView control, otherwise not.
@@ -1613,10 +1592,10 @@
 
     /**
      * Clears the client certificate preferences stored in response
-     * to proceeding/cancelling client cert requests. Note that Webview
+     * to proceeding/cancelling client cert requests. Note that WebView
      * automatically clears these preferences when it receives a
      * {@link KeyChain#ACTION_STORAGE_CHANGED} intent. The preferences are
-     * shared by all the webviews that are created by the embedder application.
+     * shared by all the WebViews that are created by the embedder application.
      *
      * @param onCleared  A runnable to be invoked when client certs are cleared.
      *                   The embedder can pass null if not interested in the
@@ -1672,7 +1651,7 @@
      * Notifies any registered {@link FindListener}.
      *
      * @param find the string to find
-     * @return the number of occurances of the String "find" that were found
+     * @return the number of occurrences of the String "find" that were found
      * @deprecated {@link #findAllAsync} is preferred.
      * @see #setFindListener
      */
@@ -2087,7 +2066,7 @@
     /**
      * Performs a zoom operation in this WebView.
      *
-     * @param zoomFactor the zoom factor to apply. The zoom factor will be clamped to the Webview's
+     * @param zoomFactor the zoom factor to apply. The zoom factor will be clamped to the WebView's
      * zoom limits. This value must be in the range 0.01 to 100.0 inclusive.
      */
     public void zoomBy(float zoomFactor) {
@@ -2152,7 +2131,7 @@
 
     /**
      * Gets the WebViewProvider. Used by providers to obtain the underlying
-     * implementation, e.g. when the appliction responds to
+     * implementation, e.g. when the application responds to
      * WebViewClient.onCreateWindow() request.
      *
      * @hide WebViewProvider is not public API.
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index cc2c6cc..87d3c7b 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -65,8 +65,8 @@
      * Gets whether there are any saved credentials for HTTP authentication.
      *
      * @return whether there are any saved credentials
-     * @see WebView#getHttpAuthUsernamePassword
-     * @see WebView#setHttpAuthUsernamePassword
+     * @see #getHttpAuthUsernamePassword
+     * @see #setHttpAuthUsernamePassword
      * @see #clearHttpAuthUsernamePassword
      */
     public abstract boolean hasHttpAuthUsernamePassword();
@@ -83,13 +83,61 @@
      * mechanism should be implemented by the Web site designer (such as server sending a HTTP 401
      * for invalidating credentials).
      *
-     * @see WebView#getHttpAuthUsernamePassword
-     * @see WebView#setHttpAuthUsernamePassword
+     * @see #getHttpAuthUsernamePassword
+     * @see #setHttpAuthUsernamePassword
      * @see #hasHttpAuthUsernamePassword
      */
     public abstract void clearHttpAuthUsernamePassword();
 
     /**
+     * Stores HTTP authentication credentials for a given host and realm to the {@link WebViewDatabase}
+     * instance.
+     * <p>
+     * To use HTTP authentication, the embedder application has to implement
+     * {@link WebViewClient#onReceivedHttpAuthRequest}, and call {@link HttpAuthHandler#proceed}
+     * with the correct username and password.
+     * <p>
+     * The embedder app can get the username and password any way it chooses, and does not have to
+     * use {@link WebViewDatabase}.
+     * <p>
+     * Notes:
+     * <li>
+     * {@link WebViewDatabase} is provided only as a convenience to store and retrieve http
+     * authentication credentials. WebView does not read from it during HTTP authentication.
+     * </li>
+     * <li>
+     * WebView does not provide a special mechanism to clear HTTP authentication credentials for
+     * implementing client logout. The client logout mechanism should be implemented by the Web site
+     * designer (such as server sending a HTTP 401 for invalidating credentials).
+     * </li>
+     *
+     * @param host the host to which the credentials apply
+     * @param realm the realm to which the credentials apply
+     * @param username the username
+     * @param password the password
+     * @see #getHttpAuthUsernamePassword
+     * @see #hasHttpAuthUsernamePassword
+     * @see #clearHttpAuthUsernamePassword
+     */
+    public abstract void setHttpAuthUsernamePassword(String host, String realm,
+            String username, String password);
+
+   /**
+     * Retrieves HTTP authentication credentials for a given host and realm from the {@link
+     * WebViewDatabase} instance.
+     *
+     * @param host the host to which the credentials apply
+     * @param realm the realm to which the credentials apply
+     * @return the credentials as a String array, if found. The first element
+     *         is the username and the second element is the password. Null if
+     *         no credentials are found.
+     * @see #setHttpAuthUsernamePassword
+     * @see #hasHttpAuthUsernamePassword
+     * @see #clearHttpAuthUsernamePassword
+     */
+    public abstract String[] getHttpAuthUsernamePassword(String host, String realm);
+
+    /**
      * Gets whether there is any saved data for web forms.
      *
      * @return whether there is any saved data for web forms
diff --git a/core/java/android/widget/Button.java b/core/java/android/widget/Button.java
index 154cc33..09e09b7 100644
--- a/core/java/android/widget/Button.java
+++ b/core/java/android/widget/Button.java
@@ -18,6 +18,8 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.PointerIcon;
 import android.widget.RemoteViews.RemoteView;
 
 
@@ -113,4 +115,12 @@
     public CharSequence getAccessibilityClassName() {
         return Button.class.getName();
     }
+
+    @Override
+    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
+        if (getPointerIcon() == null && isClickable() && isEnabled()) {
+            return PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_HAND);
+        }
+        return super.onResolvePointerIcon(event, pointerIndex);
+    }
 }
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index e196cf0..80f25d4 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -18,7 +18,9 @@
 
 import com.android.internal.R;
 
+import android.annotation.IntDef;
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.annotation.Widget;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -33,6 +35,8 @@
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Locale;
 
 /**
@@ -76,11 +80,36 @@
  */
 @Widget
 public class DatePicker extends FrameLayout {
-    private static final int MODE_SPINNER = 1;
-    private static final int MODE_CALENDAR = 2;
+    /**
+     * Presentation mode for the Holo-style date picker that uses a set of
+     * {@link android.widget.NumberPicker}s.
+     *
+     * @see #getMode()
+     * @hide Visible for testing only.
+     */
+    @TestApi
+    public static final int MODE_SPINNER = 1;
+
+    /**
+     * Presentation mode for the Material-style date picker that uses a
+     * calendar.
+     *
+     * @see #getMode()
+     * @hide Visible for testing only.
+     */
+    @TestApi
+    public static final int MODE_CALENDAR = 2;
+
+    /** @hide */
+    @IntDef({MODE_SPINNER, MODE_CALENDAR})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DatePickerMode {}
 
     private final DatePickerDelegate mDelegate;
 
+    @DatePickerMode
+    private final int mMode;
+
     /**
      * The callback used to indicate the user changed the date.
      */
@@ -115,11 +144,20 @@
 
         final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker,
                 defStyleAttr, defStyleRes);
-        final int mode = a.getInt(R.styleable.DatePicker_datePickerMode, MODE_SPINNER);
+        final boolean isDialogMode = a.getBoolean(R.styleable.DatePicker_dialogMode, false);
+        final int requestedMode = a.getInt(R.styleable.DatePicker_datePickerMode, MODE_SPINNER);
         final int firstDayOfWeek = a.getInt(R.styleable.DatePicker_firstDayOfWeek, 0);
         a.recycle();
 
-        switch (mode) {
+        if (requestedMode == MODE_CALENDAR && isDialogMode) {
+            // You want MODE_CALENDAR? YOU CAN'T HANDLE MODE_CALENDAR! Well,
+            // maybe you can depending on your screen size. Let's check...
+            mMode = context.getResources().getInteger(R.integer.date_picker_mode);
+        } else {
+            mMode = requestedMode;
+        }
+
+        switch (mMode) {
             case MODE_CALENDAR:
                 mDelegate = createCalendarUIDelegate(context, attrs, defStyleAttr, defStyleRes);
                 break;
@@ -146,6 +184,18 @@
     }
 
     /**
+     * @return the picker's presentation mode, one of {@link #MODE_CALENDAR} or
+     *         {@link #MODE_SPINNER}
+     * @attr ref android.R.styleable#DatePicker_datePickerMode
+     * @hide Visible for testing only.
+     */
+    @DatePickerMode
+    @TestApi
+    public int getMode() {
+        return mMode;
+    }
+
+    /**
      * Initialize the state. If the provided values designate an inconsistent
      * date the values are normalized before updating the spinners.
      *
diff --git a/core/java/android/widget/ImageButton.java b/core/java/android/widget/ImageButton.java
index 332b158..e1b0c91 100644
--- a/core/java/android/widget/ImageButton.java
+++ b/core/java/android/widget/ImageButton.java
@@ -18,6 +18,8 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.PointerIcon;
 import android.widget.RemoteViews.RemoteView;
 
 /**
@@ -94,4 +96,12 @@
     public CharSequence getAccessibilityClassName() {
         return ImageButton.class.getName();
     }
+
+    @Override
+    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
+        if (getPointerIcon() == null && isClickable() && isEnabled()) {
+            return PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_HAND);
+        }
+        return super.onResolvePointerIcon(event, pointerIndex);
+    }
 }
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index aa67c82..d9cb269 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -1441,7 +1441,9 @@
     /**
      * Returns the alpha that will be applied to the drawable of this ImageView.
      *
-     * @return the alpha that will be applied to the drawable of this ImageView
+     * @return the alpha value that will be applied to the drawable of this
+     * ImageView (between 0 and 255 inclusive, with 0 being transparent and
+     * 255 being opaque)
      *
      * @see #setImageAlpha(int)
      */
@@ -1452,7 +1454,8 @@
     /**
      * Sets the alpha value that should be applied to the image.
      *
-     * @param alpha the alpha value that should be applied to the image
+     * @param alpha the alpha value that should be applied to the image (between
+     * 0 and 255 inclusive, with 0 being transparent and 255 being opaque)
      *
      * @see #getImageAlpha()
      */
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index 6f198e7..5a0e1f9 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.view.PointerIcon;
 import com.android.internal.R;
 import com.android.internal.widget.ExploreByTouchHelper;
 
@@ -1052,6 +1053,18 @@
         invalidate();
     }
 
+    @Override
+    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
+        if (!isEnabled()) {
+            return null;
+        }
+        final int degrees = getDegreesFromXY(event.getX(), event.getY(), false);
+        if (degrees != -1) {
+            return PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_HAND);
+        }
+        return super.onResolvePointerIcon(event, pointerIndex);
+    }
+
     private class RadialPickerTouchHelper extends ExploreByTouchHelper {
         private final Rect mTempRect = new Rect();
 
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index 3a63e28..8c43782 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.view.PointerIcon;
 import com.android.internal.R;
 import com.android.internal.widget.ExploreByTouchHelper;
 
@@ -1025,6 +1026,21 @@
         return true;
     }
 
+    @Override
+    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
+        if (!isEnabled()) {
+            return null;
+        }
+        // Add 0.5f to event coordinates to match the logic in onTouchEvent.
+        final int x = (int) (event.getX() + 0.5f);
+        final int y = (int) (event.getY() + 0.5f);
+        final int dayUnderPointer = getDayAtLocation(x, y);
+        if (dayUnderPointer >= 0) {
+            return PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_HAND);
+        }
+        return super.onResolvePointerIcon(event, pointerIndex);
+    }
+
     /**
      * Provides a virtual view hierarchy for interfacing with an accessibility
      * service.
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index e2df402..dc5e5a2 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.TestApi;
+import android.view.PointerIcon;
 import com.android.internal.R;
 import com.android.internal.view.menu.ShowableListMenu;
 
@@ -903,6 +904,14 @@
         }
     }
 
+    @Override
+    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
+        if (getPointerIcon() == null && isClickable() && isEnabled()) {
+            return PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_HAND);
+        }
+        return super.onResolvePointerIcon(event, pointerIndex);
+    }
+
     static class SavedState extends AbsSpinner.SavedState {
         boolean showDropdown;
 
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index eb81e6f..d51c5be 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -65,6 +65,9 @@
  * {@link #setSwitchTextAppearance(android.content.Context, int) switchTextAppearance} and
  * the related setSwitchTypeface() methods control that of the thumb.
  *
+ * <p>{@link android.support.v7.widget.SwitchCompat} is a version of
+ * the Switch widget which runs on devices back to API 7.</p>
+ *
  * <p>See the <a href="{@docRoot}guide/topics/ui/controls/togglebutton.html">Toggle Buttons</a>
  * guide.</p>
  *
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index 20b771b..1f0cb7c 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -16,6 +16,8 @@
 
 package android.widget;
 
+import android.view.MotionEvent;
+import android.view.PointerIcon;
 import com.android.internal.R;
 
 import android.annotation.DrawableRes;
@@ -494,6 +496,10 @@
         child.setFocusable(true);
         child.setClickable(true);
 
+        if (child.getPointerIcon() == null) {
+            child.setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_HAND));
+        }
+
         super.addView(child);
 
         // TODO: detect this via geometry with a tabwidget listener rather
@@ -507,6 +513,14 @@
         mSelectedTab = -1;
     }
 
+    @Override
+    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
+        if (!isEnabled()) {
+            return null;
+        }
+        return super.onResolvePointerIcon(event, pointerIndex);
+    }
+
     /**
      * Provides a way for {@link TabHost} to be notified that the user clicked
      * on a tab indicator.
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index ce6400e9..5264d5c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3242,6 +3242,10 @@
      * Sets the text color for all the states (normal, selected,
      * focused) to be this color.
      *
+     * @param color A color value in the form 0xAARRGGBB.
+     * Do not pass a resource ID. To get a color value from a resource ID, call
+     * {@link android.support.v4.content.ContextCompat#getColor(Context, int) getColor}.
+     *
      * @see #setTextColor(ColorStateList)
      * @see #getTextColors()
      *
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index e2d1415..6a76c5b 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -18,6 +18,7 @@
 
 import com.android.internal.R;
 
+import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.TestApi;
@@ -31,6 +32,8 @@
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Locale;
 
 import libcore.icu.LocaleData;
@@ -46,11 +49,36 @@
  */
 @Widget
 public class TimePicker extends FrameLayout {
-    private static final int MODE_SPINNER = 1;
-    private static final int MODE_CLOCK = 2;
+    /**
+     * Presentation mode for the Holo-style time picker that uses a set of
+     * {@link android.widget.NumberPicker}s.
+     *
+     * @see #getMode()
+     * @hide Visible for testing only.
+     */
+    @TestApi
+    public static final int MODE_SPINNER = 1;
+
+    /**
+     * Presentation mode for the Material-style time picker that uses a clock
+     * face.
+     *
+     * @see #getMode()
+     * @hide Visible for testing only.
+     */
+    @TestApi
+    public static final int MODE_CLOCK = 2;
+
+    /** @hide */
+    @IntDef({MODE_SPINNER, MODE_CLOCK})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface TimePickerMode {}
 
     private final TimePickerDelegate mDelegate;
 
+    @TimePickerMode
+    private final int mMode;
+
     /**
      * The callback interface used to indicate the time has been adjusted.
      */
@@ -81,10 +109,19 @@
 
         final TypedArray a = context.obtainStyledAttributes(
                 attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes);
-        final int mode = a.getInt(R.styleable.TimePicker_timePickerMode, MODE_SPINNER);
+        final boolean isDialogMode = a.getBoolean(R.styleable.TimePicker_dialogMode, false);
+        final int requestedMode = a.getInt(R.styleable.TimePicker_timePickerMode, MODE_SPINNER);
         a.recycle();
 
-        switch (mode) {
+        if (requestedMode == MODE_CLOCK && isDialogMode) {
+            // You want MODE_CLOCK? YOU CAN'T HANDLE MODE_CLOCK! Well, maybe
+            // you can depending on your screen size. Let's check...
+            mMode = context.getResources().getInteger(R.integer.time_picker_mode);
+        } else {
+            mMode = requestedMode;
+        }
+
+        switch (mMode) {
             case MODE_CLOCK:
                 mDelegate = new TimePickerClockDelegate(
                         this, context, attrs, defStyleAttr, defStyleRes);
@@ -98,6 +135,18 @@
     }
 
     /**
+     * @return the picker's presentation mode, one of {@link #MODE_CLOCK} or
+     *         {@link #MODE_SPINNER}
+     * @attr ref android.R.styleable#TimePicker_timePickerMode
+     * @hide Visible for testing only.
+     */
+    @TimePickerMode
+    @TestApi
+    public int getMode() {
+        return mMode;
+    }
+
+    /**
      * Sets the currently selected hour using 24-hour time.
      *
      * @param hour the hour to set, in the range (0-23)
diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java
index 03a3a38..4d4c7ce 100644
--- a/core/java/com/android/internal/app/ResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverComparator.java
@@ -157,7 +157,10 @@
 
         // We want to put the one targeted to another user at the end of the dialog.
         if (lhs.targetUserId != UserHandle.USER_CURRENT) {
-            return 1;
+            return rhs.targetUserId != UserHandle.USER_CURRENT ? 0 : 1;
+        }
+        if (rhs.targetUserId != UserHandle.USER_CURRENT) {
+            return -1;
         }
 
         if (mHttp) {
diff --git a/core/java/com/android/internal/os/BaseCommand.java b/core/java/com/android/internal/os/BaseCommand.java
index c067da7..3baccee 100644
--- a/core/java/com/android/internal/os/BaseCommand.java
+++ b/core/java/com/android/internal/os/BaseCommand.java
@@ -36,6 +36,8 @@
     public static final String NO_SYSTEM_ERROR_CODE = "Error type 2";
     public static final String NO_CLASS_ERROR_CODE = "Error type 3";
 
+    private String[] mRawArgs;
+
     /**
      * Call to run the command.
      */
@@ -45,7 +47,8 @@
             return;
         }
 
-        mArgs.init(null, null, null, null, args, 0);
+        mRawArgs = args;
+        mArgs.init(null, null, null, null, args, null, 0);
 
         try {
             onRun();
@@ -109,4 +112,11 @@
     public String nextArgRequired() {
         return mArgs.getNextArgRequired();
     }
+
+    /**
+     * Return the original raw argument list supplied to the command.
+     */
+    public String[] getRawArgs() {
+        return mRawArgs;
+    }
 }
diff --git a/core/java/android/accounts/IAccountAccessTracker.aidl b/core/java/com/android/internal/os/IShellCallback.aidl
similarity index 63%
copy from core/java/android/accounts/IAccountAccessTracker.aidl
copy to core/java/com/android/internal/os/IShellCallback.aidl
index e12b3d1..57d6789 100644
--- a/core/java/android/accounts/IAccountAccessTracker.aidl
+++ b/core/java/com/android/internal/os/IShellCallback.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
+/**
+ * Copyright (c) 2016, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     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,
@@ -14,13 +14,11 @@
  * limitations under the License.
  */
 
-package android.accounts;
+package com.android.internal.os;
 
-/**
- * Interface to track which apps accessed an account
- *
- * @hide
- */
-oneway interface IAccountAccessTracker {
-    void onAccountAccessed();
+import android.os.ParcelFileDescriptor;
+
+/** @hide */
+interface IShellCallback {
+    ParcelFileDescriptor openOutputFile(String path, String seLinuxContext);
 }
diff --git a/core/java/com/android/internal/policy/EmergencyAffordanceManager.java b/core/java/com/android/internal/policy/EmergencyAffordanceManager.java
new file mode 100644
index 0000000..bed7c1ba
--- /dev/null
+++ b/core/java/com/android/internal/policy/EmergencyAffordanceManager.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.policy;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.provider.Settings;
+
+/**
+ * A class that manages emergency affordances and enables immediate calling to emergency services
+ */
+public class EmergencyAffordanceManager {
+
+    public static final boolean ENABLED = true;
+
+    /**
+     * Global setting override with the number to call with the emergency affordance.
+     * @hide
+     */
+    private static final String EMERGENCY_CALL_NUMBER_SETTING = "emergency_affordance_number";
+
+    /**
+     * Global setting, whether the emergency affordance should be shown regardless of device state.
+     * The value is a boolean (1 or 0).
+     * @hide
+     */
+    private static final String FORCE_EMERGENCY_AFFORDANCE_SETTING = "force_emergency_affordance";
+
+    private final Context mContext;
+
+    public EmergencyAffordanceManager(Context context) {
+        mContext = context;
+    }
+
+    /**
+     * perform an emergency call.
+     */
+    public final void performEmergencyCall() {
+        performEmergencyCall(mContext);
+    }
+
+    private static Uri getPhoneUri(Context context) {
+        String number = context.getResources().getString(
+                com.android.internal.R.string.config_emergency_call_number);
+        if (Build.IS_DEBUGGABLE) {
+            String override = Settings.Global.getString(
+                    context.getContentResolver(), EMERGENCY_CALL_NUMBER_SETTING);
+            if (override != null) {
+                number = override;
+            }
+        }
+        return Uri.fromParts("tel", number, null);
+    }
+
+    private static void performEmergencyCall(Context context) {
+        Intent intent = new Intent(Intent.ACTION_CALL_EMERGENCY);
+        intent.setData(getPhoneUri(context));
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        context.startActivity(intent);
+    }
+
+    /**
+     * @return whether emergency affordance should be active.
+     */
+    public boolean needsEmergencyAffordance() {
+        if (!ENABLED) {
+            return false;
+        }
+        if (forceShowing()) {
+            return true;
+        }
+        return isEmergencyAffordanceNeeded();
+    }
+
+    private boolean isEmergencyAffordanceNeeded() {
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.EMERGENCY_AFFORDANCE_NEEDED, 0) != 0;
+    }
+
+
+    private boolean forceShowing() {
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                FORCE_EMERGENCY_AFFORDANCE_SETTING, 0) != 0;
+    }
+}
diff --git a/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java
index 2cb9c25..fb0edea 100644
--- a/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java
+++ b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java
@@ -150,6 +150,7 @@
                         sendCloseSystemWindows();
                         // Broadcast an intent that the Camera button was longpressed
                         Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null);
+                        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                         intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
                         mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF,
                                 null, null, null, 0, null, null);
diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java
index 1203dd2..effe219 100644
--- a/core/java/com/android/internal/view/FloatingActionMode.java
+++ b/core/java/com/android/internal/view/FloatingActionMode.java
@@ -59,15 +59,19 @@
 
     private final Runnable mMovingOff = new Runnable() {
         public void run() {
-            mFloatingToolbarVisibilityHelper.setMoving(false);
-            mFloatingToolbarVisibilityHelper.updateToolbarVisibility();
+            if (isViewStillActive()) {
+                mFloatingToolbarVisibilityHelper.setMoving(false);
+                mFloatingToolbarVisibilityHelper.updateToolbarVisibility();
+            }
         }
     };
 
     private final Runnable mHideOff = new Runnable() {
         public void run() {
-            mFloatingToolbarVisibilityHelper.setHideRequested(false);
-            mFloatingToolbarVisibilityHelper.updateToolbarVisibility();
+            if (isViewStillActive()) {
+                mFloatingToolbarVisibilityHelper.setHideRequested(false);
+                mFloatingToolbarVisibilityHelper.updateToolbarVisibility();
+            }
         }
     };
 
@@ -301,6 +305,11 @@
         mOriginatingView.removeCallbacks(mHideOff);
     }
 
+    private boolean isViewStillActive() {
+        return mOriginatingView.getWindowVisibility() == View.VISIBLE
+                && mOriginatingView.isShown();
+    }
+
     /**
      * A helper for showing/hiding the floating toolbar depending on certain states.
      */
diff --git a/core/java/com/android/internal/widget/ImageFloatingTextView.java b/core/java/com/android/internal/widget/ImageFloatingTextView.java
index 926ebd1..358be60 100644
--- a/core/java/com/android/internal/widget/ImageFloatingTextView.java
+++ b/core/java/com/android/internal/widget/ImageFloatingTextView.java
@@ -40,6 +40,9 @@
     /** Number of lines from the top to indent */
     private int mIndentLines;
 
+    /** Resolved layout direction */
+    private int mResolvedDirection = LAYOUT_DIRECTION_UNDEFINED;
+
     public ImageFloatingTextView(Context context) {
         this(context, null);
     }
@@ -82,7 +85,7 @@
                 margins[i] = endMargin;
             }
         }
-        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+        if (mResolvedDirection == LAYOUT_DIRECTION_RTL) {
             builder.setIndents(margins, null);
         } else {
             builder.setIndents(null, margins);
@@ -91,6 +94,19 @@
         return builder.build();
     }
 
+    @Override
+    public void onRtlPropertiesChanged(int layoutDirection) {
+        super.onRtlPropertiesChanged(layoutDirection);
+
+        if (layoutDirection != mResolvedDirection && isLayoutDirectionResolved()) {
+            mResolvedDirection = layoutDirection;
+            if (mIndentLines > 0) {
+                // Invalidate layout.
+                setHint(getHint());
+            }
+        }
+    }
+
     @RemotableViewMethod
     public void setHasImage(boolean hasImage) {
         setNumIndentLines(hasImage ? 2 : 0);
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 1e6b125..c4c1511 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -25,6 +25,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
+#include <sys/system_properties.h>
 
 #include <private/android_filesystem_config.h> // for AID_SYSTEM
 
@@ -41,6 +42,7 @@
 #include "ScopedUtfChars.h"
 #include "utils/Log.h"
 #include "utils/misc.h"
+#include "utils/String8.h"
 
 extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
 extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
@@ -184,11 +186,19 @@
                 argv[argc++] = AssetManager::TARGET_APK_PATH;
                 argv[argc++] = AssetManager::IDMAP_DIR;
 
-                // Directories to scan for overlays
-                // /vendor/overlay
-                if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
+                // Directories to scan for overlays: if OVERLAY_SUBDIR_PROPERTY is defined,
+                // use OVERLAY_SUBDIR/<value of OVERLAY_SUBDIR_PROPERTY>/ if exists, otherwise
+                // use OVERLAY_DIR if exists.
+                char subdir[PROP_VALUE_MAX];
+                int len = __system_property_get(AssetManager::OVERLAY_SUBDIR_PROPERTY, subdir);
+                if (len > 0) {
+                    String8 subdirPath = String8(AssetManager::OVERLAY_SUBDIR) + "/" + subdir;
+                    if (stat(subdirPath.string(), &st) == 0) {
+                        argv[argc++] = subdirPath.string();
+                    }
+                } else if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
                     argv[argc++] = AssetManager::OVERLAY_DIR;
-                 }
+                }
 
                 // Finally, invoke idmap (if any overlay directory exists)
                 if (argc > 5) {
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 5637dbc..3f2b924 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -487,6 +487,11 @@
     return surface->setScalingMode(scalingMode);
 }
 
+static jint nativeForceScopedDisconnect(JNIEnv *env, jclass clazz, jlong nativeObject) {
+    Surface* surface = reinterpret_cast<Surface*>(nativeObject);
+    return surface->disconnect(-1, IGraphicBufferProducer::DisconnectMode::AllLocal);
+}
+
 namespace uirenderer {
 
 using namespace android::uirenderer::renderthread;
@@ -564,6 +569,7 @@
     {"nativeGetHeight", "(J)I", (void*)nativeGetHeight },
     {"nativeGetNextFrameNumber", "(J)J", (void*)nativeGetNextFrameNumber },
     {"nativeSetScalingMode", "(JI)I", (void*)nativeSetScalingMode },
+    {"nativeForceScopedDisconnect", "(J)I", (void*)nativeForceScopedDisconnect},
 
     // HWUI context
     {"nHwuiCreate", "(JJ)J", (void*) hwui::create },
diff --git a/core/jni/fd_utils-inl.h b/core/jni/fd_utils-inl.h
index c67662b..5c17b23 100644
--- a/core/jni/fd_utils-inl.h
+++ b/core/jni/fd_utils-inl.h
@@ -20,6 +20,7 @@
 #include <vector>
 #include <algorithm>
 
+#include <android-base/strings.h>
 #include <dirent.h>
 #include <fcntl.h>
 #include <grp.h>
@@ -241,7 +242,8 @@
 
   // Returns true iff. a given path is whitelisted. A path is whitelisted
   // if it belongs to the whitelist (see kPathWhitelist) or if it's a path
-  // under /system/framework that ends with ".jar".
+  // under /system/framework that ends with ".jar" or if it is a system
+  // framework overlay.
   static bool IsWhitelisted(const std::string& path) {
     for (size_t i = 0; i < (sizeof(kPathWhitelist) / sizeof(kPathWhitelist[0])); ++i) {
       if (kPathWhitelist[i] == path) {
@@ -249,12 +251,37 @@
       }
     }
 
-    static const std::string kFrameworksPrefix = "/system/framework/";
-    static const std::string kJarSuffix = ".jar";
-    if (path.compare(0, kFrameworksPrefix.size(), kFrameworksPrefix) == 0 &&
-        path.compare(path.size() - kJarSuffix.size(), kJarSuffix.size(), kJarSuffix) == 0) {
+    static const char* kFrameworksPrefix = "/system/framework/";
+    static const char* kJarSuffix = ".jar";
+    if (android::base::StartsWith(path, kFrameworksPrefix)
+        && android::base::EndsWith(path, kJarSuffix)) {
       return true;
     }
+
+    // Whitelist files needed for Runtime Resource Overlay, like these:
+    // /system/vendor/overlay/framework-res.apk
+    // /system/vendor/overlay-subdir/pg/framework-res.apk
+    // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap
+    // /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap
+    // See AssetManager.cpp for more details on overlay-subdir.
+    static const char* kOverlayDir = "/system/vendor/overlay/";
+    static const char* kOverlaySubdir = "/system/vendor/overlay-subdir/";
+    static const char* kApkSuffix = ".apk";
+
+    if ((android::base::StartsWith(path, kOverlayDir)
+            || android::base::StartsWith(path, kOverlaySubdir))
+        && android::base::EndsWith(path, kApkSuffix)
+        && path.find("/../") == std::string::npos) {
+      return true;
+    }
+
+    static const char* kOverlayIdmapPrefix = "/data/resource-cache/";
+    static const char* kOverlayIdmapSuffix = ".apk@idmap";
+    if (android::base::StartsWith(path, kOverlayIdmapPrefix)
+        && android::base::EndsWith(path, kOverlayIdmapSuffix)) {
+      return true;
+    }
+
     return false;
   }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 099622c..357d6f9 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3126,7 +3126,7 @@
                  android:killAfterRestore="false"
                  android:icon="@drawable/ic_launcher_android"
                  android:supportsRtl="true"
-                 android:theme="@style/Theme.Material.Light.DarkActionBar"
+                 android:theme="@style/Theme.DeviceDefault.Light.DarkActionBar"
                  android:defaultToDeviceProtectedStorage="true"
                  android:directBootAware="true">
         <activity android:name="com.android.internal.app.ChooserActivity"
@@ -3163,7 +3163,7 @@
                 android:label="@string/managed_profile_label">
         </activity-alias>
         <activity android:name="com.android.internal.app.HeavyWeightSwitcherActivity"
-                android:theme="@style/Theme.Material.Light.Dialog"
+                android:theme="@style/Theme.DeviceDefault.Light.Dialog"
                 android:label="@string/heavy_weight_switcher_title"
                 android:finishOnCloseSystemDialogs="true"
                 android:excludeFromRecents="true"
@@ -3196,7 +3196,7 @@
         <activity android:name="android.accounts.ChooseAccountActivity"
                 android:excludeFromRecents="true"
                 android:exported="true"
-                android:theme="@style/Theme.Material.Light.Dialog"
+                android:theme="@style/Theme.DeviceDefault.Light.Dialog"
                 android:label="@string/choose_account_label"
                 android:process=":ui">
         </activity>
@@ -3204,14 +3204,14 @@
         <activity android:name="android.accounts.ChooseTypeAndAccountActivity"
                 android:excludeFromRecents="true"
                 android:exported="true"
-                android:theme="@style/Theme.Material.Light.Dialog"
+                android:theme="@style/Theme.DeviceDefault.Light.Dialog"
                 android:label="@string/choose_account_label"
                 android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.ChooseAccountTypeActivity"
                 android:excludeFromRecents="true"
-                android:theme="@style/Theme.Material.Light.Dialog"
+                android:theme="@style/Theme.DeviceDefault.Light.Dialog"
                 android:label="@string/choose_account_label"
                 android:process=":ui">
         </activity>
@@ -3219,19 +3219,19 @@
         <activity android:name="android.accounts.CantAddAccountActivity"
                 android:excludeFromRecents="true"
                 android:exported="true"
-                android:theme="@style/Theme.Material.Light.Dialog.NoActionBar"
+                android:theme="@style/Theme.DeviceDefault.Light.Dialog.NoActionBar"
                 android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.GrantCredentialsPermissionActivity"
                 android:excludeFromRecents="true"
                 android:exported="true"
-                android:theme="@style/Theme.Material.Light.DialogWhenLarge"
+                android:theme="@style/Theme.DeviceDefault.Light.DialogWhenLarge"
                 android:process=":ui">
         </activity>
 
         <activity android:name="android.content.SyncActivityTooManyDeletes"
-               android:theme="@style/Theme.Material.Light.Dialog"
+               android:theme="@style/Theme.DeviceDefault.Light.Dialog"
                android:label="@string/sync_too_many_deletes"
                android:process=":ui">
         </activity>
@@ -3251,7 +3251,7 @@
         </activity>
 
         <activity android:name="com.android.internal.app.NetInitiatedActivity"
-                android:theme="@style/Theme.Material.Light.Dialog.Alert"
+                android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
                 android:excludeFromRecents="true"
                 android:process=":ui">
         </activity>
@@ -3272,7 +3272,7 @@
         <activity android:name="com.android.internal.app.ConfirmUserCreationActivity"
                 android:excludeFromRecents="true"
                 android:process=":ui"
-                android:theme="@style/Theme.Material.Light.Dialog.Alert">
+                android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert">
             <intent-filter android:priority="1000">
                 <action android:name="android.os.action.CREATE_USER" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -3280,7 +3280,7 @@
         </activity>
 
         <activity android:name="com.android.internal.app.UnlaunchableAppActivity"
-                android:theme="@style/Theme.Material.Light.Dialog.Alert"
+                android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
                 android:excludeFromRecents="true"
                 android:process=":ui">
         </activity>
diff --git a/core/res/res/drawable-watch/ic_input_extract_action_done.xml b/core/res/res/drawable-watch/ic_input_extract_action_done.xml
new file mode 100644
index 0000000..a04b944
--- /dev/null
+++ b/core/res/res/drawable-watch/ic_input_extract_action_done.xml
@@ -0,0 +1,19 @@
+<!--
+     Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector android:height="22dp" android:viewportHeight="22.0"
+    android:viewportWidth="22.0" android:width="22dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FFFFFF" android:pathData="M9.25,14.82L5.43,11l-1.3,1.3 5.12,5.12 11,-11 -1.3,-1.3 -9.7,9.7z"/>
+</vector>
diff --git a/core/res/res/drawable-watch/ic_input_extract_action_send.xml b/core/res/res/drawable-watch/ic_input_extract_action_send.xml
new file mode 100644
index 0000000..3689172
--- /dev/null
+++ b/core/res/res/drawable-watch/ic_input_extract_action_send.xml
@@ -0,0 +1,24 @@
+<!--
+     Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="22dp"
+        android:height="22dp"
+        android:viewportWidth="22.0"
+        android:viewportHeight="22.0">
+    <path
+        android:pathData="M2.77,19.32L22,11.07 2.78,2.82v6.42l13.74,1.83L2.77,12.9v6.42z"
+        android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/core/res/res/drawable/emergency_icon.xml b/core/res/res/drawable/emergency_icon.xml
new file mode 100644
index 0000000..b2ffa2b
--- /dev/null
+++ b/core/res/res/drawable/emergency_icon.xml
@@ -0,0 +1,40 @@
+<!--
+Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M6.8,17.3C5.3,15.9 4.5,14.0 4.5,12.0c0.0,-2.0 0.8,-3.8 2.1,-5.2l1.4,1.4c-1.0,1.0 -1.6,2.4 -1.6,3.8c0.0,1.5 0.6,2.9 1.6,3.9L6.8,17.3z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M3.3,20.2C1.2,18.0 0.0,15.1 0.0,12.0c0.0,-3.1 1.2,-6.0 3.3,-8.2l1.4,1.4C3.0,7.0 2.0,9.4 2.0,12.0s1.0,5.0 2.7,6.9L3.3,20.2z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M17.2,17.3l-1.4,-1.4c1.1,-1.0 1.6,-2.4 1.6,-3.9c0.0,-1.4 -0.6,-2.8 -1.6,-3.8l1.4,-1.4c1.4,1.4 2.1,3.3 2.1,5.2C19.5,14.0 18.7,15.9 17.2,17.3z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M20.7,20.2l-1.4,-1.4C21.0,17.0 22.0,14.6 22.0,12.0c0.0,-2.6 -1.0,-5.0 -2.7,-6.9l1.4,-1.4C22.8,6.0 24.0,8.9 24.0,12.0C24.0,15.1 22.8,18.0 20.7,20.2z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M11.0,15.0l2.0,0.0l0.0,2.0l-2.0,0.0z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M11.0,7.0l2.0,0.0l0.0,6.0l-2.0,0.0z"/>
+</vector>
diff --git a/core/res/res/layout-land/time_picker_material.xml b/core/res/res/layout-land/time_picker_material.xml
index 7a0c38f..70833d6 100644
--- a/core/res/res/layout-land/time_picker_material.xml
+++ b/core/res/res/layout-land/time_picker_material.xml
@@ -61,6 +61,7 @@
                 android:ellipsize="none"
                 android:gravity="right"
                 android:focusable="true"
+                android:pointerIcon="hand"
                 android:nextFocusForward="@+id/minutes" />
 
             <TextView
@@ -83,6 +84,7 @@
                 android:ellipsize="none"
                 android:gravity="left"
                 android:focusable="true"
+                android:pointerIcon="hand"
                 android:nextFocusForward="@+id/am_label" />
         </LinearLayout>
 
diff --git a/core/res/res/layout-sw600dp/date_picker_dialog.xml b/core/res/res/layout-sw600dp/date_picker_dialog.xml
index 5e3ca14..cd6af46 100644
--- a/core/res/res/layout-sw600dp/date_picker_dialog.xml
+++ b/core/res/res/layout-sw600dp/date_picker_dialog.xml
@@ -22,4 +22,4 @@
     android:layout_height="wrap_content"
     android:spinnersShown="true"
     android:calendarViewShown="true"
-    android:datePickerMode="@integer/date_picker_mode" />
+    android:dialogMode="true" />
diff --git a/core/res/res/layout-watch/input_method_extract_view.xml b/core/res/res/layout-watch/input_method_extract_view.xml
index 038b766..3478bb5 100644
--- a/core/res/res/layout-watch/input_method_extract_view.xml
+++ b/core/res/res/layout-watch/input_method_extract_view.xml
@@ -49,7 +49,7 @@
             android:layout_width="@dimen/input_extract_action_button_width"
             android:layout_height="@dimen/input_extract_action_button_width"
             android:background="@drawable/input_extract_action_bg_material_dark"
-            android:padding="4dp"
+            android:padding="@dimen/input_extract_action_icon_padding"
             android:scaleType="centerInside" />
     </FrameLayout>
 </android.inputmethodservice.CompactExtractEditLayout>
diff --git a/core/res/res/layout/date_picker_dialog.xml b/core/res/res/layout/date_picker_dialog.xml
index 8f36e95..32a7360 100644
--- a/core/res/res/layout/date_picker_dialog.xml
+++ b/core/res/res/layout/date_picker_dialog.xml
@@ -22,4 +22,4 @@
     android:layout_height="wrap_content"
     android:spinnersShown="true"
     android:calendarViewShown="false"
-    android:datePickerMode="@integer/date_picker_mode" />
+    android:dialogMode="true" />
diff --git a/core/res/res/layout/date_picker_header_material.xml b/core/res/res/layout/date_picker_header_material.xml
index 755317e..81f08fd9 100644
--- a/core/res/res/layout/date_picker_header_material.xml
+++ b/core/res/res/layout/date_picker_header_material.xml
@@ -45,6 +45,7 @@
             android:padding="8dp"
             android:background="?attr/selectableItemBackground"
             android:textAppearance="@style/TextAppearance.Material.DatePicker.YearLabel"
+            android:pointerIcon="hand"
             android:nextFocusForward="@+id/prev" />
 
         <TextView
@@ -55,6 +56,7 @@
             android:includeFontPadding="false"
             android:gravity="start"
             android:maxLines="@integer/date_picker_header_max_lines_material"
+            android:pointerIcon="hand"
             android:ellipsize="none" />
     </LinearLayout>
 </LinearLayout>
diff --git a/core/res/res/layout/time_picker_dialog.xml b/core/res/res/layout/time_picker_dialog.xml
index d1f3902..ada18d1 100644
--- a/core/res/res/layout/time_picker_dialog.xml
+++ b/core/res/res/layout/time_picker_dialog.xml
@@ -22,4 +22,4 @@
     android:layout_gravity="center_horizontal"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:timePickerMode="@integer/time_picker_mode" />
+    android:dialogMode="true" />
diff --git a/core/res/res/layout/time_picker_header_material.xml b/core/res/res/layout/time_picker_header_material.xml
index 8fd87b8..ced1722 100644
--- a/core/res/res/layout/time_picker_header_material.xml
+++ b/core/res/res/layout/time_picker_header_material.xml
@@ -38,6 +38,7 @@
         android:ellipsize="none"
         android:gravity="right"
         android:focusable="true"
+        android:pointerIcon="hand"
         android:nextFocusForward="@+id/minutes" />
 
     <TextView
@@ -64,6 +65,7 @@
         android:ellipsize="none"
         android:gravity="left"
         android:focusable="true"
+        android:pointerIcon="hand"
         android:nextFocusForward="@+id/am_label" />
 
     <!-- The layout alignment of this view will switch between toRightOf
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 1961843..34244ab 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Foonopsies"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Skermslot"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Sit af"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Foutverslag"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Neem foutverslag"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Dit sal inligting oor die huidige toestand van jou toestel insamel om as \'n e-posboodskap te stuur. Dit sal \'n tydjie neem vandat die foutverslag begin is totdat dit reg is om gestuur te word; wees asseblief geduldig."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g>-USB-datastokkie"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-berging"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Redigeer"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Dataverbruik-waarskuwing"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Tik om gebruik en instellings te bekyk."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G-datalimiet bereik"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G-datalimiet bereik"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index e332cee1..b3cd896 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"የስልክ አማራጮች"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"ማያ ቆልፍ"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"ኃይል አጥፋ"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"የሳንካ ሪፖርት"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"የሳንካ ሪፖርት ውሰድ"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ይሄ እንደ የኢሜይል መልዕክት አድርጎ የሚልከውን ስለመሣሪያዎ የአሁኑ ሁኔታ መረጃ ይሰበስባል። የሳንካ ሪፖርቱን ከመጀመር ጀምሮ እስኪላክ ድረስ ትንሽ ጊዜ ይወስዳል፤ እባክዎ ይታገሱ።"</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"የ<xliff:g id="MANUFACTURER">%s</xliff:g> ዩኤስቢ አንጻፊ"</string>
     <string name="storage_usb" msgid="3017954059538517278">"የUSB  ማከማቻ"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"አርትዕ"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"የውሂብ አጠቃቀም ማስጠንቀቂየ"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"አጠቃቀምን እና ቅንብሮችን ለማየት መታ ያድርጉ።"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"የ2ጂ-3ጂ ውሂብ ገደብ ላይ ተደርሷል"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"የ4ጂ ውሂብ ገደብ ላይ ተደርሷል"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 388ae0f..717e9da 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"خيارات الهاتف"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"تأمين الشاشة"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"إيقاف التشغيل"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"تقرير الأخطاء"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"إعداد تقرير بالأخطاء"</string>
     <string name="bugreport_message" msgid="398447048750350456">"سيجمع هذا معلومات حول حالة جهازك الحالي لإرسالها كرسالة إلكترونية، ولكنه سيستغرق وقتًا قليلاً من بدء عرض تقرير بالأخطاء. وحتى يكون جاهزًا للإرسال، الرجاء الانتظار."</string>
@@ -1432,7 +1434,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"‏محرك أقراص USB من <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"‏وحدة تخزين USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"تعديل"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"تحذير استخدام البيانات"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"انقر لعرض الاستخدام والإعدادات."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"‏تم بلوغ حد بيانات اتصال 2G-3G"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"‏تم بلوغ حد بيانات اتصال 4G"</string>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 3e84f7a..5ff1373 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefon seçimləri"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Ekran kilidi"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Söndür"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Baq hesabatı"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Baqı xəbər verin"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Bu, sizin hazırkı cihaz durumu haqqında məlumat toplayacaq ki, elektron məktub şəklində göndərsin. Baq raportuna başlamaq üçün bir az vaxt lazım ola bilər, bir az səbr edin."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB drayv"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB yaddaş"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Düzəliş edin"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Data istifadə xəbərdarlığı"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"İstifadə və ayarları görmək üçün tıklayın."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G data limitinə çatdı"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G data limitinə çatdı"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 53fc741..a351d5c 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -216,6 +216,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opcije telefona"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Zaključaj ekran"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Isključi"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Izveštaj o grešci"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Napravi izveštaj o grešci"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Ovim će se prikupiti informacije o trenutnom stanju uređaja kako bi bile poslate u poruci e-pošte. Od započinjanja izveštaja o grešci do trenutka za njegovo slanje proći će neko vreme; budite strpljivi."</string>
@@ -256,9 +258,9 @@
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Skladište"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"pristupa slikama, medijima i datotekama na uređaju"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
-    <string name="permgroupdesc_microphone" msgid="4988812113943554584">"snima audio snimke"</string>
+    <string name="permgroupdesc_microphone" msgid="4988812113943554584">"snima audio"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
-    <string name="permgroupdesc_camera" msgid="3250611594678347720">"snima slike i video snimke"</string>
+    <string name="permgroupdesc_camera" msgid="3250611594678347720">"snima slike i video"</string>
     <string name="permgrouplab_phone" msgid="5229115638567440675">"Telefon"</string>
     <string name="permgroupdesc_phone" msgid="6234224354060641055">"upućuje telefonske pozive i upravlja njima"</string>
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Senzori za telo"</string>
@@ -1354,7 +1356,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB disk"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB memorija"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Izmeni"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Upozorenje o potrošnji podataka"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Dodirnite za potrošnju i podešavanja."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Nema više 2G-3G podataka"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Nema više 4G podataka"</string>
diff --git a/core/res/res/values-be-rBY/strings.xml b/core/res/res/values-be-rBY/strings.xml
index 1ba2345..13a9cdcef 100644
--- a/core/res/res/values-be-rBY/strings.xml
+++ b/core/res/res/values-be-rBY/strings.xml
@@ -218,6 +218,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Параметры тэлефона"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Блакіроўка экрана"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Выключыць"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Справаздача пра памылкі"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Справаздача пра памылку"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Будзе збiрацца iнфармацыя пра бягучы стан прылады, якая будзе адпраўляцца на электронную пошту. Стварэнне справаздачы пра памылкi зойме некаторы час."</string>
@@ -1380,7 +1382,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"USB-дыск <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-назапашвальнік"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Рэдагаваць"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Папярэджанне выкарыстання дадзеных"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Прагляд выкарыстання і налад."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Дасягнуты ліміт трафіку 2G-3G"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Дасягнуты ліміт трафіку 4G"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 7dfd94c..95e89af 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Опции на телефона"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Заключване на екрана"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Изключване"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Сигнал за програмна грешка"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Сигнал за програмна грешка"</string>
     <string name="bugreport_message" msgid="398447048750350456">"По този начин ще се събере информация за текущото състояние на устройството ви, която да се изпрати като имейл съобщение. След стартирането на процеса ще мине известно време, докато сигналът за програмна грешка бъде готов за подаване. Моля, имайте търпение."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"USB устройство от <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB хранилище"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Редактиране"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Предупрежд. за ползване на данни"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Пренос и настройки: Докоснете за преглед."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Достигнат лимит за 2G/3G данните"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Достигнат лимит за 4G данните"</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 1a67dfa..25f3367 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"ফোন বিকল্পগুলি"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"স্ক্রীণ লক"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"পাওয়ার বন্ধ করুন"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"ত্রুটির প্রতিবেদন"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"ত্রুটির অভিযোগ করুন"</string>
     <string name="bugreport_message" msgid="398447048750350456">"এটি একটি ই-মেল বার্তা পাঠানোর জন্য আপনার ডিভাইসের বর্তমান অবস্থা সম্পর্কে তথ্য সংগ্রহ করবে৷ ত্রুটির প্রতিবেদন শুরুর সময় থেকে এটি পাঠানোর জন্য প্রস্তুত হতে কিছুটা সময় নেবে; দয়া করে ধৈর্য রাখুন৷"</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB ড্রাইভ"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB সঞ্চয়স্থান"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"সম্পাদনা করুন"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"ডেটা ব্যবহারের সতর্কতা"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"ব্যবহার এবং সেটিংস দেখতে আলতো চাপুন৷"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G ডেটা সীমা ছাড়িয়েছে"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G ডেটা সীমা ছাড়িয়েছে"</string>
diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml
index 9519215..e786ff9 100644
--- a/core/res/res/values-bs-rBA/strings.xml
+++ b/core/res/res/values-bs-rBA/strings.xml
@@ -216,6 +216,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opcije telefona"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Zaključavanje ekrana"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Isključi telefon"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Izvještaj o greškama"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Kreirajte izvještaj o greškama"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Ovim će se prikupljati informacije o trenutnom stanju uređaja, koji će biti poslani kao poruka e-pošte. Može malo potrajati dok se izvještaj o greškama ne kreira i bude spreman za slanje. Budite strpljivi."</string>
@@ -1356,7 +1358,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB disk"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB pohrana"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Uredi"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Upozorenje za prijenos podataka"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Dodirnite za prikaz upotrebe i postavki."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Dostignut limit za 2G-3G podatke"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Dostignut limit za 4G podatke"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index baf4080..ac0b6d3 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opcions del telèfon"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Bloqueig de pantalla"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Apaga"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Informe d\'error"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Crea informe d\'errors"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Es recopilarà informació sobre l\'estat actual del dispositiu i se t\'enviarà per correu electrònic. Passaran uns quants minuts des de l\'inici de l\'informe d\'errors fins al seu enviament, per la qual cosa et recomanem que tinguis paciència."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Unitat USB de: <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Emmagatzematge USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Edita"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Advertiment d\'ús de dades"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Toca per veure l\'ús i la configuració."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Límit de dades 2G-3G assolit"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Límit de dades 4G assolit"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 9a6526e..4370d9f 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -218,6 +218,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Možnosti telefonu"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Zámek obrazovky"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Vypnout"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Hlášení chyb"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Vytvořit chybové hlášení"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Shromažďuje informace o aktuálním stavu zařízení. Tyto informace je následně možné poslat v e-mailové zprávě, chvíli však potrvá, než bude hlášení o chybě připraveno k odeslání. Buďte prosím trpěliví."</string>
@@ -1380,7 +1382,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Jednotka USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Úložiště USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Upravit"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Upozornění na využití dat"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Klepnutím zobrazíte nastavení."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Dosáhli jste limitu dat 2G–3G"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Dosáhli jste limitu dat 4G"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 8edd692..1688cbe 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Indstillinger for telefon"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Skærmlås"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Sluk"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Fejlrapport"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Lav fejlrapport"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Der indsamles oplysninger om din enheds aktuelle status, der efterfølgende sendes i en e-mail. Der går lidt tid, fra fejlrapporten påbegyndes, til den er klar til at blive sendt. Tak for tålmodigheden."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"USB-drev fra <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-lager"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Rediger"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Advarsel om dataforbrug"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Tryk for at se forbrug og indstillinger."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Grænsen for 2G-3G-data er nået"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Grænsen for 4G-data er nået"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index b2765d5..d13777b 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefonoptionen"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Displaysperre"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Ausschalten"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Fehlerbericht"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Fehlerbericht abrufen"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Bei diesem Fehlerbericht werden Daten zum aktuellen Status deines Geräts erfasst und als E-Mail versandt. Vom Start des Berichts bis zu seinem Versand kann es eine Weile dauern. Bitte habe etwas Geduld."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"USB-Speichergerät von <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-Speicher"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Bearbeiten"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Warnung zum Datenverbrauch"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Für Nutzung und Einstellungen tippen."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-/3G-Datenlimit erreicht"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G-Datenlimit erreicht"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 2b0c4a7..8f63a73 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Επιλογές τηλεφώνου"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Κλείδωμα οθόνης"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Απενεργοποίηση"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Αναφορά σφαλμάτων"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Λήψη αναφοράς σφάλματος"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Θα συλλέξει πληροφορίες σχετικά με την τρέχουσα κατάσταση της συσκευής σας και θα τις στείλει μέσω μηνύματος ηλεκτρονικού ταχυδρομείου. Απαιτείται λίγος χρόνος για τη σύνταξη της αναφοράς σφάλματος και την αποστολή της. Κάντε λίγη υπομονή."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Μονάδα USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Αποθηκευτικός χώρος USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Επεξεργασία"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Προειδοποίηση χρήσης δεδομένων"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Πατήστε για προβολή χρήσης/ρυθμ."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Συμπλ. το όριο δεδομένων 2G-3G"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Συμπλ. το όριο δεδομένων 4G"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 8be6295..348a7de56 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Phone options"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Screen lock"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Power off"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Bug report"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Take bug report"</string>
     <string name="bugreport_message" msgid="398447048750350456">"This will collect information about your current device state, to send as an email message. It will take a little time from starting the bug report until it is ready to be sent. Please be patient."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB drive"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB storage"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Edit"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Data usage warning"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Tap to view usage and settings."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G data limit reached"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G data limit reached"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 8be6295..348a7de56 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Phone options"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Screen lock"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Power off"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Bug report"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Take bug report"</string>
     <string name="bugreport_message" msgid="398447048750350456">"This will collect information about your current device state, to send as an email message. It will take a little time from starting the bug report until it is ready to be sent. Please be patient."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB drive"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB storage"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Edit"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Data usage warning"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Tap to view usage and settings."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G data limit reached"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G data limit reached"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 8be6295..348a7de56 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Phone options"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Screen lock"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Power off"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Bug report"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Take bug report"</string>
     <string name="bugreport_message" msgid="398447048750350456">"This will collect information about your current device state, to send as an email message. It will take a little time from starting the bug report until it is ready to be sent. Please be patient."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB drive"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB storage"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Edit"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Data usage warning"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Tap to view usage and settings."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G data limit reached"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G data limit reached"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index f293d29..39746e0 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opciones de dispositivo"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Bloqueo de pantalla"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Apagar"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Informe de errores"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Iniciar informe de errores"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Se recopilará información sobre el estado actual de tu dispositivo, que se enviará por correo. Pasarán unos minutos desde que se inicie el informe de errores hasta que se envíe, por lo que te recomendamos que tengas paciencia."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Unidad USB de <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Almacenamiento USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Editar"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Advertencia de uso de datos"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Presiona para uso y opciones."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Límite de datos 2G-3G alcanzado"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Límite de datos 4G alcanzado"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 5760e12..117205f 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opciones del teléfono"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Bloqueo de pantalla"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Apagar"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Informe de error"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Crear informe de errores"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Se recopilará información sobre el estado actual de tu dispositivo y se enviará por correo electrónico. Pasarán unos minutos desde que empiece a generarse el informe de errores hasta que se envíe."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Unidad USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Almacenamiento USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Editar"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Advertencia de uso de datos"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Toca para ver uso y ajustes."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Límite de datos 2G-3G alcanzado"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Límite de datos 4G alcanzado"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 5066ce1..2fadecb 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefonivalikud"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Ekraanilukk"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Lülita välja"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Veaaruanne"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Veaaruande võtmine"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Nii kogutakse teavet teie seadme praeguse oleku kohta, et saata see meilisõnumina. Enne kui saate veaaruande ära saata, võtab selle loomine natuke aega; varuge kannatust."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Tootja <xliff:g id="MANUFACTURER">%s</xliff:g> USB-ketas"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-mäluseade"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Muuda"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Andmete kasutamise hoiatus"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Puudutage kasutuse/seadete vaat."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-, 3G-andmeside limiit on täis"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G-andmeside limiit on täis"</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 0a6c753..6179987 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefonoaren aukerak"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Pantailaren blokeoa"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Itzali"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Akatsen txostena"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Sortu akatsen txostena"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Gailuaren uneko egoerari buruzko informazioa bilduko da, mezu elektroniko gisa bidaltzeko. Minutu batzuk igaroko dira akatsen txostena sortzen hasten denetik bidaltzeko prest egon arte. Itxaron, mesedez."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB unitatea"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB memoria"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Editatu"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Datuen erabilerari buruzko abisua"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Sakatu erabilera eta ezarpenak ikusteko."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2-3 GB-ko mugara iritsi zara"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4 GB-ko mugara iritsi zara"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 35589b0..fd2bf81 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"گزینه‌های تلفن"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"قفل صفحه"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"خاموش کردن"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"گزارش اشکال"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"گرفتن گزارش اشکال"</string>
     <string name="bugreport_message" msgid="398447048750350456">"این گزارش اطلاعات مربوط به وضعیت دستگاه کنونی شما را جمع‌آوری می‌کند تا به صورت یک پیام رایانامه ارسال شود. از زمان شروع گزارش اشکال تا آماده شدن برای ارسال اندکی زمان می‌برد؛ لطفاً شکیبا باشید."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"‏درایو USB ‏<xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"‏حافظهٔ USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"ویرایش"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"هشدار میزان استفاده از داده"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"برای مشاهده مصرف و تنظیمات ضربه بزنید."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"‏به حد مجاز مصرف داده 2G-3G رسید"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"‏به حد مجاز مصرف داده 4G رسید"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 07afcf6..3ea7e66 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Puhelimen asetukset"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Näytön lukitus"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Katkaise virta"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Virheraportti"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Luo virheraportti"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Toiminto kerää tietoja laitteen tilasta ja lähettää ne sähköpostitse. Virheraportti on valmis lähetettäväksi hetken kuluttua - kiitos kärsivällisyydestäsi."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"USB-asema: <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-tallennustila"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Muokkaa"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Tiedonsiirtovaroitus"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Käyttö &amp; asetukset napauttamalla"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G-tietojen raja saavutettu"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G-tietojen raja saavutettu"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index bf7e3dd..8b74244 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Options du téléphone"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Verrouillage de l\'écran"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Éteindre"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Rapport de bogue"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Créer un rapport de bogue"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Cela permet de recueillir des informations concernant l\'état actuel de votre appareil. Ces informations sont ensuite envoyées sous forme de courriel. Merci de patienter pendant la préparation du rapport de bogue. Cette opération peut prendre quelques instants."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Clé USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Mémoire de stockage USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Modifier"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Avertissement utilisation données"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Touch. pour aff. util. et param."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Limite de données 2G-3G atteinte"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Limite de données 4G atteinte"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 28073a8..8c8c683 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Options du téléphone"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Verrouillage de l\'écran"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Éteindre"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Rapport de bug"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Créer un rapport de bug"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Cela permet de recueillir des informations concernant l\'état actuel de votre appareil. Ces informations sont ensuite envoyées sous forme d\'e-mail. Merci de patienter pendant la préparation du rapport de bug. Cette opération peut prendre quelques instants."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Clé USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Mémoire de stockage USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Modifier"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Avertissement utilisation données"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Appuyez pour conso/paramètres."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Limite de données 2G-3G atteinte"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Limite de données 4G atteinte"</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index ea94f6a..f842df2 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opcións de teléfono"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Bloqueo da pantalla"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Apagar"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Informe de erros"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Crear informe de erros"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Este informe recompilará información acerca do estado actual do teu dispositivo para enviala en forma de mensaxe de correo electrónico. O informe de erros tardará un pouco en completarse desde o seu inicio ata que estea preparado para enviarse, polo que che recomendamos que teñas paciencia."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Unidade USB de <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"almacenamento USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Editar"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Aviso de uso de datos"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Toca para uso e configuración."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Límite de datos de 2G-3G acadado"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Límite de datos de 4G acadado"</string>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index b3af1f1..45038b0 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"ફોન વિકલ્પો"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"સ્ક્રીન લૉક"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"પાવર બંધ"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"બગ રિપોર્ટ"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"બગ રિપોર્ટ લો"</string>
     <string name="bugreport_message" msgid="398447048750350456">"આ, એક ઇ-મેઇલ સંદેશ તરીકે મોકલવા માટે, તમારા વર્તમાન ઉપકરણ સ્થિતિ વિશેની માહિતી એકત્રિત કરશે. એક બગ રિપોર્ટ પ્રારંભ કરીને તે મોકલવા માટે તૈયાર ન થઈ જાય ત્યાં સુધી તેમાં થોડો સમય લાગશે; કૃપા કરીને ધીરજ રાખો."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB ડ્રાઇવ"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB સંગ્રહ"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"સંપાદિત કરો"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"ડેટા વપરાશ ચેતવણી"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"વપરાશ અને સેટિંગ્સ જોવા ટૅપ કરો."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G ડેટા મર્યાદા પર પહોંચ્યાં"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G ડેટા મર્યાદા સુધી પહોંચ્યાં"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 6a093965..8a651bd 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"फ़ोन विकल्‍प"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"स्‍क्रीन लॉक"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"पावर बंद"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"बग रिपोर्ट"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"बग रिपोर्ट प्राप्त करें"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ईमेल संदेश के रूप में भेजने के लिए, इसके द्वारा आपके डिवाइस की वर्तमान स्थिति के बारे में जानकारी एकत्र की जाएगी. बग रिपोर्ट प्रारंभ करने से लेकर भेजने के लिए तैयार होने तक कुछ समय लगेगा; कृपया धैर्य रखें."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB डिस्‍क"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB मेमोरी"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"संपादित करें"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"डेटा उपयोग की चेतावनी"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"उपयोग व सेटिंग देखने हेतु टैप करें."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G डेटा सीमा पूर्ण हो गई"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G डेटा सीमा पूर्ण हो गई"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index b28ea1c..16a304f 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -216,6 +216,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opcije telefona"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Zaključavanje zaslona"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Isključi"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Izvješće o bugovima"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Izvješće o programskoj pogrešci"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Time će se prikupiti podaci o trenutačnom stanju vašeg uređaja koje ćete nam poslati u e-poruci. Za pripremu izvješća o programskoj pogrešci potrebno je nešto vremena pa vas molimo za strpljenje."</string>
@@ -1354,7 +1356,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB pogon"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB pohrana"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Uredi"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Upozorenje o upotrebi podataka"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Dodirnite za upotrebu i postavke"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Dost. ogr. 2G–3G prijenosa pod."</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Dost. ogr. 4G prijenosa podataka"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 470f17f..cbb72a7 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefonbeállítások"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Képernyő lezárása"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Kikapcsolás"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Programhiba bejelentése"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Hibajelentés készítése"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Ezzel információt fog gyűjteni az eszköz jelenlegi állapotáról, amelyet a rendszer e-mailben fog elküldeni. Kérjük, legyen türelemmel, amíg a hibajelentés elkészül, és küldhető állapotba kerül."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB-meghajtó"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-tár"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Szerkesztés"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Adathasználati figyelmeztetés"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Koppintson az adatokért."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-/3G-adatkorlát elérve"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G-adatkorlát elérve"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index b0f0f51..ae83552a 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Հեռախոսի ընտրանքներ"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Էկրանի փական"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Անջատել"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Վրիպակի զեկույց"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Գրել սխալի զեկույց"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Սա տեղեկություններ կհավաքագրի ձեր սարքի առկա կարգավիճակի մասին և կուղարկի այն էլեկտրոնային նամակով: Որոշակի ժամանակ կպահանջվի վրիպակի մասին զեկուցելու պահից սկսած մինչ ուղարկելը: Խնդրում ենք փոքր-ինչ համբերատար լինել:"</string>
@@ -249,17 +251,17 @@
     <string name="permgrouplab_calendar" msgid="5863508437783683902">"Օրացույց"</string>
     <string name="permgroupdesc_calendar" msgid="3889615280211184106">"օգտագործել օրացույցը"</string>
     <string name="permgrouplab_sms" msgid="228308803364967808">"Կարճ հաղորդագրություն"</string>
-    <string name="permgroupdesc_sms" msgid="4656988620100940350">"ուղարկել և դիտել SMS հաղորդագրությունները"</string>
+    <string name="permgroupdesc_sms" msgid="4656988620100940350">"ուղարկել և դիտել SMS հաղորդ․-ները"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Պահոց"</string>
-    <string name="permgroupdesc_storage" msgid="637758554581589203">"օգտագործել լուսանկարները, մեդիա ֆայլերը և ձեր սարքում պահվող այլ ֆայլերը"</string>
+    <string name="permgroupdesc_storage" msgid="637758554581589203">"օգտագործել լուսանկարները, մեդիա ֆայլերը և ձեր սարքում պահվող մյուս ֆայլերը"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Բարձրախոս"</string>
-    <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ձայնագրում"</string>
+    <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ձայնագրել"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Ֆոտոխցիկ"</string>
-    <string name="permgroupdesc_camera" msgid="3250611594678347720">"լուսանկարում և տեսագրում"</string>
+    <string name="permgroupdesc_camera" msgid="3250611594678347720">"լուսանկարել և տեսագրել"</string>
     <string name="permgrouplab_phone" msgid="5229115638567440675">"Հեռախոս"</string>
-    <string name="permgroupdesc_phone" msgid="6234224354060641055">"հեռախոսազանգերի կատարում և կառավարում"</string>
+    <string name="permgroupdesc_phone" msgid="6234224354060641055">"կատարել զանգեր և կառավարել զանգերը"</string>
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Մարմնի սենսորներ"</string>
-    <string name="permgroupdesc_sensors" msgid="7147968539346634043">"օգտագործել ձեր հիմնական ֆիզիոլոգիական ցուցանիշների վերաբերյալ սենսորի տվյալները"</string>
+    <string name="permgroupdesc_sensors" msgid="7147968539346634043">"օգտագործել սենսորների տվյալները ձեր օրգանիզմի վիճակի մասին"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Առբերել պատուհանի բովանդակությունը"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Ստուգեք պատուհանի բովանդակությունը, որի հետ փոխգործակցում եք:"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Միացնել Հպման միջոցով հետազոտումը"</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"USB սարքավար <xliff:g id="MANUFACTURER">%s</xliff:g>-ից"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB կրիչ"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Խմբագրել"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Տվյալների օգտագործման նախազգուշացում"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Հպեք և տեսեք օգտագործումը և կարգավորումները:"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G տվյալների սահմանաչափը սպառվել է"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G տվյալների սահմանաչափը սպառվել է"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 35c489a..b6f6c4d 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opsi telepon"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Kunci layar"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Matikan daya"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Laporan bug"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Ambil laporan bug"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Ini akan mengumpulkan informasi status perangkat Anda saat ini, untuk dikirimkan sebagai pesan email. Harap bersabar, mungkin perlu waktu untuk memulai laporan bug hingga siap dikirim."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Drive USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Penyimpanan USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Edit"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Peringatan penggunaan data"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Ketuk untuk lihat penggunaan &amp; setelan."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Batas data 2G-3G terlampaui"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Batas data 4G terlampaui"</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 59b3ecb..5cce18b 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Valkostir síma"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Skjálás"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Slökkva"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Villutilkynning"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Útbúa villutilkynningu"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Þetta safnar upplýsingum um núverandi stöðu tækisins til að senda með tölvupósti. Það tekur smástund frá því villutilkynningin er ræst og þar til hún er tilbúin til sendingar – sýndu biðlund."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"USB-drif frá <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-geymsla"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Breyta"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Viðvörun vegna gagnanotkunar"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Ýttu fyrir uppl. og stillingar"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Gagnahámarki 2G og 3G náð"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Gagnahámarki 4G náð"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 9c0f6b7..13c17ce 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opzioni telefono"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Blocco schermo"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Spegni"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Segnalazione di bug"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Apri segnalazione bug"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Verranno raccolte informazioni sullo stato corrente del dispositivo che saranno inviate sotto forma di messaggio email. Passerà un po\' di tempo prima che la segnalazione di bug aperta sia pronta per essere inviata; ti preghiamo di avere pazienza."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Unità USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Archivio USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Modifica"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Avviso sull\'utilizzo dei dati"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Tocca per uso e impostazioni."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Limite di dati 2G-3G raggiunto"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Limite di dati 4G raggiunto"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 466d574..87ec61a 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -218,6 +218,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"אפשרויות טלפון"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"נעילת מסך"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"כיבוי"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"דיווח על באג"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"שלח דיווח על באג"</string>
     <string name="bugreport_message" msgid="398447048750350456">"פעולה זו תאסוף מידע על מצב המכשיר הנוכחי שלך על מנת לשלוח אותו כהודעת אימייל. היא תימשך זמן קצר מרגע פתיחת דיווח הבאג ועד לשליחת ההודעה בפועל. אנא המתן בסבלנות."</string>
@@ -1380,7 +1382,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"‏כונן USB של <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"‏אחסון USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"ערוך"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"אזהרת שימוש בנתונים"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"הקש כדי להציג נתוני שימוש והגדרות."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"‏הגעת למגבלת הנתונים של 2G-3G"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"‏הגעת למגבלת הנתונים של 4G"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index ddd6e83..213c064 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"携帯電話オプション"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"画面ロック"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"電源を切る"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"バグレポート"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"バグレポートを取得"</string>
     <string name="bugreport_message" msgid="398447048750350456">"現在の端末の状態に関する情報が収集され、その内容がメールで送信されます。バグレポートが開始してから送信可能な状態となるまでには多少の時間がかかりますのでご了承ください。"</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g>製USBドライブ"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USBストレージ"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"編集"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"データ使用の警告"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"タップして使用状況と設定を表示します。"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G~3Gデータの上限に達しました"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4Gデータの上限に達しました"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 3acc952..315ff64 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"ტელეფონის პარამეტრები"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"ეკრანის დაბლოკვა"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"კვების გამორთვა"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"ხარვეზის შესახებ ანგარიში"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"შექმენით შეცდომის ანგარიში"</string>
     <string name="bugreport_message" msgid="398447048750350456">"იგი შეაგროვებს ინფორმაციას თქვენი მოწყობილობის ამჟამინდელი მდგომარეობის შესახებ, რათა ის ელფოსტის შეტყობინების სახით გააგზავნოს. ხარვეზის ანგარიშის მომზადებასა და შეტყობინების გაგზავნას გარკვეული დრო სჭირდება. გთხოვთ, მოითმინოთ."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB დისკი"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB მეხსიერება"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"რედაქტირება"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"ინტერნეტის გამოყენების გაფრთხილება"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"შეეხეთ მოხმარებისა და პარამეტრების სანახავად."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G მონაცემთა ლიმიტი ამოიწურა"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G მონაცემთა ლიმიტი ამოიწურა"</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index c63d772..525fbee 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Телефон опциялары"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Экранды құлыптау"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Өшіру"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Вирус туралы хабарлау"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Қате туралы есеп құру"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Құрылғының қазіргі күйі туралы ақпаратты жинап, электрондық хабармен жібереді. Есеп әзір болғанша біраз уақыт кетеді, шыдай тұрыңыз."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB дискі"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB жады"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Өзгерту"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Дерекқор қолдануға қатысты ескерту"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Трафик пен параметрлерді көру үшін түртіңіз."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G деректер шегіне жеттіңіз"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G деректер шегіне жеттіңіз"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 9f24460..014d844 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"ជម្រើស​ទូរស័ព្ទ"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"ចាក់​សោ​អេក្រង់"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"បិទ"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"របាយការណ៍​កំហុស"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"យក​របាយការណ៍​កំហុស"</string>
     <string name="bugreport_message" msgid="398447048750350456">"វា​នឹង​​ប្រមូល​ព័ត៌មាន​អំពី​ស្ថានភាព​ឧបករណ៍​របស់​អ្នក ដើម្បី​ផ្ញើ​ជា​សារ​អ៊ីមែល។ វា​នឹង​ចំណាយ​ពេល​តិច​ពី​ពេល​ចាប់ផ្ដើម​របាយការណ៍​រហូត​ដល់​ពេល​វា​រួចរាល់​ដើម្បី​ផ្ញើ សូម​អត់ធ្មត់។"</string>
@@ -1330,7 +1332,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"ឧបករណ៍ផ្ទុក USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"ឧបករណ៍​ផ្ទុក​យូអេសប៊ី"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"កែសម្រួល​"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"ការព្រមាន​ប្រើ​ទិន្នន័យ"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"ប៉ះដើម្បីមើលការប្រើប្រាស់ និងការកំណត់"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"បាន​ដល់​ដែន​កំណត់​ទិន្នន័យ 2G-3G"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"បាន​ដល់​ដែន​កំណត់​ទិន្នន័យ 4G"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 095fee6..ab60289 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"ಫೋನ್ ಆಯ್ಕೆಗಳು"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"ಸ್ಕ್ರೀನ್ ಲಾಕ್"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"ಪವರ್ ಆಫ್ ಮಾಡು"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"ದೋಷದ ವರದಿ"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"ದೋಷ ವರದಿ ರಚಿಸಿ"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ನಿಮ್ಮ ಸಾಧನದ ಪ್ರಸ್ತುತ ಸ್ಥಿತಿಯ ಕುರಿತು ಮಾಹಿತಿಯನ್ನು ಸಂಗ್ರಹಿಸಿಕೊಳ್ಳುವುದರ ಜೊತೆ ಇ-ಮೇಲ್ ರೂಪದಲ್ಲಿ ನಿಮಗೆ ರವಾನಿಸುತ್ತದೆ. ಇದು ದೋಷ ವರದಿಯನ್ನು ಪ್ರಾರಂಭಿಸಿದ ಸಮಯದಿಂದ ಅದನ್ನು ಕಳುಹಿಸುವವರೆಗೆ ಸ್ವಲ್ಪ ಸಮಯವನ್ನು ತೆಗೆದುಕೊಳ್ಳುತ್ತದೆ; ದಯವಿಟ್ಟು ತಾಳ್ಮೆಯಿಂದಿರಿ."</string>
@@ -979,8 +981,8 @@
     <string name="whichSendToApplication" msgid="8272422260066642057">"ಇದನ್ನು ಬಳಸಿಕೊಂಡು ಕಳುಹಿಸಿ"</string>
     <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"%1$s ಬಳಸಿಕೊಂಡು ಕಳುಹಿಸಿ"</string>
     <string name="whichSendToApplicationLabel" msgid="8878962419005813500">"ಕಳುಹಿಸು"</string>
-    <string name="whichHomeApplication" msgid="4307587691506919691">"ಹೋಮ್‌ ಅಪ್ಲಿಕೇಶನ್‌  ಆಯ್ಕೆಮಾಡಿ"</string>
-    <string name="whichHomeApplicationNamed" msgid="4493438593214760979">"ಹೋಮ್‌ ಎಂಬಂತೆ %1$s ಅನ್ನು ಬಳಸಿ"</string>
+    <string name="whichHomeApplication" msgid="4307587691506919691">"ಮುಖಪುಟ‌ ಅಪ್ಲಿಕೇಶನ್‌  ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="whichHomeApplicationNamed" msgid="4493438593214760979">"ಮುಖಪುಟ‌ ಎಂಬಂತೆ %1$s ಅನ್ನು ಬಳಸಿ"</string>
     <string name="whichHomeApplicationLabel" msgid="809529747002918649">"ಚಿತ್ರ ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ"</string>
     <string name="whichImageCaptureApplication" msgid="3680261417470652882">"ಇದರ ಜೊತೆಗೆ ಚಿತ್ರ ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ"</string>
     <string name="whichImageCaptureApplicationNamed" msgid="8619384150737825003">"%1$s ಜೊತೆ ಚಿತ್ರ ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ"</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB ಡ್ರೈವ್"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB ಸಂಗ್ರಹಣೆ"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"ಎಡಿಟ್"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"ಡೇಟಾ ಬಳಕೆಯ ಎಚ್ಚರಿಕೆ"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"ಬಳಕೆ ಮತ್ತು ಸೆಟ್ಟಿಂಗ್‍ಗಳನ್ನು ವೀಕ್ಷಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G ಡೇಟಾ ಮೀತಿಯನ್ನು ತಲುಪಿದೆ"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G ಡೇಟಾ ಮೀತಿಯನ್ನು ತಲುಪಿದೆ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index f5f0f99..5d226a6 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"휴대전화 옵션"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"화면 잠금"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"종료"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"버그 신고"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"버그 신고"</string>
     <string name="bugreport_message" msgid="398447048750350456">"현재 기기 상태에 대한 정보를 수집하여 이메일 메시지로 전송합니다. 버그 신고를 시작하여 전송할 준비가 되려면 약간 시간이 걸립니다."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB 드라이브"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB 저장소"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"수정"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"데이터 사용 경고"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"사용량 및 설정을 보려면 탭하세요."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G 데이터 한도에 도달함"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G 데이터 한도에 도달함"</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 9a28b98..99bba3a7 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Телефон мүмкүнчүлүктөрү"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Экран кулпусу"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Кубатын өчүрүү"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Ката тууралуу билдирүү"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Ката тууралуу билдирүү түзүү"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Бул сиздин түзмөгүңүздүн учурдагы абалын эмейл билдирүүсү катары жөнөтүш максатында маалымат чогултат. Ката тууралуу билдирүү түзүлүп башталып, жөнөтүлгөнгө чейин бир аз убакыт керек болот; сураныч, бир аз күтө туруңуз."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB түзмөгү"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB эстутуму"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Өзгөртүү"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Дайындарды колдонуу боюнча эскрт"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Колдонулушун жана жөндөөлөрүн көрүү үчүн таптаңыз."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G дайындар чегине жетти"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G дайындар чегине жетти"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index bb27f43..9762f26 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"ໂຕເລືອກໂທລະສັບ"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"ລັອກໜ້າຈໍ"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"ປິດ"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"ລາຍງານຂໍ້ຜິດພາດ"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"ໃຊ້ລາຍງານຂໍ້ບົກພ່ອງ"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ນີ້ຈະເປັນການເກັບກຳຂໍ້ມູນກ່ຽວກັບ ສະຖານະປັດຈຸບັນຂອງອຸປະກອນທ່ານ ເພື່ອສົ່ງເປັນຂໍ້ຄວາມທາງອີເມວ. ມັນຈະໃຊ້ເວລາໜ້ອຍນຶ່ງ ໃນການເລີ່ມຕົ້ນການລາຍງານຂໍ້ຜິດພາດ ຈົນກວ່າຈະພ້ອມທີ່ຈະສົ່ງໄດ້, ກະລຸນາລໍຖ້າ."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB ດ​ຣ້າຍ"</string>
     <string name="storage_usb" msgid="3017954059538517278">"ບ່ອນຈັດເກັບຂໍ້ມູນ USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"ແກ້ໄຂ"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"ເຕືອນກ່ຽວກັບການນຳໃຊ້ຂໍ້ມູນ"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"ແຕະເພື່ອເບິ່ງການນຳໃຊ້ ແລະ ການຕັ້ງຄ່າ."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"ໃຊ້​ຂໍ້​ມູນ 2G-3G ຮອດ​ຈຳ​ນວນ​ທີ່​ຈຳ​ກັດ​ແລ້ວ"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"ໃຊ້​ຂໍ້​ມູນ 4G ຮອດ​ຈຳ​ນວນ​ທີ່​ຈຳ​ກັດ​ແລ້ວ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 64e0d44..6446066 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -218,6 +218,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefono parinktys"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Ekrano užraktas"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Išjungiamas maitinimas"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Pranešimas apie riktą"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Pranešti apie riktą"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Bus surinkta informacija apie dabartinę įrenginio būseną ir išsiųsta el. pašto pranešimu. Šiek tiek užtruks, kol pranešimas apie riktą bus paruoštas siųsti; būkite kantrūs."</string>
@@ -1380,7 +1382,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"„<xliff:g id="MANUFACTURER">%s</xliff:g>“ atmintukas"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB atmintis"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Redaguoti"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Įspėjimas dėl duomenų naudojimo"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Pal. ir perž. naud. i. bei nust."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Pasiektas 2G–3G duomenų apribojimas"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Pasiektas 4G duomenų apribojimas"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index c3d126c..b0e7af5 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -216,6 +216,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Tālruņa opcijas"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Ekrāna bloķētājs"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Strāvas padeve ir izslēgta."</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Kļūdu ziņojums"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Kļūdu ziņojuma sagatavošana"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Veicot šo darbību, tiks apkopota informācija par jūsu ierīces pašreizējo stāvokli un nosūtīta e-pasta ziņojuma veidā. Kļūdu ziņojuma pabeigšanai un nosūtīšanai var būt nepieciešams laiks. Lūdzu, esiet pacietīgs."</string>
@@ -1354,7 +1356,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB disks"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB atmiņa"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Rediģēt"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Datu izmantošanas brīdinājums"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Piesk., lai sk. lietoj. un iest."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Sasniegts 2G-3G datu ierobež."</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Sasniegts 4G datu ierobežojums"</string>
diff --git a/core/res/res/values-mcc238-mnc06/config.xml b/core/res/res/values-mcc238-mnc06/config.xml
deleted file mode 100644
index afc0cc4..0000000
--- a/core/res/res/values-mcc238-mnc06/config.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, 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">
-    <!-- SIM does not save, but the voice mail number to be changed. -->
-    <bool name="editable_voicemailnumber">true</bool>
-</resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 4a5d24b..a47a483 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Опции на телефон"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Заклучи екран"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Исклучи"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Извештај за грешка"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Земи извештај за грешки"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Ова ќе собира информации за моменталната состојба на вашиот уред, за да ги испрати како порака по е-пошта. Тоа ќе одземе малку време почнувајќи од извештајот за грешки додека не се подготви за праќање; бидете трпеливи."</string>
@@ -1330,7 +1332,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> УСБ-меморија"</string>
     <string name="storage_usb" msgid="3017954059538517278">"УСБ меморија"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Уреди"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Опомена за потрошен интернет"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Допрете за употреба и поставки."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Постигна лимит за 2G-3G податоци"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Постигнат лимит за 4G податоци"</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index e74074c..eaa8deb 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"ഫോൺ ഓപ്‌ഷനുകൾ"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"സ്‌ക്രീൻ ലോക്ക്"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"പവർ ഓഫാക്കുക"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"ബഗ് റിപ്പോർട്ട്"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"ബഗ് റിപ്പോർട്ട് എടുക്കുക"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ഒരു ഇമെയിൽ സന്ദേശമായി അയയ്‌ക്കുന്നതിന്, ഇത് നിങ്ങളുടെ നിലവിലെ ഉപകരണ നിലയെക്കുറിച്ചുള്ള വിവരങ്ങൾ ശേഖരിക്കും. ബഗ് റിപ്പോർട്ട് ആരംഭിക്കുന്നതിൽ നിന്ന് ഇത് അയയ്‌ക്കാനായി തയ്യാറാകുന്നതുവരെ അൽപ്പസമയമെടുക്കും; ക്ഷമയോടെ കാത്തിരിക്കുക."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB ഡ്രൈവ്"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB സ്റ്റോറേജ്"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"എഡിറ്റുചെയ്യുക"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"ഡാറ്റ ഉപയോഗ മുന്നറിയിപ്പ്"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"ഉപയോഗവും ക്രമീകരണവും കാണാൻ ടാപ്പുചെയ്യുക."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G ഡാറ്റ പരിധിയിലെത്തി"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G ഡാറ്റ പരിധിയിലെത്തി"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 96643dc..79dbc68 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Утасны сонголтууд"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Дэлгэцний түгжээ"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Унтраах"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Алдаа мэдээллэх"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Согог репорт авах"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Энэ таны төхөөрөмжийн одоогийн статусын талаарх мэдээллийг цуглуулах ба имэйл мессеж болгон илгээнэ. Алдааны мэдэгдлээс эхэлж илгээхэд бэлэн болоход хэсэг хугацаа зарцуулагдана тэвчээртэй байна уу."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB диск"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB сан"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Засах"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Дата хэрэглээний анхааруулга"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Хэрэглээ, тохиргоог харах бол товш."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G дата хязгаарт хүрсэн"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G дата хязгаарт хүрсэн"</string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index d98bb85..fce64c4 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"फोन पर्याय"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"स्क्रीन लॉक"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"बंद"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"दोष अहवाल"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"दोष अहवाल घ्या"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ई-मेल संदेश म्हणून पाठविण्यासाठी, हे आपल्या वर्तमान डिव्हाइस स्थितीविषयी माहिती संकलित करेल. दोष अहवाल प्रारंभ करण्यापासून तो पाठविण्यापर्यंत थोडा वेळ लागेल; कृपया धीर धरा."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB ड्राइव्‍ह"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB संचयन"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"संपादित करा"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"डेटा वापर चेतावणी"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"वापर आणि सेटिंग्ज पाहण्यासाठी टॅप करा."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G डेटा मर्यादा गाठली"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G डेटा मर्यादा गाठली"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 1596dee..53181ce 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Pilihan telefon"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Kunci skrin"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Matikan kuasa"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Laporan pepijat"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Ambil laporan pepijat"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Ini akan mengumpul maklumat tentang keadaan peranti semasa anda untuk dihantarkan sebagai mesej e-mel. Harap bersabar, mungkin perlu sedikit masa untuk memulakan laporan sehingga siap untuk dihantar."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Pemacu USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Storan USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Edit"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Amaran penggunaan data"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Ketik utk lihat p\'gunaan &amp; ttpn."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Mencapai had data 2G-3G"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Mencapai had data 4G"</string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 73d8561..987d764 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"ဖုန်းဆိုင်ရာရွေးချယ်မှုများ"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"ဖုန်းမျက်နှာပြင်အား သော့ချရန်"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"ပါဝါပိတ်ရန်"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"အမှားရှာဖွေပြင်ဆင်မှုမှတ်တမ်း"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"အမှားရှာဖွေပြင်ဆင်မှုမှတ်တမ်းအား ယူရန်"</string>
     <string name="bugreport_message" msgid="398447048750350456">"သင့်ရဲ့ လက်ရှိ စက်အခြေအနေ အချက်အလက်များကို အီးမေးလ် အနေဖြင့် ပေးပို့ရန် စုဆောင်းပါမည်။ အမှားရှာဖွေပြင်ဆင်မှုမှတ်တမ်းမှ ပေးပို့ရန် အသင့်ဖြစ်သည်အထိ အချိန် အနည်းငယ်ကြာမြင့်မှာ ဖြစ်သဖြင့် သည်းခံပြီး စောင့်ပါရန်"</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB ဒရိုက်ဗ်"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USBဖြင့် သိမ်းဆည်း"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"ပြင်ဆင်ရန်"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"ဒေတာအသုံးပြုမှုသတိပေးချက်"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"အသုံးပြုမှုနှင့် ဆက်တင်များကိုကြည့်ရန် တို့ပါ။"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G ဒေတာ ကန့်သတ်ချက် ပြည့်မီသွားပြီ"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G ဒေတာ ကန့်သတ်ချက် ပြည့်မီသွားပြီ"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index b2045e7..c807c14 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefoninnstillinger"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Lås skjermen"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Slå av"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Feilrapport"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Utfør feilrapport"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Informasjon om tilstanden til enheten din samles inn og sendes som en e-post. Det tar litt tid fra du starter feilrapporten til e-posten er klar, så vær tålmodig."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB-stasjon"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-lagring"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Rediger"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Advarsel for høyt dataforbruk"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Trykk for å se bruken og innstillingene."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Datagrensen for 2G-3G er nådd"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Datagrensen for 4G er nådd"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 97eccb8..65d3b69 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"फोन विकल्पहरू"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"स्क्रिन बन्द"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"बन्द गर्नुहोस्"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"बग रिपोर्ट"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"बग रिपोर्ट लिनुहोस्"</string>
     <string name="bugreport_message" msgid="398447048750350456">"एउटा इमेल सन्देशको रूपमा पठाउनलाई यसले तपाईँको हालैको उपकरणको अवस्थाको बारेमा सूचना जम्मा गर्ने छ। बग रिपोर्ट सुरु गरेदेखि पठाउन तयार नभएसम्म यसले केही समय लिन्छ; कृपया धैर्य गर्नुहोस्।"</string>
@@ -255,7 +257,7 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"माइक्रोफोन"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"अडियो रेकर्ड गर्नुहोस्"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"क्यामेरा"</string>
-    <string name="permgroupdesc_camera" msgid="3250611594678347720">"तस्बिर खिच्नुहोस् तथा भिडियो रेकर्ड गर्नुहोस्"</string>
+    <string name="permgroupdesc_camera" msgid="3250611594678347720">"तस्बिर खिच्नुका साथै भिडियो रेकर्ड गर्नुहोस्"</string>
     <string name="permgrouplab_phone" msgid="5229115638567440675">"फोन"</string>
     <string name="permgroupdesc_phone" msgid="6234224354060641055">"फोन कलहरू गर्नुहोस् र व्यवस्थापन गर्नुहोस्"</string>
     <string name="permgrouplab_sensors" msgid="416037179223226722">"शारीरिक सेन्सर"</string>
@@ -1334,7 +1336,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB ड्राइभ"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB भण्डारण"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"सम्पादन गर्नुहोस्"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"डेटाको प्रयोग चेतावनी"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"प्रयोग र सेटिङहरू हेर्न ट्याप गर्नुहोस्।"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G डेटा सीमा पुग्यो"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G डेटा सीमा पुग्यो"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 30c7f7c..69a4074 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefoonopties"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Schermvergrendeling"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Uitschakelen"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Foutenrapport"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Foutenrapport genereren"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Hiermee worden gegevens over de huidige status van je apparaat verzameld en als e-mail verzonden. Wanneer u een foutenrapport start, duurt het even voordat het kan worden verzonden. Even geduld alstublieft."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB-drive"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-opslag"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Bewerken"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Waarschuwing v. gegevensgebruik"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Tik voor gebruik en instellingen"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Gegevenslimiet van 2G-3G bereikt"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Gegevenslimiet van 4G bereikt"</string>
diff --git a/core/res/res/values-notround-watch/dimens.xml b/core/res/res/values-notround-watch/dimens.xml
index f103aa9..f0204d0 100644
--- a/core/res/res/values-notround-watch/dimens.xml
+++ b/core/res/res/values-notround-watch/dimens.xml
@@ -24,4 +24,5 @@
     <item name="input_extract_action_margin_bottom" type="fraction">0%</item>
     <item name="input_extract_action_button_width" type="dimen">24dp</item>
     <item name="input_extract_action_button_height" type="dimen">24dp</item>
+    <item name="input_extract_action_icon_padding" type="dimen">3dp</item>
 </resources>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index f5210f8..ac80d51 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"ਫੋਨ ਚੋਣਾਂ"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"ਸਕ੍ਰੀਨ ਲੌਕ"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"ਪਾਵਰ ਬੰਦ"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"ਬਗ ਰਿਪੋਰਟ"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"ਬਗ ਰਿਪੋਰਟ ਲਓ"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ਇਹ ਇੱਕ ਈ-ਮੇਲ ਸੁਨੇਹਾ ਭੇਜਣ ਲਈ, ਤੁਹਾਡੀ ਵਰਤਮਾਨ ਡੀਵਾਈਸ ਬਾਰੇ ਜਾਣਕਾਰੀ ਇਕੱਤਰ ਕਰੇਗਾ। ਬਗ ਰਿਪੋਰਟ ਸ਼ੁਰੂ ਕਰਨ ਵਿੱਚ ਥੋੜ੍ਹਾ ਸਮਾਂ ਲੱਗੇਗਾ ਜਦੋਂ ਤੱਕ ਇਹ ਭੇਜੇ ਜਾਣ ਲਈ ਤਿਆਰ ਨਾ ਹੋਵੇ, ਕਿਰਪਾ ਕਰਕੇ ਧੀਰਜ ਰੱਖੋ।"</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB ਡ੍ਰਾਇਵ"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB ਸਟੋਰੇਜ"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"ਸੰਪਾਦਿਤ ਕਰੋ"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"ਡੈਟਾ ਉਪਯੋਗ ਚਿਤਾਵਨੀ"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"ਵਰਤੋਂ ਅਤੇ ਸੈਟਿੰਗਾਂ ਨੂੰ ਵੇਖਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G ਡੈਟਾ ਸੀਮਾ ਪੂਰੀ ਹੋ ਗਈ"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G ਡੈਟਾ ਸੀਮਾ ਪੂਰੀ ਹੋਈ"</string>
@@ -1638,7 +1641,7 @@
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ਚੁਣਿਆ ਗਿਆ</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ਚੁਣਿਆ ਗਿਆ</item>
     </plurals>
-    <string name="default_notification_channel_label" msgid="6950908610709016902">"ਵਿਵਿਧ"</string>
+    <string name="default_notification_channel_label" msgid="6950908610709016902">"ਫੁਟਕਲ"</string>
     <string name="importance_from_user" msgid="7318955817386549931">"ਤੁਸੀਂ ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਦੀ ਮਹੱਤਤਾ ਸੈੱਟ ਕੀਤੀ।"</string>
     <string name="importance_from_person" msgid="9160133597262938296">"ਇਹ ਸ਼ਾਮਲ ਲੋਕਾਂ ਦੇ ਕਾਰਨ ਮਹੱਤਵਪੂਰਨ ਹੈ।"</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"ਕੀ <xliff:g id="APP">%1$s</xliff:g> ਨੂੰ <xliff:g id="ACCOUNT">%2$s</xliff:g> ਨਾਲ ਇੱਕ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਬਣਾਉਣ ਦੀ ਮਨਜ਼ੂਰੀ ਦੇਣੀ ਹੈ?"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 91931b1..8698846 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -218,6 +218,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opcje telefonu"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Blokada ekranu"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Wyłącz"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Zgłoszenie błędu"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Zgłoś błąd"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Informacje o bieżącym stanie urządzenia zostaną zebrane i wysłane e-mailem. Przygotowanie zgłoszenia błędu do wysłania chwilę potrwa, więc zachowaj cierpliwość."</string>
@@ -1380,7 +1382,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Dysk USB (<xliff:g id="MANUFACTURER">%s</xliff:g>)"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Nośnik USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Edytuj"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Ostrzeżenie o transmisji danych"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Kliknij, by wyświetlić użycie i ustawienia."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Osiągnięto limit danych 2G/3G"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Osiągnięto limit danych 4G"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index c5ce01f..74b7519 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opções do telefone"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Bloquear tela"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Desligar"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Relatório de bugs"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Obter relatório de bugs"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Isto coletará informações sobre o estado atual do dispositivo para enviá-las em uma mensagem de e-mail. Após iniciar o relatório de bugs, será necessário aguardar algum tempo até que esteja pronto para ser enviado."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Drive USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Armazenamento USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Editar"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Aviso sobre uso de dados"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Toque para ver uso e config."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Limite de dados 2G-3G atingido"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Limite de dados 4G atingido"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index b25f8ff..58e4097 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opções do telefone"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Bloqueio de ecrã"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Desligar"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Relatório de erros"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Criar relatório de erros"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Será recolhida informação sobre o estado atual do seu dispositivo a enviar através de uma mensagem de email. Demorará algum tempo até que o relatório de erro esteja pronto para ser enviado. Aguarde um pouco."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Unidade USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Armazenamento USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Editar"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Aviso de utilização de dados"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Toque para ver a utilização e definições"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Limite de dados 2G/3G atingido"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Limite de dados 4G atingido"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index c5ce01f..74b7519 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opções do telefone"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Bloquear tela"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Desligar"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Relatório de bugs"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Obter relatório de bugs"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Isto coletará informações sobre o estado atual do dispositivo para enviá-las em uma mensagem de e-mail. Após iniciar o relatório de bugs, será necessário aguardar algum tempo até que esteja pronto para ser enviado."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Drive USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Armazenamento USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Editar"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Aviso sobre uso de dados"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Toque para ver uso e config."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Limite de dados 2G-3G atingido"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Limite de dados 4G atingido"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 867ccc8..5011363 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -216,6 +216,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opțiuni telefon"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Blocați ecranul"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Opriți alimentarea"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Raport despre erori"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Executați un raport despre erori"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Acest raport va colecta informații despre starea actuală a dispozitivului, pentru a le trimite într-un e-mail. Aveți răbdare după pornirea raportului despre erori până când va fi gata de trimis."</string>
@@ -1354,7 +1356,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Unitate USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Dsipozitiv de stocare USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Editați"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Avertisment de utiliz. a datelor"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Atingeți ca să vedeți utilizarea/setările."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Ați atins limita de date 2G-3G"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Ați atins limita de date 4G"</string>
diff --git a/core/res/res/values-round-watch/dimens.xml b/core/res/res/values-round-watch/dimens.xml
index a12f499..1d8c669 100644
--- a/core/res/res/values-round-watch/dimens.xml
+++ b/core/res/res/values-round-watch/dimens.xml
@@ -24,4 +24,5 @@
     <item name="input_extract_action_margin_bottom" type="fraction">2.1%</item>
     <item name="input_extract_action_button_width" type="dimen">32dp</item>
     <item name="input_extract_action_button_height" type="dimen">32dp</item>
+    <item name="input_extract_action_icon_padding" type="dimen">5dp</item>
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 4e7624e..7850cd8 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -218,6 +218,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Параметры телефона"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Блокировка экрана"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Отключить питание"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Отчет об ошибке"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Отчет об ошибке"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Информация о текущем состоянии вашего устройства будет собрана и отправлена по электронной почте. Подготовка отчета займет некоторое время."</string>
@@ -1380,7 +1382,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"USB-накопитель <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-накопитель"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Изменить"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Осталось мало трафика"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Нажмите, чтобы проверить трафик и настройки."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Достигнут лимит трафика 2G/3G"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Достигнут лимит трафика 4G"</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index a1fd8c6..7cab897 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"දුරකථන විකල්ප"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"තිර අගුල"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"බලය අක්‍රිය කරන්න"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"දෝෂ වර්තාව"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"දෝෂ වාර්තාවක් ගන්න"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ඊ-තැපැල් පණිවිඩයක් ලෙස යැවීමට මෙය ඔබගේ වත්මන් උපාංග තත්වය ගැන තොරතුරු එකතු කරනු ඇත. දෝෂ වාර්තාව ආරම්භ කර එය යැවීමට සූදානම් කරන තෙක් එයට කිසියම් කාලයක් ගතවනු ඇත; කරුණාකර ඉවසන්න."</string>
@@ -1330,7 +1332,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB ධාවකය"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB ආචයනය"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"සංස්කරණය කරන්න"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"දත්ත භාවිතා අවවාදය"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"භාවිතය සහ සැකසීම් බැලීමට තට්ටු කරන්න."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G දත්ත සීමාවට ළඟාවී ඇත"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G දත්ත සීමාවට ළඟාවී ඇත"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index e4a1c9d..26e275f 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -218,6 +218,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Možnosti telefónu"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Zámka obrazovky"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Vypnúť"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Hlásenie o chybách"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Vytvoriť hlásenie chyby"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Týmto zhromaždíte informácie o aktuálnom stave zariadenia. Informácie je potom možné odoslať e-mailom, chvíľu však potrvá, kým bude hlásenie chyby pripravené na odoslanie. Prosíme vás preto o trpezlivosť."</string>
@@ -1380,7 +1382,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Disk USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Ukladací priestor USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Upraviť"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Upozornenie o využití dát"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Klepnutím zobrazíte využitie a nastavenia."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Bol dosiahnutý limit 2G–3G"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Bol dosiahnutý limit 4G"</string>
@@ -1675,7 +1678,7 @@
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (ďalší budík)"</string>
-    <string name="zen_mode_forever" msgid="7420011936770086993">"Dokým túto funkciu nevypnete"</string>
+    <string name="zen_mode_forever" msgid="7420011936770086993">"Kým túto funkciu nevypnete"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dokým nevypnete stav Nerušiť"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
     <string name="toolbar_collapse_description" msgid="2821479483960330739">"Zbaliť"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 5feeb07..7f49968 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -218,6 +218,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Možnosti telefona"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Zaklep zaslona"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Izklopi"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Poročilo o napakah"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Ustvari poročilo o napakah"</string>
     <string name="bugreport_message" msgid="398447048750350456">"S tem bodo zbrani podatki o trenutnem stanju naprave, ki bodo poslani v e-poštnem sporočilu. Izvedba poročila o napakah in priprava trajata nekaj časa, zato bodite potrpežljivi."</string>
@@ -1380,7 +1382,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Pogon USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Pomnilnik USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Uredi"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Opozorilo o uporabi podatkov"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Dot. se za ogled upor. in nast."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Dosežena pod. omejitev za 2G/3G"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Dosežena pod. omejitev za 4G"</string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index 75e134c..c906f74 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opsionet e telefonit"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Kyçja e ekranit"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Fik"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Raporti i defekteve në kod"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Merr raportin e defekteve në kod"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Ky funksion mundëson mbledhjen e informacioneve mbi gjendjen aktuale të pajisjes për ta dërguar si mesazh mail-i. Do të duhet pak kohë nga nisja e raportit të defekteve në kod. Faleminderit për durimin."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"USB-ja nga <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Hapësira ruajtëse e USB-së"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Redakto"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Paralajmërim për përdorimin e të dhënave"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Trokit për të parë përdorimin dhe cilësimet."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Kufiri i të dhënave 2G-3G u arrit"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Kufiri i të dhënave 4G u arrit"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 4349221..f029dbb 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -216,6 +216,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Опције телефона"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Закључај екран"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Искључи"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Извештај о грешци"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Направи извештај о грешци"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Овим ће се прикупити информације о тренутном стању уређаја како би биле послате у поруци е-поште. Од започињања извештаја о грешци до тренутка за његово слање проћи ће неко време; будите стрпљиви."</string>
@@ -256,9 +258,9 @@
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Складиште"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"приступа сликама, медијима и датотекама на уређају"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Микрофон"</string>
-    <string name="permgroupdesc_microphone" msgid="4988812113943554584">"снима аудио снимке"</string>
+    <string name="permgroupdesc_microphone" msgid="4988812113943554584">"снима аудио"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Камера"</string>
-    <string name="permgroupdesc_camera" msgid="3250611594678347720">"снима слике и видео снимке"</string>
+    <string name="permgroupdesc_camera" msgid="3250611594678347720">"снима слике и видео"</string>
     <string name="permgrouplab_phone" msgid="5229115638567440675">"Телефон"</string>
     <string name="permgroupdesc_phone" msgid="6234224354060641055">"упућује телефонске позиве и управља њима"</string>
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Сензори за тело"</string>
@@ -1354,7 +1356,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB диск"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB меморија"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Измени"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Упозорење о потрошњи података"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Додирните за потрошњу и подешавања."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Нема више 2G-3G података"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Нема више 4G података"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 2085ca7..3f4f836 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefonalternativ"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Skärmlås"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Stäng av"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Felrapport"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Skapa felrapport"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Nu hämtas information om aktuell status för enheten, som sedan skickas i ett e-postmeddelade. Det tar en liten stund innan felrapporten är färdig och kan skickas, så vi ber dig ha tålamod."</string>
@@ -671,7 +673,7 @@
     <string name="lockscreen_carrier_default" msgid="6169005837238288522">"Ingen tjänst"</string>
     <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Skärmen har låsts."</string>
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Tryck på Menu om du vill låsa upp eller ringa nödsamtal."</string>
-    <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Tryck på Menu om du vill låsa upp."</string>
+    <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Tryck på Menu för att låsa upp."</string>
     <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Rita grafiskt lösenord för att låsa upp"</string>
     <string name="lockscreen_emergency_call" msgid="5298642613417801888">"Nödsamtal"</string>
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Tillbaka till samtal"</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"USB-enhet (<xliff:g id="MANUFACTURER">%s</xliff:g>)"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-lagring"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Redigera"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Varning angående dataanvändning"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Visa användning och inställning."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Datagränsen för 2G-3G har uppnåtts"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Datagränsen för 4G har uppnåtts"</string>
@@ -1656,7 +1659,7 @@
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Du har nya meddelanden"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Öppna sms-appen och visa meddelandet"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Vissa funktioner är begränsade"</string>
-    <string name="user_encrypted_message" msgid="4923292604515744267">"Tryck om du vill låsa upp"</string>
+    <string name="user_encrypted_message" msgid="4923292604515744267">"Tryck för att låsa upp"</string>
     <string name="user_encrypted_detail" msgid="5708447464349420392">"Användaruppgifterna är låsta"</string>
     <string name="profile_encrypted_detail" msgid="3700965619978314974">"Jobbprofilen är låst"</string>
     <string name="profile_encrypted_message" msgid="6964994232310195874">"Tryck och lås upp jobbprofilen"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 5256d72..9cba390 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -212,6 +212,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Chaguo za simu"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Funga skrini"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Zima"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Ripoti ya hitilafu"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Chukua ripoti ya hitilafu"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Hii itakusanya maelezo kuhusu hali ya kifaa chako kwa sasa, na itume kama barua pepe. Itachukua muda mfupi tangu ripoti ya hitilafu ianze kuzalishwa hadi iwe tayari kutumwa; vumilia."</string>
@@ -1326,7 +1328,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Hifadhi ya USB iliyotengenezwa na <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Hifadhi ya USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Badilisha"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Onyo la matumizi ya data"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Gonga ili uangalie matumizi na mipangilio."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Kikomo data ya 2G-3G kimefikiwa"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Kikomo cha data ya 4G kimefikiwa"</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 0e1afe9..e784a76 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"தொலைபேசி விருப்பங்கள்"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"திரைப் பூட்டு"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"முடக்கு"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"பிழை அறிக்கை"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"பிழை அறிக்கையை எடு"</string>
     <string name="bugreport_message" msgid="398447048750350456">"உங்கள் நடப்புச் சாதன நிலையை மின்னஞ்சல் செய்தியாக அனுப்ப, அது குறித்த தகவலை இது சேகரிக்கும். பிழை அறிக்கையைத் தொடங்குவதில் இருந்து, அது அனுப்புவதற்குத் தயாராகும் வரை, இதற்குச் சிறிது நேரம் ஆகும்; பொறுமையாகக் காத்திருக்கவும்."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB டிரைவ்"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB சேமிப்பிடம்"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"திருத்து"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"தரவு பயன்பாட்டு எச்சரிக்கை"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"தரவு உபயோகம், அமைப்புகளைப் பார்க்க, தட்டவும்."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G தரவு வரம்பைக் கடந்தது"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G தரவு வரம்பைக் கடந்தது"</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index cc47e81..21ed7c6 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"ఫోన్ ఎంపికలు"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"స్క్రీన్ లాక్"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"పవర్ ఆఫ్ చేయి"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"బగ్ నివేదిక"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"బగ్ నివేదికను సిద్ధం చేయి"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ఇది ఇ-మెయిల్ సందేశం రూపంలో పంపడానికి మీ ప్రస్తుత పరికర స్థితి గురించి సమాచారాన్ని సేకరిస్తుంది. బగ్ నివేదికను ప్రారంభించడం మొదలుకొని పంపడానికి సిద్ధం చేసే వరకు ఇందుకు కొంత సమయం పడుతుంది; దయచేసి ఓపిక పట్టండి."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB డ్రైవ్"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB నిల్వ"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"సవరించు"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"డేటా వినియోగం హెచ్చరిక"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"వినియోగం,సెట్టింగ్‌ల కోసం నొక్కండి"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G డేటా పరిమితిని చేరుకుంది"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G డేటా పరిమితిని చేరుకుంది"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index d3781d5..df9b182 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"ตัวเลือกโทรศัพท์"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"ล็อกหน้าจอ"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"ปิดเครื่อง"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"รายงานข้อบกพร่อง"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"ใช้รายงานข้อบกพร่อง"</string>
     <string name="bugreport_message" msgid="398447048750350456">"การดำเนินการนี้จะรวบรวมข้อมูลเกี่ยวกับสถานะปัจจุบันของอุปกรณ์ของคุณ โดยจะส่งไปในรูปแบบข้อความอีเมล อาจใช้เวลาสักครู่ตั้งแต่เริ่มการสร้างรายงานข้อบกพร่องจนกระทั่งเสร็จสมบูรณ์ โปรดอดทนรอ"</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"ไดรฟ์ USB ของ <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"ที่เก็บข้อมูล USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"แก้ไข"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"คำเตือนการใช้ข้อมูล"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"แตะเพื่อดูการใช้งานและการตั้งค่า"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"ถึงขีดจำกัดข้อมูล 2G-3G แล้ว"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"ถึงขีดจำกัดข้อมูล 4G แล้ว"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index b9c7657..fac6eeb 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Pagpipilian sa telepono"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Pag-lock sa screen"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"I-off"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Ulat sa bug"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Kunin ang ulat sa bug"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Mangongolekta ito ng impormasyon tungkol sa kasalukuyang katayuan ng iyong device, na ipapadala bilang mensaheng e-mail. Gugugol ito ng kaunting oras mula sa pagsisimula ng ulat sa bug hanggang sa handa na itong maipadala; mangyaring magpasensya."</string>
@@ -1150,7 +1152,7 @@
     <string name="usb_accessory_notification_title" msgid="7848236974087653666">"Nakakonekta sa isang accessory ng USB"</string>
     <string name="usb_notification_message" msgid="3370903770828407960">"I-tap para sa higit pang mga opsyon."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Konektado ang debugging ng USB"</string>
-    <string name="adb_active_notification_message" msgid="4948470599328424059">"I-tap upang i-disable ang pagde-debug ng USB."</string>
+    <string name="adb_active_notification_message" msgid="4948470599328424059">"I-tap upang i-disable ang pag-debug ng USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Kinukuha ang ulat ng bug…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Gusto mo bang ibahagi ang ulat ng bug?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Ibinabahagi ang ulat ng bug…"</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB drive"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB storage"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"I-edit"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Babala sa paggamit ng data"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"I-tap tingnan paggamit/setting."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Naabot na ang limitasyon sa 2G-3G data"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Naabot na ang limitasyon sa 4G data"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 4f4789b..afd9e68 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefon seçenekleri"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Ekran kilidi"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Kapat"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Hata raporu"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Hata raporu al"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Bu rapor, e-posta iletisi olarak göndermek üzere cihazınızın şu anki durumuyla ilgili bilgi toplar. Hata raporu başlatıldıktan sonra hazır olması biraz zaman alabilir, lütfen sabırlı olun."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB sürücüsü"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB bellek"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Düzenle"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Veri kullanım uyarısı"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Kul. ve ayar. gör. için dokunun."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G veri sınırına ulaşıldı"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G veri sınırına ulaşıldı"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 3c693d8..0ce3396 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -218,6 +218,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Параметри телеф."</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Заблок. екран"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Вимкнути"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Звіт про помилки"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Звіт про помилку"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Інформація про поточний стан вашого пристрою буде зібрана й надіслана електронною поштою. Підготовка звіту триватиме певний час."</string>
@@ -1380,7 +1382,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Носій USB (<xliff:g id="MANUFACTURER">%s</xliff:g>)"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Носій USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Редагувати"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Застереження про використ. даних"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Переглянути дані та параметри."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Досягнуто ліміту даних 2G–3G"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Досягнуто ліміту даних 4G"</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 5c3ecfc..ebab740 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"فون کے اختیارات"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"اسکرین لاک"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"پاور آف"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"بگ کی اطلاع"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"بگ کی اطلاع لیں"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ایک ای میل پیغام کے بطور بھیجنے کیلئے، یہ آپ کے موجودہ آلہ کی حالت کے بارے میں معلومات جمع کرے گا۔ بگ کی اطلاع شروع کرنے سے لے کر بھیجنے کیلئے تیار ہونے تک اس میں تھوڑا وقت لگے گا؛ براہ کرم تحمل سے کام لیں۔"</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"‏<xliff:g id="MANUFACTURER">%s</xliff:g> USB ڈرائیو"</string>
     <string name="storage_usb" msgid="3017954059538517278">"‏USB اسٹوریج"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"ترمیم کریں"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"ڈیٹا کے استعمال کی وارننگ"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"استعمال اور ترتیبات دیکھنے کیلئے تھپتھپائیں۔"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"‏2G-3G ڈیٹا کی حد کو پہنچ گیا"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"‏4G ڈیٹا کی حد کو پہنچ گیا"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 8fdb309..f97a7b8 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefon sozlamalari"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Ekran qulfi"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"O‘chirish"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Nosozlik haqida ma’lumot berish"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Xatoliklar hisoboti"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Qurilmangiz holati haqidagi ma’lumotlar to‘planib, e-pochta orqali yuboriladi. Hisobotni tayyorlash biroz vaqt olishi mumkin."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB xotira qurilmasi"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB xotira"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Tahrirlash"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Trafik kam qoldi"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Trafik sarfi va sozlamalarni ko‘rish uchun bosing."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G trafik chekloviga yetdi"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G trafik chekloviga yetdi"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index f802d55..66b87e7 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Tùy chọn điện thoại"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Khoá màn hình"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Tắt nguồn"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Báo cáo lỗi"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Nhận báo cáo lỗi"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Báo cáo này sẽ thu thập thông tin về tình trạng thiết bị hiện tại của bạn, để gửi dưới dạng thông báo qua email. Sẽ mất một chút thời gian kể từ khi bắt đầu báo cáo lỗi cho tới khi báo cáo sẵn sàng để gửi; xin vui lòng kiên nhẫn."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Ổ USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Bộ lưu trữ USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Chỉnh sửa"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Cảnh báo sử dụng dữ liệu"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Nhấn để xem sử dụng và cài đặt."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Đã đạt tới giới hạn dữ liệu 2G-3G"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Đã đạt tới giới hạn dữ liệu 4G"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 403021d6..1bd1023 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"手机选项"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"屏幕锁定"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"关机"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"错误报告"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"提交错误报告"</string>
     <string name="bugreport_message" msgid="398447048750350456">"这会收集有关当前设备状态的信息,并以电子邮件的形式进行发送。从开始生成错误报告到准备好发送需要一点时间,请耐心等待。"</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> U 盘"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB存储器"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"修改"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"流量警告"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"点按即可查看使用情况和设置。"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"已达到2G-3G流量上限"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"已达到4G流量上限"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 3f40c75..4329c8f 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"手機選項"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"螢幕鎖定"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"關閉"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"錯誤報告"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"取得錯誤報告"</string>
     <string name="bugreport_message" msgid="398447048750350456">"這會收集您目前裝置狀態的相關資訊,並以電郵傳送給您。從開始建立錯誤報告到準備傳送需要一段時間,請耐心等候。"</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB 驅動器"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB 儲存裝置"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"編輯"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"資料用量警告"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"輕按即可查看用量和設定。"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"已達到 2G-3G 數據流量上限"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"已達到 4G 數據流量上限"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 4e18d69..ec7a9a0 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"電話選項"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"螢幕鎖定"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"關機"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"錯誤報告"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"取得錯誤報告"</string>
     <string name="bugreport_message" msgid="398447048750350456">"這會收集您目前裝置狀態的相關資訊,以便透過電子郵件傳送。從錯誤報告開始建立到準備傳送的這段過程可能需要一點時間,敬請耐心等候。"</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB 隨身碟"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB 儲存裝置"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"編輯"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"數據用量警告"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"輕觸即可查看用量和設定。"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"已達到 2G-3G 數據流量上限"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"已達到 4G 數據流量上限"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 733e676..3a19648 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -214,6 +214,8 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Okukhethwa kukho kwefoni"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Ukuvala isikrini"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Vala amandla"</string>
+    <!-- no translation found for global_action_emergency (7112311161137421166) -->
+    <skip />
     <string name="global_action_bug_report" msgid="7934010578922304799">"Umbiko wephutha"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Thatha umbiko wesiphazamiso"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Lokhu kuzoqoqa ulwazi mayelana nesimo samanje sedivayisi yakho, ukuthumela imilayezo ye-imeyili. Kuzothatha isikhathi esincane kusuka ekuqaleni umbiko wesiphazamiso uze ulungele ukuthunyelwa; sicela ubekezele."</string>
@@ -1328,7 +1330,8 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> idrayivu ye-USB"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Isitoreji se-USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Hlela"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"Isexwayiso sokusetshenziswa kwedatha"</string>
+    <!-- no translation found for data_usage_warning_title (3620440638180218181) -->
+    <skip />
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Thepha ukuze ubuke ukusetshenziswa nezilungiselelo."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G umkhawulo wedatha ufinyelelwe"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G umkhawulo wedatha ufinyelelwe"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index aca2bcc..f0a25aa 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4841,6 +4841,11 @@
         <!-- The list year's selected circle color in the list.
              {@deprecated No longer displayed.} -->
         <attr name="yearListSelectorColor" format="color" />
+
+        <!-- @hide Whether this time picker is being displayed within a dialog,
+             in which case it may ignore the requested time picker mode due to
+             space considerations. -->
+        <attr name="dialogMode" format="boolean" />
     </declare-styleable>
 
     <declare-styleable name="TwoLineListItem">
@@ -5176,6 +5181,11 @@
         <!-- The background color state list for the AM/PM selectors.
              {@deprecated Use headerBackground instead.}-->
         <attr name="amPmBackgroundColor" format="color" />
+
+        <!-- @hide Whether this time picker is being displayed within a dialog,
+             in which case it may ignore the requested time picker mode due to
+             space considerations. -->
+        <attr name="dialogMode" />
     </declare-styleable>
 
     <!-- ========================= -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index e9e7d53..3ae6186 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2584,6 +2584,16 @@
     <!-- True if the device supports system navigation keys. -->
     <bool name="config_supportSystemNavigationKeys">false</bool>
 
+    <!-- emergency call number for the emergency affordance -->
+    <string name="config_emergency_call_number" translatable="false">112</string>
+
+    <!-- Do not translate. Mcc codes whose existence trigger the presence of emergency
+         affordances-->
+    <integer-array name="config_emergency_mcc_codes" translatable="false">
+        <item>404</item>
+        <item>405</item>
+    </integer-array>
+
     <!-- Package name for the device provisioning package. -->
     <string name="config_deviceProvisioningPackage"></string>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f1118d7..bf7317c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -488,6 +488,9 @@
     <!-- TODO: promote to separate string-->
     <string name="global_action_restart" translatable="false">@string/sim_restart_button</string>
 
+    <!-- label for item that starts emergency call -->
+    <string name="global_action_emergency">Emergency</string>
+
     <!-- label for item that generates a bug report in the phone options dialog -->
     <string name="global_action_bug_report">Bug report</string>
 
@@ -3559,8 +3562,8 @@
     <string name="extract_edit_menu_button">Edit</string>
 
     <!-- Notification title when data usage has exceeded warning threshold. [CHAR LIMIT=32] -->
-    <string name="data_usage_warning_title">Data usage warning</string>
-    <!-- Notification body when data usage has exceeded warning threshold. -->
+    <string name="data_usage_warning_title">Data usage alert</string>
+    <!-- Notification body when data usage has exceeded warning threshold. [CHAR LIMIT=32] -->
     <string name="data_usage_warning_body">Tap to view usage and settings.</string>
 
     <!-- Notification title when 2G-3G data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index cf6fdc8..30dd760 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -347,8 +347,6 @@
   <java-symbol type="integer"  name="config_wifi_operating_voltage_mv" />
   <java-symbol type="string"  name="config_wifi_framework_sap_2G_channel_list" />
 
-  <java-symbol type="bool" name="editable_voicemailnumber" />
-
   <java-symbol type="bool" name="config_wifi_framework_cellular_handover_enable_user_triggered_adjustment" />
   <java-symbol type="integer" name="config_wifi_framework_associated_full_scan_tx_packet_threshold" />
   <java-symbol type="integer" name="config_wifi_framework_associated_full_scan_rx_packet_threshold" />
@@ -2677,6 +2675,10 @@
 
   <java-symbol type="string" name="lockscreen_storage_locked" />
 
+  <java-symbol type="string" name="global_action_emergency" />
+  <java-symbol type="string" name="config_emergency_call_number" />
+  <java-symbol type="array" name="config_emergency_mcc_codes" />
+
   <!-- Used for MimeIconUtils. -->
   <java-symbol type="drawable" name="ic_doc_apk" />
   <java-symbol type="drawable" name="ic_doc_audio" />
@@ -2716,7 +2718,13 @@
 
   <java-symbol type="drawable" name="ic_restart" />
 
+  <java-symbol type="drawable" name="emergency_icon" />
+
   <java-symbol type="array" name="config_convert_to_emergency_number_map" />
 
   <java-symbol type="array" name="config_nonBlockableNotificationPackages" />
+
+  <!-- Screen-size-dependent modes for picker dialogs. -->
+  <java-symbol type="integer" name="time_picker_mode" />
+  <java-symbol type="integer" name="date_picker_mode" />
 </resources>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
index 68f3179..23135dd 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
@@ -63,11 +63,6 @@
 
         String password = arguments.getString("password");
 
-        String freqStr = arguments.getString("frequency-band");
-        if (freqStr != null) {
-            setFrequencyBand(freqStr);
-        }
-
         assertTrue("enable Wifi failed", enableWifi());
         WifiInfo wi = mWifiManager.getConnectionInfo();
         logv("%s", wi);
@@ -80,28 +75,6 @@
     }
 
     /**
-     * Set the frequency band and verify that it has been set.
-     */
-    private void setFrequencyBand(String frequencyBandStr) {
-        int frequencyBand = -1;
-        if ("2.4".equals(frequencyBandStr)) {
-            frequencyBand = WifiManager.WIFI_FREQUENCY_BAND_2GHZ;
-        } else if ("5.0".equals(frequencyBandStr)) {
-            frequencyBand = WifiManager.WIFI_FREQUENCY_BAND_5GHZ;
-        } else if ("auto".equals(frequencyBandStr)) {
-            frequencyBand = WifiManager.WIFI_FREQUENCY_BAND_AUTO;
-        } else {
-            fail("Invalid frequency-band");
-        }
-        if (mWifiManager.getFrequencyBand() != frequencyBand) {
-            logv("Set frequency band to %s", frequencyBandStr);
-            mWifiManager.setFrequencyBand(frequencyBand, true);
-        }
-        assertEquals("Specified frequency band does not match operational band",
-                frequencyBand, mWifiManager.getFrequencyBand());
-    }
-
-    /**
      * Get the {@link WifiConfiguration} based on ssid, security, and password.
      */
     private WifiConfiguration getConfig(String ssid, SecurityType securityType, String password) {
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index c234b6a..ee78613 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1329,6 +1329,11 @@
             android:exported="true">
         </activity>
 
+        <activity
+                android:name="android.print.mockservice.AddPrintersActivity"
+                android:exported="true">
+        </activity>
+
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/core/tests/coretests/res/xml/printservice.xml b/core/tests/coretests/res/xml/printservice.xml
index abbebda..b105a0f 100644
--- a/core/tests/coretests/res/xml/printservice.xml
+++ b/core/tests/coretests/res/xml/printservice.xml
@@ -17,4 +17,5 @@
 -->
 
 <print-service  xmlns:android="http://schemas.android.com/apk/res/android"
-     android:settingsActivity="android.print.mockservice.SettingsActivity"/>
+     android:settingsActivity="android.print.mockservice.SettingsActivity"
+     android:addPrintersActivity="android.print.mockservice.AddPrintersActivity" />
diff --git a/core/tests/coretests/src/android/app/LoaderLifecycleTest.java b/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
index a3d51a0..1850d57 100644
--- a/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
+++ b/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
@@ -99,6 +99,9 @@
             final FragmentManager fm2 = fc2.getFragmentManager();
 
             fc2.attachHost(null);
+            // Make sure nothing blows up on a null here
+            fc2.restoreLoaderNonConfig(null);
+            // for real this time
             fc2.restoreLoaderNonConfig(loaderNonConfig);
             fc2.restoreAllState(savedState, nonconf);
             fc2.dispatchCreate();
diff --git a/core/tests/coretests/src/android/print/BasePrintTest.java b/core/tests/coretests/src/android/print/BasePrintTest.java
index 2c2ee8c..8ef8062 100644
--- a/core/tests/coretests/src/android/print/BasePrintTest.java
+++ b/core/tests/coretests/src/android/print/BasePrintTest.java
@@ -16,6 +16,9 @@
 
 package android.print;
 
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doCallRealMethod;
@@ -26,173 +29,134 @@
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.pm.PackageManager;
-import android.content.res.Configuration;
-import android.content.res.Resources;
 import android.os.CancellationSignal;
-import android.os.LocaleList;
 import android.os.ParcelFileDescriptor;
 import android.os.SystemClock;
-import android.print.PrintAttributes;
-import android.print.PrintDocumentAdapter;
-import android.print.PrintManager;
-import android.print.PrinterId;
 import android.print.mockservice.PrintServiceCallbacks;
 import android.print.mockservice.PrinterDiscoverySessionCallbacks;
 import android.print.mockservice.StubbablePrinterDiscoverySession;
 import android.printservice.CustomPrinterIconCallback;
 import android.printservice.PrintJob;
 import android.printservice.PrintService;
-import android.test.InstrumentationTestCase;
-import android.util.DisplayMetrics;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.rule.ActivityTestRule;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
 import org.mockito.stubbing.Answer;
 
-import java.io.BufferedReader;
 import java.io.FileInputStream;
 import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
 import java.util.List;
-import java.util.Locale;
 import java.util.concurrent.TimeoutException;
 
 /**
  * This is the base class for print tests.
  */
-public abstract class BasePrintTest extends InstrumentationTestCase {
-
-    private static final long OPERATION_TIMEOUT = 30000;
+abstract class BasePrintTest {
+    protected static final long OPERATION_TIMEOUT = 30000;
     private static final String PM_CLEAR_SUCCESS_OUTPUT = "Success";
-    private static final String COMMAND_LIST_ENABLED_IME_COMPONENTS = "ime list -s";
-    private static final String COMMAND_PREFIX_ENABLE_IME = "ime enable ";
-    private static final String COMMAND_PREFIX_DISABLE_IME = "ime disable ";
     private static final int CURRENT_USER_ID = -2; // Mirrors UserHandle.USER_CURRENT
 
-    private PrintTestActivity mActivity;
     private android.print.PrintJob mPrintJob;
 
-    private LocaleList mOldLocale;
-
     private CallCounter mStartCallCounter;
     private CallCounter mStartSessionCallCounter;
 
-    private String[] mEnabledImes;
+    private static Instrumentation sInstrumentation;
+    private static UiDevice sUiDevice;
 
-    private String[] getEnabledImes() throws IOException {
-        List<String> imeList = new ArrayList<>();
+    @Rule
+    public ActivityTestRule<PrintTestActivity> mActivityRule =
+            new ActivityTestRule<>(PrintTestActivity.class, false, true);
 
-        ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
-                .executeShellCommand(COMMAND_LIST_ENABLED_IME_COMPONENTS);
-        try (BufferedReader reader = new BufferedReader(
-                new InputStreamReader(new FileInputStream(pfd.getFileDescriptor())))) {
+    /**
+     * {@link Runnable} that can throw and {@link Exception}
+     */
+    interface Invokable {
+        /**
+         * Execute the invokable
+         *
+         * @throws Exception
+         */
+        void run() throws Exception;
+    }
 
-            String line;
-            while ((line = reader.readLine()) != null) {
-                imeList.add(line);
+    /**
+     * Assert that the invokable throws an expectedException
+     *
+     * @param invokable The {@link Invokable} to run
+     * @param expectedClass The {@link Exception} that is supposed to be thrown
+     */
+    void assertException(Invokable invokable, Class<? extends Exception> expectedClass)
+            throws Exception {
+        try {
+            invokable.run();
+        } catch (Exception e) {
+            if (e.getClass().isAssignableFrom(expectedClass)) {
+                return;
+            } else {
+                throw e;
             }
         }
 
-        String[] imeArray = new String[imeList.size()];
-        imeList.toArray(imeArray);
-
-        return imeArray;
+        throw new AssertionError("No exception thrown");
     }
 
-    private void disableImes() throws Exception {
-        mEnabledImes = getEnabledImes();
-        for (String ime : mEnabledImes) {
-            String disableImeCommand = COMMAND_PREFIX_DISABLE_IME + ime;
-            runShellCommand(getInstrumentation(), disableImeCommand);
-        }
+    /**
+     * Return the UI device
+     *
+     * @return the UI device
+     */
+    public UiDevice getUiDevice() {
+        return sUiDevice;
     }
 
-    private void enableImes() throws Exception {
-        for (String ime : mEnabledImes) {
-            String enableImeCommand = COMMAND_PREFIX_ENABLE_IME + ime;
-            runShellCommand(getInstrumentation(), enableImeCommand);
-        }
-        mEnabledImes = null;
+    protected static Instrumentation getInstrumentation() {
+        return sInstrumentation;
     }
 
-    @Override
-    protected void runTest() throws Throwable {
-        // Do nothing if the device does not support printing.
-        if (supportsPrinting()) {
-            super.runTest();
-        }
-    }
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+        sInstrumentation = InstrumentationRegistry.getInstrumentation();
+        assumeTrue(sInstrumentation.getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_PRINTING));
 
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        if (!supportsPrinting()) {
-            return;
-        }
+        sUiDevice = UiDevice.getInstance(sInstrumentation);
 
         // Make sure we start with a clean slate.
         clearPrintSpoolerData();
-        disableImes();
 
         // Workaround for dexmaker bug: https://code.google.com/p/dexmaker/issues/detail?id=2
         // Dexmaker is used by mockito.
         System.setProperty("dexmaker.dexcache", getInstrumentation()
                 .getTargetContext().getCacheDir().getPath());
+    }
 
-        // Set to US locale.
-        Resources resources = getInstrumentation().getTargetContext().getResources();
-        Configuration oldConfiguration = resources.getConfiguration();
-        if (!oldConfiguration.getLocales().get(0).equals(Locale.US)) {
-            mOldLocale = oldConfiguration.getLocales();
-            DisplayMetrics displayMetrics = resources.getDisplayMetrics();
-            Configuration newConfiguration = new Configuration(oldConfiguration);
-            newConfiguration.setLocale(Locale.US);
-            resources.updateConfiguration(newConfiguration, displayMetrics);
-        }
-
+    @Before
+    public void initCounters() throws Exception {
         // Initialize the latches.
         mStartCallCounter = new CallCounter();
         mStartSessionCallCounter = new CallCounter();
-
-        // Create the activity for the right locale.
-        createActivity();
     }
 
-    @Override
-    public void tearDown() throws Exception {
-        if (!supportsPrinting()) {
-            return;
-        }
-
-        // Done with the activity.
-        getActivity().finish();
-        enableImes();
-
-        // Restore the locale if needed.
-        if (mOldLocale != null) {
-            Resources resources = getInstrumentation().getTargetContext().getResources();
-            DisplayMetrics displayMetrics = resources.getDisplayMetrics();
-            Configuration newConfiguration = new Configuration(resources.getConfiguration());
-            newConfiguration.setLocales(mOldLocale);
-            mOldLocale = null;
-            resources.updateConfiguration(newConfiguration, displayMetrics);
-        }
-
-        // Make sure the spooler is cleaned, this also un-approves all services
-        clearPrintSpoolerData();
-
-        super.tearDown();
+    @After
+    public void exitActivities() throws Exception {
+        // Exit print spooler
+        getUiDevice().pressBack();
+        getUiDevice().pressBack();
     }
 
     protected android.print.PrintJob print(@NonNull final PrintDocumentAdapter adapter,
             final PrintAttributes attributes) {
         // Initiate printing as if coming from the app.
-        getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                PrintManager printManager = (PrintManager) getActivity()
-                        .getSystemService(Context.PRINT_SERVICE);
-                mPrintJob = printManager.print("Print job", adapter, attributes);
-            }
+        getInstrumentation().runOnMainSync(() -> {
+            PrintManager printManager = (PrintManager) getActivity()
+                    .getSystemService(Context.PRINT_SERVICE);
+            mPrintJob = printManager.print("Print job", adapter, attributes);
         });
 
         return mPrintJob;
@@ -215,7 +179,7 @@
         waitForCallbackCallCount(mStartCallCounter, 1, "Did not get expected call to start.");
     }
 
-    private void waitForCallbackCallCount(CallCounter counter, int count, String message) {
+    private static void waitForCallbackCallCount(CallCounter counter, int count, String message) {
         try {
             counter.waitForCount(count, OPERATION_TIMEOUT);
         } catch (TimeoutException te) {
@@ -224,12 +188,7 @@
     }
 
     protected PrintTestActivity getActivity() {
-        return mActivity;
-    }
-
-    protected void createActivity() {
-        mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
-                PrintTestActivity.class, null);
+        return mActivityRule.getActivity();
     }
 
     public static String runShellCommand(Instrumentation instrumentation, String cmd)
@@ -238,7 +197,7 @@
         byte[] buf = new byte[512];
         int bytesRead;
         FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
-        StringBuffer stdout = new StringBuffer();
+        StringBuilder stdout = new StringBuilder();
         while ((bytesRead = fis.read(buf)) != -1) {
             stdout.append(new String(buf, 0, bytesRead));
         }
@@ -246,7 +205,7 @@
         return stdout.toString();
     }
 
-    protected void clearPrintSpoolerData() throws Exception {
+    protected static void clearPrintSpoolerData() throws Exception {
         assertTrue("failed to clear print spooler data",
                 runShellCommand(getInstrumentation(), String.format(
                         "pm clear --user %d %s", CURRENT_USER_ID,
@@ -319,7 +278,7 @@
         return service;
     }
 
-    protected final class CallCounter {
+    private static final class CallCounter {
         private final Object mLock = new Object();
 
         private int mCallCount;
@@ -331,7 +290,7 @@
             }
         }
 
-        public int getCallCount() {
+        int getCallCount() {
             synchronized (mLock) {
                 return mCallCount;
             }
@@ -355,9 +314,4 @@
             }
         }
     }
-
-    protected boolean supportsPrinting() {
-        return getInstrumentation().getContext().getPackageManager()
-                .hasSystemFeature(PackageManager.FEATURE_PRINTING);
-    }
 }
diff --git a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
index d491ec4..2e9c8e7 100644
--- a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
+++ b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
@@ -38,17 +38,23 @@
 import android.print.mockservice.PrinterDiscoverySessionCallbacks;
 import android.print.mockservice.StubbablePrinterDiscoverySession;
 
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+import android.support.test.filters.LargeTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
 import java.util.List;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
 /**
  * tests feeding all possible parameters to the IPrintManager Binder.
  */
+@RunWith(AndroidJUnit4.class)
 public class IPrintManagerParametersTest extends BasePrintTest {
 
     private final int BAD_APP_ID = 0xffffffff;
@@ -58,9 +64,7 @@
     private final PrintJobId mBadPrintJobId;
 
     private PrintJob mGoodPrintJob;
-    private PrinterId mBadPrinterId;
     private PrinterId mGoodPrinterId;
-    private ComponentName mGoodComponentName;
     private ComponentName mBadComponentName;
 
     private IPrintManager mIPrintManager;
@@ -93,6 +97,7 @@
             public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
                     CancellationSignal cancellationSignal, LayoutResultCallback callback,
                     Bundle extras) {
+                callback.onLayoutFailed("not implemented");
             }
 
             @Override
@@ -109,54 +114,46 @@
      */
     private PrintServiceCallbacks createMockCallbacks() {
         return createMockPrintServiceCallbacks(
-                new Answer<PrinterDiscoverySessionCallbacks>() {
-                    @Override
-                    public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
-                        return createMockPrinterDiscoverySessionCallbacks(new Answer<Void>() {
-                            @Override
-                            public Void answer(InvocationOnMock invocation) {
-                                // Get the session.
-                                StubbablePrinterDiscoverySession session =
-                                        ((PrinterDiscoverySessionCallbacks) invocation
-                                        .getMock()).getSession();
+                invocation -> createMockPrinterDiscoverySessionCallbacks(invocation1 -> {
+                    // Get the session.
+                    StubbablePrinterDiscoverySession session =
+                            ((PrinterDiscoverySessionCallbacks) invocation1
+                            .getMock()).getSession();
 
-                                if (session.getPrinters().isEmpty()) {
-                                    final String PRINTER_NAME = "good printer";
-                                    List<PrinterInfo> printers = new ArrayList<>();
+                    if (session.getPrinters().isEmpty()) {
+                        final String PRINTER_NAME = "good printer";
+                        List<PrinterInfo> printers = new ArrayList<>();
 
-                                    // Add the printer.
-                                    mGoodPrinterId = session.getService()
-                                            .generatePrinterId(PRINTER_NAME);
+                        // Add the printer.
+                        mGoodPrinterId = session.getService()
+                                .generatePrinterId(PRINTER_NAME);
 
-                                    PrinterCapabilitiesInfo capabilities =
-                                            new PrinterCapabilitiesInfo.Builder(mGoodPrinterId)
-                                                    .setMinMargins(
-                                                            new Margins(200, 200, 200, 200))
-                                                    .addMediaSize(MediaSize.ISO_A4, true)
-                                                    .addResolution(new Resolution("300x300",
-                                                            "300x300", 300, 300),
-                                                            true)
-                                                    .setColorModes(
-                                                            PrintAttributes.COLOR_MODE_COLOR,
-                                                            PrintAttributes.COLOR_MODE_COLOR)
-                                                    .build();
+                        PrinterCapabilitiesInfo capabilities =
+                                new PrinterCapabilitiesInfo.Builder(mGoodPrinterId)
+                                        .setMinMargins(
+                                                new Margins(200, 200, 200, 200))
+                                        .addMediaSize(MediaSize.ISO_A4, true)
+                                        .addResolution(new Resolution("300x300",
+                                                "300x300", 300, 300),
+                                                true)
+                                        .setColorModes(
+                                                PrintAttributes.COLOR_MODE_COLOR,
+                                                PrintAttributes.COLOR_MODE_COLOR)
+                                        .build();
 
-                                    PrinterInfo printer = new PrinterInfo.Builder(
-                                            mGoodPrinterId,
-                                            PRINTER_NAME,
-                                            PrinterInfo.STATUS_IDLE)
-                                                    .setCapabilities(capabilities)
-                                                    .build();
-                                    printers.add(printer);
+                        PrinterInfo printer = new PrinterInfo.Builder(
+                                mGoodPrinterId,
+                                PRINTER_NAME,
+                                PrinterInfo.STATUS_IDLE)
+                                        .setCapabilities(capabilities)
+                                        .build();
+                        printers.add(printer);
 
-                                    session.addPrinters(printers);
-                                }
-                                onPrinterDiscoverySessionStartCalled();
-                                return null;
-                            }
-                        }, null, null, null, null, null, null);
+                        session.addPrinters(printers);
                     }
-                },
+                    onPrinterDiscoverySessionStartCalled();
+                    return null;
+                }, null, null, null, null, null, null),
                 null, null);
     }
 
@@ -214,60 +211,28 @@
         waitForPrinterDiscoverySessionStartCallbackCalled();
     }
 
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
+    /**
+     * Return a printer Id that is not from any print service
+     *
+     * @return The bad printer id.
+     */
+    private PrinterId getBadPrinterId() {
+        return new PrinterId(getActivity().getComponentName(), "dummy printer");
+    }
 
+    @Before
+    public void setUpMockService() throws Exception {
         MockPrintService.setCallbacks(createMockCallbacks());
 
-        mGoodComponentName = getActivity().getComponentName();
-
         mIPrintManager = IPrintManager.Stub
                 .asInterface(ServiceManager.getService(Context.PRINT_SERVICE));
-
-        // Generate dummy printerId which is a valid PrinterId object, but does not correspond to a
-        // printer
-        mBadPrinterId = new PrinterId(mGoodComponentName, "dummy printer");
-    }
-
-    /**
-     * {@link Runnable} that can throw and {@link Exception}
-     */
-    private interface Invokable {
-        /**
-         * Execute the invokable
-         *
-         * @throws Exception
-         */
-        void run() throws Exception;
-    }
-
-    /**
-     * Assert that the invokable throws an expectedException
-     *
-     * @param invokable The {@link Invokable} to run
-     * @param expectedClass The {@link Exception} that is supposed to be thrown
-     */
-    public void assertException(Invokable invokable, Class<? extends Exception> expectedClass)
-            throws Exception {
-        try {
-            invokable.run();
-        } catch (Exception e) {
-            if (e.getClass().isAssignableFrom(expectedClass)) {
-                return;
-            } else {
-                throw new AssertionError("Expected: " + expectedClass.getName() + ", got: "
-                                + e.getClass().getName());
-            }
-        }
-
-        throw new AssertionError("No exception thrown");
     }
 
     /**
      * test IPrintManager.getPrintJobInfo
      */
     @LargeTest
+    @Test
     public void testGetPrintJobInfo() throws Exception {
         startPrinting();
 
@@ -276,12 +241,9 @@
         assertEquals(null, mIPrintManager.getPrintJobInfo(mBadPrintJobId, mAppId, mUserId));
         assertEquals(null, mIPrintManager.getPrintJobInfo(null, mAppId, mUserId));
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.getPrintJobInfo(mGoodPrintJob.getId(), BAD_APP_ID, mUserId);
-            }
-        }, SecurityException.class);
+        assertException(
+                () -> mIPrintManager.getPrintJobInfo(mGoodPrintJob.getId(), BAD_APP_ID, mUserId),
+                SecurityException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -290,6 +252,7 @@
      * test IPrintManager.getPrintJobInfos
      */
     @LargeTest
+    @Test
     public void testGetPrintJobInfos() throws Exception {
         startPrinting();
 
@@ -304,12 +267,8 @@
         }
         assertTrue(foundPrintJob);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.getPrintJobInfos(BAD_APP_ID, mUserId);
-            }
-        }, SecurityException.class);
+        assertException(() -> mIPrintManager.getPrintJobInfos(BAD_APP_ID, mUserId),
+                SecurityException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -318,6 +277,7 @@
      * test IPrintManager.print
      */
     @LargeTest
+    @Test
     public void testPrint() throws Exception {
         final String name = "dummy print job";
 
@@ -326,44 +286,23 @@
 
         startPrinting();
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.print(null, adapter, null, mGoodComponentName.getPackageName(),
-                        mAppId, mUserId);
-            }
-        }, IllegalArgumentException.class);
+        assertException(() -> mIPrintManager.print(null, adapter, null,
+                getActivity().getPackageName(), mAppId, mUserId),
+                IllegalArgumentException.class);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.print(name, null, null, mGoodComponentName.getPackageName(),
-                        mAppId, mUserId);
-            }
-        }, NullPointerException.class);
+        assertException(() -> mIPrintManager.print(name, null, null,
+                getActivity().getPackageName(), mAppId, mUserId),
+                NullPointerException.class);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.print(name, adapter, null, null, mAppId, mUserId);
-            }
-        }, IllegalArgumentException.class);
+        assertException(() -> mIPrintManager.print(name, adapter, null, null, mAppId, mUserId),
+                IllegalArgumentException.class);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.print(name, adapter, null, mBadComponentName.getPackageName(),
-                        mAppId, mUserId);
-            }
-        }, IllegalArgumentException.class);
+        assertException(() -> mIPrintManager.print(name, adapter, null,
+                mBadComponentName.getPackageName(), mAppId, mUserId),
+                IllegalArgumentException.class);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.print(name, adapter, null, mGoodComponentName.getPackageName(),
-                        BAD_APP_ID, mUserId);
-            }
-        }, SecurityException.class);
+        assertException(() -> mIPrintManager.print(name, adapter, null,
+                getActivity().getPackageName(), BAD_APP_ID, mUserId), SecurityException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -372,6 +311,7 @@
      * test IPrintManager.cancelPrintJob
      */
     @LargeTest
+    @Test
     public void testCancelPrintJob() throws Exception {
         startPrinting();
 
@@ -379,12 +319,9 @@
         mIPrintManager.cancelPrintJob(mBadPrintJobId, mAppId, mUserId);
         mIPrintManager.cancelPrintJob(null, mAppId, mUserId);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.cancelPrintJob(mGoodPrintJob.getId(), BAD_APP_ID, mUserId);
-            }
-        }, SecurityException.class);
+        assertException(
+                () -> mIPrintManager.cancelPrintJob(mGoodPrintJob.getId(), BAD_APP_ID, mUserId),
+                SecurityException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
 
@@ -396,6 +333,7 @@
      * test IPrintManager.restartPrintJob
      */
     @LargeTest
+    @Test
     public void testRestartPrintJob() throws Exception {
         startPrinting();
 
@@ -405,12 +343,9 @@
         mIPrintManager.restartPrintJob(mBadPrintJobId, mAppId, mUserId);
         mIPrintManager.restartPrintJob(null, mAppId, mUserId);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.restartPrintJob(mGoodPrintJob.getId(), BAD_APP_ID, mUserId);
-            }
-        }, SecurityException.class);
+        assertException(
+                () -> mIPrintManager.restartPrintJob(mGoodPrintJob.getId(), BAD_APP_ID, mUserId),
+                SecurityException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -419,24 +354,18 @@
      * test IPrintManager.addPrintJobStateChangeListener
      */
     @MediumTest
+    @Test
     public void testAddPrintJobStateChangeListener() throws Exception {
         final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
 
         mIPrintManager.addPrintJobStateChangeListener(listener, mAppId, mUserId);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.addPrintJobStateChangeListener(null, mAppId, mUserId);
-            }
-        }, NullPointerException.class);
+        assertException(() -> mIPrintManager.addPrintJobStateChangeListener(null, mAppId, mUserId),
+                NullPointerException.class);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.addPrintJobStateChangeListener(listener, BAD_APP_ID, mUserId);
-            }
-        }, SecurityException.class);
+        assertException(
+                () -> mIPrintManager.addPrintJobStateChangeListener(listener, BAD_APP_ID, mUserId),
+                SecurityException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -445,6 +374,7 @@
      * test IPrintManager.removePrintJobStateChangeListener
      */
     @MediumTest
+    @Test
     public void testRemovePrintJobStateChangeListener() throws Exception {
         final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
 
@@ -455,12 +385,8 @@
         mIPrintManager.removePrintJobStateChangeListener(listener, mUserId);
 
         mIPrintManager.addPrintJobStateChangeListener(listener, mAppId, mUserId);
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.removePrintJobStateChangeListener(null, mUserId);
-            }
-        }, NullPointerException.class);
+        assertException(() -> mIPrintManager.removePrintJobStateChangeListener(null, mUserId),
+                NullPointerException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -469,17 +395,14 @@
      * test IPrintManager.addPrintServicesChangeListener
      */
     @MediumTest
+    @Test
     public void testAddPrintServicesChangeListener() throws Exception {
         final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
 
         mIPrintManager.addPrintServicesChangeListener(listener, mUserId);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.addPrintServicesChangeListener(null, mUserId);
-            }
-        }, NullPointerException.class);
+        assertException(() -> mIPrintManager.addPrintServicesChangeListener(null, mUserId),
+                NullPointerException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -488,6 +411,7 @@
      * test IPrintManager.removePrintServicesChangeListener
      */
     @MediumTest
+    @Test
     public void testRemovePrintServicesChangeListener() throws Exception {
         final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
 
@@ -498,12 +422,8 @@
         mIPrintManager.removePrintServicesChangeListener(listener, mUserId);
 
         mIPrintManager.addPrintServicesChangeListener(listener, mUserId);
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.removePrintServicesChangeListener(null, mUserId);
-            }
-        }, NullPointerException.class);
+        assertException(() -> mIPrintManager.removePrintServicesChangeListener(null, mUserId),
+                NullPointerException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -512,6 +432,7 @@
      * test IPrintManager.getPrintServices
      */
     @MediumTest
+    @Test
     public void testGetPrintServices() throws Exception {
         List<PrintServiceInfo> printServices = mIPrintManager.getPrintServices(
                 PrintManager.ALL_SERVICES, mUserId);
@@ -520,12 +441,8 @@
         printServices = mIPrintManager.getPrintServices(0, mUserId);
         assertEquals(printServices, null);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.getPrintServices(~PrintManager.ALL_SERVICES, mUserId);
-            }
-        }, IllegalArgumentException.class);
+        assertException(() -> mIPrintManager.getPrintServices(~PrintManager.ALL_SERVICES, mUserId),
+                IllegalArgumentException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -534,38 +451,23 @@
      * test IPrintManager.setPrintServiceEnabled
      */
     @MediumTest
+    @Test
     public void testSetPrintServiceEnabled() throws Exception {
         final ComponentName printService = mIPrintManager.getPrintServices(
                 PrintManager.ALL_SERVICES, mUserId).get(0).getComponentName();
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.setPrintServiceEnabled(printService, false, mUserId);
-            }
-        }, SecurityException.class);
+        assertException(() -> mIPrintManager.setPrintServiceEnabled(printService, false, mUserId),
+                SecurityException.class);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.setPrintServiceEnabled(printService, true, mUserId);
-            }
-        }, SecurityException.class);
+        assertException(() -> mIPrintManager.setPrintServiceEnabled(printService, true, mUserId),
+                SecurityException.class);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.setPrintServiceEnabled(new ComponentName("bad", "name"), true,
-                                mUserId);
-            }
-        }, SecurityException.class);
+        assertException(
+                () -> mIPrintManager.setPrintServiceEnabled(new ComponentName("bad", "name"), true,
+                                mUserId), SecurityException.class);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.setPrintServiceEnabled(null, true, mUserId);
-            }
-        }, SecurityException.class);
+        assertException(() -> mIPrintManager.setPrintServiceEnabled(null, true, mUserId),
+                SecurityException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -574,18 +476,16 @@
      * test IPrintManager.addPrintServiceRecommendationsChangeListener
      */
     @MediumTest
+    @Test
     public void testAddPrintServiceRecommendationsChangeListener() throws Exception {
         final IRecommendationsChangeListener listener =
                 createMockIPrintServiceRecommendationsChangeListener();
 
         mIPrintManager.addPrintServiceRecommendationsChangeListener(listener, mUserId);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.addPrintServiceRecommendationsChangeListener(null, mUserId);
-            }
-        }, NullPointerException.class);
+        assertException(
+                () -> mIPrintManager.addPrintServiceRecommendationsChangeListener(null, mUserId),
+                NullPointerException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -594,6 +494,7 @@
      * test IPrintManager.removePrintServicesChangeListener
      */
     @MediumTest
+    @Test
     public void testRemovePrintServiceRecommendationsChangeListener() throws Exception {
         final IRecommendationsChangeListener listener =
                 createMockIPrintServiceRecommendationsChangeListener();
@@ -605,12 +506,9 @@
         mIPrintManager.removePrintServiceRecommendationsChangeListener(listener, mUserId);
 
         mIPrintManager.addPrintServiceRecommendationsChangeListener(listener, mUserId);
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.removePrintServiceRecommendationsChangeListener(null, mUserId);
-            }
-        }, NullPointerException.class);
+        assertException(
+                () -> mIPrintManager.removePrintServiceRecommendationsChangeListener(null, mUserId),
+                NullPointerException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -619,6 +517,7 @@
      * test IPrintManager.getPrintServiceRecommendations
      */
     @MediumTest
+    @Test
     public void testGetPrintServiceRecommendations() throws Exception {
         mIPrintManager.getPrintServiceRecommendations(mUserId);
 
@@ -629,18 +528,15 @@
      * test IPrintManager.createPrinterDiscoverySession
      */
     @MediumTest
+    @Test
     public void testCreatePrinterDiscoverySession() throws Exception {
         final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
 
         mIPrintManager.createPrinterDiscoverySession(listener, mUserId);
 
         try {
-            assertException(new Invokable() {
-                @Override
-                public void run() throws Exception {
-                    mIPrintManager.createPrinterDiscoverySession(null, mUserId);
-                }
-            }, NullPointerException.class);
+            assertException(() -> mIPrintManager.createPrinterDiscoverySession(null, mUserId),
+                    NullPointerException.class);
 
             // Cannot test bad user Id as these tests are allowed to call across users
         } finally {
@@ -655,6 +551,7 @@
      * test IPrintManager.startPrinterDiscovery
      */
     @LargeTest
+    @Test
     public void testStartPrinterDiscovery() throws Exception {
         startPrinting();
 
@@ -663,7 +560,7 @@
         goodPrinters.add(mGoodPrinterId);
 
         final List<PrinterId> badPrinters = new ArrayList<>();
-        badPrinters.add(mBadPrinterId);
+        badPrinters.add(getBadPrinterId());
 
         final List<PrinterId> emptyPrinters = new ArrayList<>();
 
@@ -677,19 +574,11 @@
         mIPrintManager.startPrinterDiscovery(listener, emptyPrinters, mUserId);
         mIPrintManager.startPrinterDiscovery(listener, null, mUserId);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.startPrinterDiscovery(listener, nullPrinters, mUserId);
-            }
-        }, NullPointerException.class);
+        assertException(() -> mIPrintManager.startPrinterDiscovery(listener, nullPrinters, mUserId),
+                NullPointerException.class);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.startPrinterDiscovery(null, goodPrinters, mUserId);
-            }
-        }, NullPointerException.class);
+        assertException(() -> mIPrintManager.startPrinterDiscovery(null, goodPrinters, mUserId),
+                NullPointerException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -698,6 +587,7 @@
      * test IPrintManager.stopPrinterDiscovery
      */
     @MediumTest
+    @Test
     public void testStopPrinterDiscovery() throws Exception {
         final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
 
@@ -708,12 +598,8 @@
         mIPrintManager.stopPrinterDiscovery(listener, mUserId);
 
         mIPrintManager.startPrinterDiscovery(listener, null, mUserId);
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.stopPrinterDiscovery(null, mUserId);
-            }
-        }, NullPointerException.class);
+        assertException(() -> mIPrintManager.stopPrinterDiscovery(null, mUserId),
+                NullPointerException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -722,6 +608,7 @@
      * test IPrintManager.validatePrinters
      */
     @LargeTest
+    @Test
     public void testValidatePrinters() throws Exception {
         startPrinting();
 
@@ -729,7 +616,7 @@
         goodPrinters.add(mGoodPrinterId);
 
         final List<PrinterId> badPrinters = new ArrayList<>();
-        badPrinters.add(mBadPrinterId);
+        badPrinters.add(getBadPrinterId());
 
         final List<PrinterId> emptyPrinters = new ArrayList<>();
 
@@ -742,19 +629,11 @@
         mIPrintManager.validatePrinters(badPrinters, mUserId);
         mIPrintManager.validatePrinters(emptyPrinters, mUserId);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.validatePrinters(null, mUserId);
-            }
-        }, NullPointerException.class);
+        assertException(() -> mIPrintManager.validatePrinters(null, mUserId),
+                NullPointerException.class);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.validatePrinters(nullPrinters, mUserId);
-            }
-        }, NullPointerException.class);
+        assertException(() -> mIPrintManager.validatePrinters(nullPrinters, mUserId),
+                NullPointerException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -763,20 +642,17 @@
      * test IPrintManager.startPrinterStateTracking
      */
     @LargeTest
+    @Test
     public void testStartPrinterStateTracking() throws Exception {
         startPrinting();
 
         mIPrintManager.startPrinterStateTracking(mGoodPrinterId, mUserId);
 
         // Bad printers do no cause exceptions
-        mIPrintManager.startPrinterStateTracking(mBadPrinterId, mUserId);
+        mIPrintManager.startPrinterStateTracking(getBadPrinterId(), mUserId);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.startPrinterStateTracking(null, mUserId);
-            }
-        }, NullPointerException.class);
+        assertException(() -> mIPrintManager.startPrinterStateTracking(null, mUserId),
+                NullPointerException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -785,20 +661,17 @@
      * test IPrintManager.getCustomPrinterIcon
      */
     @LargeTest
+    @Test
     public void testGetCustomPrinterIcon() throws Exception {
         startPrinting();
 
         mIPrintManager.getCustomPrinterIcon(mGoodPrinterId, mUserId);
 
         // Bad printers do no cause exceptions
-        mIPrintManager.getCustomPrinterIcon(mBadPrinterId, mUserId);
+        mIPrintManager.getCustomPrinterIcon(getBadPrinterId(), mUserId);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.getCustomPrinterIcon(null, mUserId);
-            }
-        }, NullPointerException.class);
+        assertException(() -> mIPrintManager.getCustomPrinterIcon(null, mUserId),
+                NullPointerException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -807,6 +680,7 @@
      * test IPrintManager.stopPrinterStateTracking
      */
     @LargeTest
+    @Test
     public void testStopPrinterStateTracking() throws Exception {
         startPrinting();
 
@@ -817,15 +691,11 @@
         mIPrintManager.stopPrinterStateTracking(mGoodPrinterId, mUserId);
 
         // Bad printers do no cause exceptions
-        mIPrintManager.startPrinterStateTracking(mBadPrinterId, mUserId);
-        mIPrintManager.stopPrinterStateTracking(mBadPrinterId, mUserId);
+        mIPrintManager.startPrinterStateTracking(getBadPrinterId(), mUserId);
+        mIPrintManager.stopPrinterStateTracking(getBadPrinterId(), mUserId);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.stopPrinterStateTracking(null, mUserId);
-            }
-        }, NullPointerException.class);
+        assertException(() -> mIPrintManager.stopPrinterStateTracking(null, mUserId),
+                NullPointerException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
@@ -834,6 +704,7 @@
      * test IPrintManager.destroyPrinterDiscoverySession
      */
     @MediumTest
+    @Test
     public void testDestroyPrinterDiscoverySession() throws Exception {
         final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
 
@@ -843,12 +714,8 @@
         // Destroying already destroyed session is a no-op
         mIPrintManager.destroyPrinterDiscoverySession(listener, mUserId);
 
-        assertException(new Invokable() {
-            @Override
-            public void run() throws Exception {
-                mIPrintManager.destroyPrinterDiscoverySession(null, mUserId);
-            }
-        }, NullPointerException.class);
+        assertException(() -> mIPrintManager.destroyPrinterDiscoverySession(null, mUserId),
+                NullPointerException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
diff --git a/core/tests/coretests/src/android/print/PrintTestActivity.java b/core/tests/coretests/src/android/print/PrintTestActivity.java
index 86074a6..e9b001f 100644
--- a/core/tests/coretests/src/android/print/PrintTestActivity.java
+++ b/core/tests/coretests/src/android/print/PrintTestActivity.java
@@ -21,7 +21,6 @@
 import android.view.WindowManager;
 
 public class PrintTestActivity extends Activity {
-
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
diff --git a/core/tests/coretests/src/android/print/WorkflowTest.java b/core/tests/coretests/src/android/print/WorkflowTest.java
new file mode 100644
index 0000000..35cfe22
--- /dev/null
+++ b/core/tests/coretests/src/android/print/WorkflowTest.java
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package android.print;
+
+import android.graphics.pdf.PdfDocument;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.ParcelFileDescriptor;
+import android.print.mockservice.AddPrintersActivity;
+import android.print.mockservice.MockPrintService;
+
+import android.print.mockservice.PrinterDiscoverySessionCallbacks;
+import android.print.mockservice.StubbablePrinterDiscoverySession;
+import android.print.pdf.PrintedPdfDocument;
+import android.support.test.filters.LargeTest;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiSelector;
+import android.util.Log;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeoutException;
+import java.util.function.Supplier;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for the basic printing workflows
+ */
+public class WorkflowTest extends BasePrintTest {
+    private static final String LOG_TAG = WorkflowTest.class.getSimpleName();
+
+    private static float sWindowAnimationScaleBefore;
+    private static float sTransitionAnimationScaleBefore;
+    private static float sAnimatiorDurationScaleBefore;
+
+    interface InterruptableConsumer<T> {
+        void accept(T t) throws InterruptedException;
+    }
+
+    /**
+     * Execute {@code waiter} until {@code condition} is met.
+     *
+     * @param condition Conditions to wait for
+     * @param waiter    Code to execute while waiting
+     */
+    private void waitWithTimeout(Supplier<Boolean> condition, InterruptableConsumer<Long> waiter)
+            throws TimeoutException, InterruptedException {
+        long startTime = System.currentTimeMillis();
+        while (condition.get()) {
+            long timeLeft = OPERATION_TIMEOUT - (System.currentTimeMillis() - startTime);
+            if (timeLeft < 0) {
+                throw new TimeoutException();
+            }
+
+            waiter.accept(timeLeft);
+        }
+    }
+
+    /**
+     * Executes a shell command using shell user identity, and return the standard output in
+     * string.
+     *
+     * @param cmd the command to run
+     *
+     * @return the standard output of the command
+     */
+    private static String runShellCommand(String cmd) throws IOException {
+        try (FileInputStream is = new ParcelFileDescriptor.AutoCloseInputStream(
+                getInstrumentation().getUiAutomation().executeShellCommand(cmd))) {
+            byte[] buf = new byte[64];
+            int bytesRead;
+
+            StringBuilder stdout = new StringBuilder();
+            while ((bytesRead = is.read(buf)) != -1) {
+                stdout.append(new String(buf, 0, bytesRead));
+            }
+
+            return stdout.toString();
+        }
+    }
+
+    @BeforeClass
+    public static void disableAnimations() throws Exception {
+        try {
+            sWindowAnimationScaleBefore = Float.parseFloat(runShellCommand(
+                    "settings get global window_animation_scale"));
+
+            runShellCommand("settings put global window_animation_scale 0");
+        } catch (NumberFormatException e) {
+            sWindowAnimationScaleBefore = Float.NaN;
+        }
+        try {
+            sTransitionAnimationScaleBefore = Float.parseFloat(runShellCommand(
+                    "settings get global transition_animation_scale"));
+
+            runShellCommand("settings put global transition_animation_scale 0");
+        } catch (NumberFormatException e) {
+            sTransitionAnimationScaleBefore = Float.NaN;
+        }
+        try {
+            sAnimatiorDurationScaleBefore = Float.parseFloat(runShellCommand(
+                    "settings get global animator_duration_scale"));
+
+            runShellCommand("settings put global animator_duration_scale 0");
+        } catch (NumberFormatException e) {
+            sAnimatiorDurationScaleBefore = Float.NaN;
+        }
+    }
+
+    @AfterClass
+    public static void enableAnimations() throws Exception {
+        if (sWindowAnimationScaleBefore != Float.NaN) {
+            runShellCommand(
+                    "settings put global window_animation_scale " + sWindowAnimationScaleBefore);
+        }
+        if (sTransitionAnimationScaleBefore != Float.NaN) {
+            runShellCommand(
+                    "settings put global transition_animation_scale " +
+                            sTransitionAnimationScaleBefore);
+        }
+        if (sAnimatiorDurationScaleBefore != Float.NaN) {
+            runShellCommand(
+                    "settings put global animator_duration_scale " + sAnimatiorDurationScaleBefore);
+        }
+    }
+
+    /** Add a printer with a given name and supported mediasize to a session */
+    private void addPrinter(StubbablePrinterDiscoverySession session,
+            String name, PrintAttributes.MediaSize mediaSize) {
+        PrinterId printerId = session.getService().generatePrinterId(name);
+        List<PrinterInfo> printers = new ArrayList<>(1);
+
+        PrinterCapabilitiesInfo.Builder builder =
+                new PrinterCapabilitiesInfo.Builder(printerId);
+
+        builder.setMinMargins(new PrintAttributes.Margins(0, 0, 0, 0))
+                .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
+                        PrintAttributes.COLOR_MODE_COLOR)
+                .addMediaSize(mediaSize, true)
+                .addResolution(new PrintAttributes.Resolution("300x300", "300x300", 300, 300),
+                        true);
+
+        printers.add(new PrinterInfo.Builder(printerId, name,
+                PrinterInfo.STATUS_IDLE).setCapabilities(builder.build()).build());
+
+        session.addPrinters(printers);
+    }
+
+    /** Find a certain element in the UI and click on it */
+    private void clickOn(UiSelector selector) throws UiObjectNotFoundException {
+        Log.i(LOG_TAG, "Click on " + selector);
+        UiObject view = getUiDevice().findObject(selector);
+        view.click();
+        getUiDevice().waitForIdle();
+    }
+
+    /** Find a certain text in the UI and click on it */
+    private void clickOnText(String text) throws UiObjectNotFoundException {
+        clickOn(new UiSelector().text(text));
+    }
+
+    /** Set the printer in the print activity */
+    private void setPrinter(String printerName) throws UiObjectNotFoundException {
+        clickOn(new UiSelector().resourceId("com.android.printspooler:id/destination_spinner"));
+
+        clickOnText(printerName);
+    }
+
+    /**
+     * Init mock print servic that returns a single printer by default.
+     *
+     * @param sessionRef Where to store the reference to the session once started
+     */
+    private void setMockPrintServiceCallbacks(StubbablePrinterDiscoverySession[] sessionRef) {
+        MockPrintService.setCallbacks(createMockPrintServiceCallbacks(
+                inv -> createMockPrinterDiscoverySessionCallbacks(inv2 -> {
+                            synchronized (sessionRef) {
+                                sessionRef[0] = ((PrinterDiscoverySessionCallbacks) inv2.getMock())
+                                        .getSession();
+
+                                addPrinter(sessionRef[0], "1st printer",
+                                        PrintAttributes.MediaSize.ISO_A0);
+
+                                sessionRef.notifyAll();
+                            }
+                            return null;
+                        },
+                        null, null, null, null, null, inv2 -> {
+                            synchronized (sessionRef) {
+                                sessionRef[0] = null;
+                                sessionRef.notifyAll();
+                            }
+                            return null;
+                        }
+        ), null, null));
+    }
+
+    /**
+     * Start print operation that just prints a single empty page
+     *
+     * @param printAttributesRef Where to store the reference to the print attributes once started
+     */
+    private void print(PrintAttributes[] printAttributesRef) {
+        print(new PrintDocumentAdapter() {
+            @Override
+            public void onStart() {
+            }
+
+            @Override
+            public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
+                    CancellationSignal cancellationSignal, LayoutResultCallback callback,
+                    Bundle extras) {
+                callback.onLayoutFinished((new PrintDocumentInfo.Builder("doc")).build(),
+                        !newAttributes.equals(printAttributesRef[0]));
+
+                synchronized (printAttributesRef) {
+                    printAttributesRef[0] = newAttributes;
+                    printAttributesRef.notifyAll();
+                }
+            }
+
+            @Override
+            public void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
+                    CancellationSignal cancellationSignal, WriteResultCallback callback) {
+                try {
+                    try {
+                        PrintedPdfDocument document = new PrintedPdfDocument(getActivity(),
+                                printAttributesRef[0]);
+                        try {
+                            PdfDocument.Page page = document.startPage(0);
+                            document.finishPage(page);
+                            try (FileOutputStream os = new FileOutputStream(
+                                    destination.getFileDescriptor())) {
+                                document.writeTo(os);
+                                os.flush();
+                            }
+                        } finally {
+                            document.close();
+                        }
+                    } finally {
+                        destination.close();
+                    }
+
+                    callback.onWriteFinished(pages);
+                } catch (IOException e) {
+                    callback.onWriteFailed(e.getMessage());
+                }
+            }
+        }, null);
+    }
+
+    @Test
+    @LargeTest
+    public void addAndSelectPrinter() throws Exception {
+        final StubbablePrinterDiscoverySession session[] = new StubbablePrinterDiscoverySession[1];
+        final PrintAttributes printAttributes[] = new PrintAttributes[1];
+
+        setMockPrintServiceCallbacks(session);
+        print(printAttributes);
+
+        // We are now in the PrintActivity
+        Log.i(LOG_TAG, "Waiting for session");
+        synchronized (session) {
+            waitWithTimeout(() -> session[0] == null, session::wait);
+        }
+
+        setPrinter("1st printer");
+
+        Log.i(LOG_TAG, "Waiting for print attributes to change");
+        synchronized (printAttributes) {
+            waitWithTimeout(
+                    () -> printAttributes[0] == null || !printAttributes[0].getMediaSize().equals(
+                            PrintAttributes.MediaSize.ISO_A0), printAttributes::wait);
+        }
+
+        setPrinter("All printers\u2026");
+
+        // We are now in the SelectPrinterActivity
+        clickOnText("Add printer");
+
+        // We are now in the AddPrinterActivity
+        AddPrintersActivity.addObserver(
+                () -> addPrinter(session[0], "2nd printer", PrintAttributes.MediaSize.ISO_A1));
+
+        // This executes the observer registered above
+        clickOn(new UiSelector().text(MockPrintService.class.getCanonicalName())
+                        .resourceId("com.android.printspooler:id/title"));
+
+        getUiDevice().pressBack();
+        AddPrintersActivity.clearObservers();
+
+        // We are now in the SelectPrinterActivity
+        clickOnText("2nd printer");
+
+        // We are now in the PrintActivity
+        Log.i(LOG_TAG, "Waiting for print attributes to change");
+        synchronized (printAttributes) {
+            waitWithTimeout(
+                    () -> printAttributes[0] == null || !printAttributes[0].getMediaSize().equals(
+                            PrintAttributes.MediaSize.ISO_A1), printAttributes::wait);
+        }
+
+        getUiDevice().pressBack();
+
+        // We are back in the test activity
+        Log.i(LOG_TAG, "Waiting for session to end");
+        synchronized (session) {
+            waitWithTimeout(() -> session[0] != null, session::wait);
+        }
+    }
+
+    @Test
+    @LargeTest
+    public void abortSelectingPrinter() throws Exception {
+        final StubbablePrinterDiscoverySession session[] = new StubbablePrinterDiscoverySession[1];
+        final PrintAttributes printAttributes[] = new PrintAttributes[1];
+
+        setMockPrintServiceCallbacks(session);
+        print(printAttributes);
+
+        // We are now in the PrintActivity
+        Log.i(LOG_TAG, "Waiting for session");
+        synchronized (session) {
+            waitWithTimeout(() -> session[0] == null, session::wait);
+        }
+
+        setPrinter("1st printer");
+
+        Log.i(LOG_TAG, "Waiting for print attributes to change");
+        synchronized (printAttributes) {
+            waitWithTimeout(
+                    () -> printAttributes[0] == null || !printAttributes[0].getMediaSize().equals(
+                            PrintAttributes.MediaSize.ISO_A0), printAttributes::wait);
+        }
+
+        setPrinter("All printers\u2026");
+
+        // We are now in the SelectPrinterActivity
+        clickOnText("Add printer");
+
+        // We are now in the AddPrinterActivity
+        AddPrintersActivity.addObserver(
+                () -> addPrinter(session[0], "2nd printer", PrintAttributes.MediaSize.ISO_A1));
+
+        // This executes the observer registered above
+        clickOn(new UiSelector().text(MockPrintService.class.getCanonicalName())
+                .resourceId("com.android.printspooler:id/title"));
+
+        getUiDevice().pressBack();
+        AddPrintersActivity.clearObservers();
+
+        // Do not select a new printer, just press back
+        getUiDevice().pressBack();
+
+        // We are now in the PrintActivity
+        // The media size should not change
+        Log.i(LOG_TAG, "Make sure print attributes did not change");
+        Thread.sleep(100);
+        assertEquals(PrintAttributes.MediaSize.ISO_A0, printAttributes[0].getMediaSize());
+
+        getUiDevice().pressBack();
+
+        // We are back in the test activity
+        Log.i(LOG_TAG, "Waiting for session to end");
+        synchronized (session) {
+            waitWithTimeout(() -> session[0] != null, session::wait);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/print/mockservice/AddPrintersActivity.java b/core/tests/coretests/src/android/print/mockservice/AddPrintersActivity.java
new file mode 100644
index 0000000..8f1a9ed
--- /dev/null
+++ b/core/tests/coretests/src/android/print/mockservice/AddPrintersActivity.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package android.print.mockservice;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+
+import java.util.ArrayList;
+
+public class AddPrintersActivity extends Activity {
+    private static final ArrayList<Runnable> sObservers = new ArrayList<>();
+
+    public static void addObserver(@NonNull Runnable observer) {
+        synchronized (sObservers) {
+            sObservers.add(observer);
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        synchronized (sObservers) {
+            for (Runnable sObserver : sObservers) {
+                sObserver.run();
+            }
+        }
+
+        finish();
+    }
+
+    public static void clearObservers() {
+        synchronized (sObservers) {
+            sObservers.clear();
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/print/mockservice/StubbablePrinterDiscoverySession.java b/core/tests/coretests/src/android/print/mockservice/StubbablePrinterDiscoverySession.java
index e132d79..f3a5373 100644
--- a/core/tests/coretests/src/android/print/mockservice/StubbablePrinterDiscoverySession.java
+++ b/core/tests/coretests/src/android/print/mockservice/StubbablePrinterDiscoverySession.java
@@ -16,6 +16,7 @@
 
 package android.print.mockservice;
 
+import android.support.annotation.NonNull;
 import android.os.CancellationSignal;
 import android.print.PrinterId;
 import android.printservice.CustomPrinterIconCallback;
@@ -42,7 +43,7 @@
     }
 
     @Override
-    public void onStartPrinterDiscovery(List<PrinterId> priorityList) {
+    public void onStartPrinterDiscovery(@NonNull List<PrinterId> priorityList) {
         if (mCallbacks != null) {
             mCallbacks.onStartPrinterDiscovery(priorityList);
         }
@@ -56,29 +57,30 @@
     }
 
     @Override
-    public void onValidatePrinters(List<PrinterId> printerIds) {
+    public void onValidatePrinters(@NonNull List<PrinterId> printerIds) {
         if (mCallbacks != null) {
             mCallbacks.onValidatePrinters(printerIds);
         }
     }
 
     @Override
-    public void onStartPrinterStateTracking(PrinterId printerId) {
+    public void onStartPrinterStateTracking(@NonNull PrinterId printerId) {
         if (mCallbacks != null) {
             mCallbacks.onStartPrinterStateTracking(printerId);
         }
     }
 
     @Override
-    public void onRequestCustomPrinterIcon(PrinterId printerId,
-            CancellationSignal cancellationSignal, CustomPrinterIconCallback callback) {
+    public void onRequestCustomPrinterIcon(@NonNull PrinterId printerId,
+            @NonNull CancellationSignal cancellationSignal,
+            @NonNull CustomPrinterIconCallback callback) {
         if (mCallbacks != null) {
             mCallbacks.onRequestCustomPrinterIcon(printerId, cancellationSignal, callback);
         }
     }
 
     @Override
-    public void onStopPrinterStateTracking(PrinterId printerId) {
+    public void onStopPrinterStateTracking(@NonNull PrinterId printerId) {
         if (mCallbacks != null) {
             mCallbacks.onStopPrinterStateTracking(printerId);
         }
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 627f360..e46f166 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -43,7 +43,7 @@
     </permission>
 
     <permission name="android.permission.BLUETOOTH_STACK" >
-        <group gid="net_bt_stack" />
+        <group gid="bluetooth" />
         <group gid="wakelock" />
     </permission>
 
diff --git a/docs/html-intl/intl/id/about/versions/marshmallow/android-6.0-testing.jd b/docs/html-intl/intl/id/about/versions/marshmallow/android-6.0-testing.jd
new file mode 100644
index 0000000..94bc74c
--- /dev/null
+++ b/docs/html-intl/intl/id/about/versions/marshmallow/android-6.0-testing.jd
@@ -0,0 +1,190 @@
+page.title=Panduan Pengujian
+page.image=images/cards/card-n-guide_2x.png
+meta.tags="preview", "testing"
+page.tags="preview", "developer preview"
+
+@jd:body
+
+<div id="tb-wrapper">
+  <div id="tb">
+    <h2>Dalam dokumen ini</h2>
+      <ol>
+        <li><a href="#runtime-permissions">Izin Pengujian</a></li>
+        <li><a href="#doze-standby">Menguji Istirahatkan dan Aplikasi Siaga</a></li>
+        <li><a href="#ids">Pencadangan Otomatis dan Identifier Perangkat</a></li>
+      </ol>
+  </div>
+</div>
+
+<p>
+  Android N memberi Anda kesempatan untuk memastikan aplikasi bekerja pada
+  platform versi berikutnya. Pratinjau ini berisi beberapa API dan perubahan perilaku yang bisa
+  memengaruhi aplikasi Anda, sebagaimana dijelaskan dalam <a href="{@docRoot}preview/api-overview.html">Ringkasan
+  API</a> dan <a href="{@docRoot}preview/behavior-changes.html">Perubahan Perilaku</a>. Dalam menguji
+  aplikasi dengan pratinjau, ada beberapa perubahan sistem spesifik yang harus Anda fokuskan untuk
+  memastikan pengguna mendapatkan pengalaman yang bagus.
+</p>
+
+<p>
+  Panduan ini menjelaskan apa dan bagaimana menguji fitur pratinjau dengan aplikasi Anda. Anda harus
+  mengutamakan pengujian fitur pratinjau spesifik ini, dikarenakan pengaruhnya yang besar pada
+  perilaku aplikasi Anda:
+</p>
+
+<ul>
+  <li><a href="#runtime-permissions">Izin</a>
+  </li>
+  <li><a href="#doze-standby">Istirahatkan dan Aplikasi Siaga</a>
+  </li>
+  <li><a href="#ids">Pencadangan Otomatis dan Identifier Perangkat</a></li>
+</ul>
+
+<p>
+  Untuk informasi selengkapnya tentang cara menyiapkan perangkat atau perangkat maya dengan citra sistem pratinjau
+  untuk pengujian, lihat <a href="{@docRoot}preview/setup-sdk.html">Menyiapkan
+Android N SDK</a>.
+</p>
+
+
+<h2 id="runtime-permissions">Izin Pengujian</h2>
+
+<p>
+  Model <a href="{@docRoot}preview/features/runtime-permissions.html">Izin</a> yang baru
+  mengubah cara alokasi izin untuk aplikasi Anda oleh pengguna. Sebagai ganti memberi semua
+  izin selama prosedur pemasangan, aplikasi Anda harus meminta izin kepada pengguna secara individual
+ pada waktu proses. Bagi pengguna, perilaku ini memberi kontrol yang lebih detail atas setiap aktivitas aplikasi, dan
+  juga konteks yang lebih untuk memahami sebab aplikasi meminta izin tertentu. Pengguna
+  bisa memberi atau mencabut izin yang diberikan pada suatu aplikasi secara individual kapan saja. Fitur
+  pratinjau ini kemungkinan besar memengaruhi perilaku aplikasi Anda dan mungkin menghambat fungsi beberapa
+  fitur aplikasi Anda, atau mengurangi kualitas kerjanya.
+</p>
+
+<p class="caution">
+  Perubahan ini memengaruhi semua aplikasi yang berjalan di platform baru, bahkan aplikasi yang tidak menargetkan versi
+  platform baru. Platform ini memberikan perilaku kompatibilitas terbatas untuk aplikasi lawas, namun Anda
+  harus mulai merencanakan migrasi aplikasi ke model izin baru sekarang juga, dengan tujuan
+  mempublikasikan versi terbaru aplikasi Anda saat peluncuran platform secara resmi.
+</p>
+
+
+<h3 id="permission-test-tips">Tip pengujian</h3>
+
+<p>
+  Gunakan tip berikut untuk membantu Anda merencanakan dan menjalankan pengujian aplikasi dengan
+  perilaku izin yang baru.
+</p>
+
+<ul>
+  <li>Identifikasi izin aplikasi Anda saat ini dan jalur kode terkait.</li>
+  <li>Uji alur pengguna pada semua layanan dan data yang dilindungi izin.</li>
+  <li>Uji dengan berbagai kombinasi izin yang diberikan/dicabut.</li>
+  <li>Gunakan alat bantu {@code adb} untuk mengelola izin dari baris perintah:
+    <ul>
+      <li>Cantumkan daftar izin dan status berdasarkan kelompok:
+        <pre>adb shell pm list permissions -d -g</pre>
+      </li>
+      <li>Beri atau cabut satu atau beberapa izin menggunakan sintaks berikut:<br>
+        <pre>adb shell pm [grant|revoke] &lt;permission.name&gt; ...</pre>
+      </li>
+    </ul>
+  </li>
+  <li>Analisis aplikasi Anda untuk layanan yang menggunakan izin.</li>
+</ul>
+
+<h3 id="permission-test-strategy">Strategi pengujian</h3>
+
+<p>
+  Perubahan izin memengaruhi struktur dan desain aplikasi Anda, begitu juga
+  pengalaman pengguna dan alur yang Anda sediakan untuk pengguna. Anda harus menilai penggunaan izin
+  aplikasi saat ini dan mulai merencanakan alur baru yang ingin ditawarkan. Rilis platform
+  resmi menyediakan perilaku kompatibilitas, namun Anda harus merencanakan pembaruan aplikasi dan tidak
+  bergantung pada perilaku ini.
+</p>
+
+<p>
+  Identifikasi izin yang sebenarnya diperlukan dan digunakan aplikasi Anda, kemudian temukan berbagai
+  jalur kode yang menggunakan layanan yang dilindungi izin. Anda bisa melakukan ini melalui kombinasi
+  pengujian pada platform baru dan analisis kode. Dalam pengujian, Anda harus fokus pada pemilihan
+ izin waktu proses dengan mengubah {@code targetSdkVersion} aplikasi ke versi pratinjau. Untuk
+  informasi selengkapnya, lihat <a href="{@docRoot}preview/setup-sdk.html#">Menyiapkan
+Android N SDK</a>.
+</p>
+
+<p>
+  Uji dengan berbagai kombinasi izin yang dicabut dan ditambahkan, untuk menyoroti alur pengguna yang
+  bergantung pada izin. Jika dependensi tidak jelas atau logis, Anda harus mempertimbangkan
+optimalisasi atau kompartementalisasi alur tersebut untuk mengeliminasi dependensi atau menjelaskan alasan
+  diperlukannya izin.
+</p>
+
+<p>
+  Untuk informasi selengkapnya tentang perilaku izin waktu proses, pengujian, dan praktik terbaik, lihat
+  halaman pratinjau <a href="{@docRoot}preview/features/runtime-permissions.html">Izin</a>
+  pengembang.
+</p>
+
+
+<h2 id="doze-standby">Menguji Istirahatkan dan Aplikasi Siaga</h2>
+
+<p>
+  Fitur penghematan daya Istirahatkan dan Aplikasi Siaga membatasi jumlah pemrosesan latar belakang yang
+  bisa dikerjakan aplikasi Anda saat perangkat dalam keadaan diam atau saat aplikasi Anda sedang tidak fokus. Pembatasan
+  yang dapat diberlakukan oleh sistem pada aplikasi termasuk akses jaringan terbatas atau tidak ada,
+  tugas latar belakang yang ditangguhkan, Pemberitahuan yang ditangguhkan, permintaan membangunkan yang diabaikan, serta alarm. Untuk memastikan
+  aplikasi Anda berperilaku dengan benar pada optimalisasi penghematan daya ini, Anda harus menguji aplikasi dengan
+ menyimulasikan keadaan baterai yang sedang tinggal sedikit ini.
+</p>
+
+<h4 id="doze">Menguji aplikasi Anda dengan Istirahatkan</h4>
+
+<p>Untuk menguji Istirahatkan dengan aplikasi Anda:</p>
+
+<ol>
+<li>Konfigurasikan perangkat keras atau perangkat maya dengan citra sistem Android N.</li>
+<li>Hubungkan perangkat dengan mesin pengembangan dan pasang aplikasi Anda.</li>
+<li>Jalankan aplikasi Anda dan biarkan aktif.</li>
+<li>Simulasikan perangkat yang sedang masuk ke dalam mode Istirahatkan dengan menjalankan perintah berikut:
+
+<pre>
+$ adb shell dumpsys battery unplug
+$ adb shell dumpsys deviceidle step
+$ adb shell dumpsys deviceidle -h
+</pre>
+
+  </li>
+  <li>Amati perilaku aplikasi Anda saat perangkat diaktifkan kembali. Pastikan aplikasi
+    pulih dengan baik saat perangkat keluar dari Istirahatkan.</li>
+</ol>
+
+
+<h4 id="standby">Menguji aplikasi dengan Aplikasi Siaga</h4>
+
+<p>Untuk menguji mode Aplikasi Siaga dengan aplikasi Anda:</p>
+
+<ol>
+  <li>Konfigurasikan perangkat keras atau perangkat maya dengan citra sistem Android N.</li>
+  <li>Hubungkan perangkat dengan mesin pengembangan dan pasang aplikasi Anda.</li>
+  <li>Jalankan aplikasi Anda dan biarkan aktif.</li>
+  <li>Simulasikan aplikasi yang sedang masuk ke dalam mode siaga dengan menjalankan perintah berikut:
+
+<pre>
+$ adb shell am broadcast -a android.os.action.DISCHARGING
+$ adb shell am set-idle &lt;packageName&gt; true
+</pre>
+
+  </li>
+  <li>Simulasikan membangunkan aplikasi Anda menggunakan perintah berikut:
+    <pre>$ adb shell am set-idle &lt;packageName&gt; false</pre>
+  </li>
+  <li>Amati perilaku aplikasi Anda saat dibangunkan. Pastikan aplikasi pulih dengan baik
+   dari mode siaga. Secara khusus, Anda harus memeriksa apakah Pemberitahuan aplikasi dan pekerjaan latar belakang
+   tetap berjalan sebagaimana yang diharapkan.</li>
+</ol>
+
+<h2 id="ids">Auto Backup for Apps dan Identifier Perangkat Spesifik</h2>
+
+<p>Jika aplikasi Anda mempertahankan identifier perangkat spesifik, seperti ID pendaftaran Google
+Cloud Messaging, dalam penyimpanan internal,
+pastikan Anda mengikuti praktik terbaik untuk mengecualikan lokasi
+penyimpanan dari pencadangan otomatis, seperti dijelaskan dalam <a href="{@docRoot}preview/backup/index.html">Auto
+Backup for Apps</a>. </p>
diff --git a/docs/html-intl/intl/id/about/versions/nougat/android-7.0-changes.jd b/docs/html-intl/intl/id/about/versions/nougat/android-7.0-changes.jd
new file mode 100644
index 0000000..af01cd2
--- /dev/null
+++ b/docs/html-intl/intl/id/about/versions/nougat/android-7.0-changes.jd
@@ -0,0 +1,610 @@
+page.title=Perubahan Perilaku
+page.keywords=pratinjau,sdk,kompatibilitas
+meta.tags="preview", "compatibility"
+page.tags="preview", "developer preview"
+page.image=images/cards/card-n-changes_2x.png
+@jd:body
+
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>Dalam dokumen ini</h2>
+
+<ol>
+  <li><a href="#perf">Peningkatan Kinerja</a>
+    <ol>
+      <li><a href="#doze">Istirahatkan</a></li>
+      <li><a href="#bg-opt">Optimalisasi Latar Belakang</a></li>
+    </ol>
+  </li>
+  <li><a href="#perm">Perubahan Izin</a>
+  </li>
+  <li><a href="#sharing-files">Berbagi File Antar Aplikasi</a></li>
+  <li><a href="#accessibility">Peningkatan Aksesibilitas</a>
+    <ol>
+      <li><a href="#screen-zoom">Perbesaran Layar</a></li>
+      <li><a href="#vision-settings">Vision Settings di Setup Wizard</a></li>
+    </ol>
+  </li>
+  <li><a href="#ndk">Penautan Aplikasi NDK ke Pustaka Platform</a></li>
+  <li><a href="#afw">Android for Work</a></li>
+  <li><a href="#annotations">Retensi Anotasi</a></li>
+  <li><a href="#other">Poin Penting Lainnya</a></li>
+</ol>
+
+<h2>Lihat Juga</h2>
+<ol>
+  <li><a href="{@docRoot}preview/api-overview.html">
+    Ringkasan Android N API</a></li>
+</ol>
+
+</div>
+</div>
+
+
+<p>
+  Bersama fitur dan kemampuan baru, Android N
+  menyertakan berbagai macam perubahan sistem dan perubahan perilaku API. Dokumen ini
+  menyoroti beberapa perubahan utama yang harus dipahami dan diperhitungkan
+  dalam aplikasi Anda.
+</p>
+
+<p>
+  Jika Anda sebelumnya telah mempublikasikan aplikasi untuk Android, ketahuilah bahwa aplikasi Anda
+  mungkin dipengaruhi oleh perubahan dalam platform.
+</p>
+
+
+<h2 id="perf">Baterai dan Memori</h2>
+
+<p>
+Android N menyertakan perubahan perilaku sistem yang bertujuan untuk meningkatkan daya tahan baterai
+perangkat dan mengurangi penggunaan RAM. Perubahan ini bisa memengaruhi akses aplikasi Anda ke
+sumber daya sistem, termasuk cara aplikasi Anda berinteraksi dengan aplikasi lain melalui
+intent implisit tertentu.
+</p>
+
+<h3 id="doze">Istirahatkan</h3>
+
+<p>
+  Diperkenalkan dalam Android 6.0 (API level 23), Istirahatkan meningkatkan daya tahan baterai dengan
+  menangguhkan aktivitas CPU dan jaringan bila pengguna tidak mencabut perangkat,
+  tidak bergerak, dan layar dinonaktifkan. Android N lebih
+  menyempurnakan Istirahatkan dengan menerapkan subset CPU dan pembatasan jaringan
+  bila perangkat dicabut dan layar dinonaktifkan, namun tidak harus
+  diam, misalnya, bila handset dibawa bepergian di saku pengguna.
+</p>
+
+
+<img src="{@docRoot}images/android-7.0/doze-diagram-1.png" alt="" height="251px" id="figure1" />
+<p class="img-caption">
+  <strong>Gambar 1.</strong> Ilustrasi tentang cara Istirahatkan menerapkan pembatasan
+  aktivitas sistem level pertama untuk meningkatkan daya tahan baterai.
+</p>
+
+<p>
+  Bila perangkat sedang menggunakan daya baterai, dan layar telah nonaktif selama jangka waktu
+  tertentu, perangkat akan memasuki Istirahatkan dan menerapkan subset pembatasan pertama: Perangkat
+  akan menutup akses jaringan aplikasi, serta menangguhkan pekerjaan dan sinkronisasi. Jika perangkat sedang
+  diam selama jangka waktu tertentu setelah memasuki Istirahatkan, sistem akan menerapkan
+  pembatasan Istirahatkan selebihnya terhadap alarm {@link android.os.PowerManager.WakeLock},
+  {@link android.app.AlarmManager}, GPS, dan pemindaian Wi-Fi. Tidak peduli
+  apakah sebagian atau semua pembatasan Istirahatkan diterapkan, sistem akan membangunkan
+  perangkat selama jeda pemeliharaan singkat, dan selama itu aplikasi diizinkan
+  mengakses jaringan dan bisa mengeksekusi semua pekerjaan/sinkronisasi yang telah ditangguhkan.
+</p>
+
+
+<img src="{@docRoot}images/android-7.0/doze-diagram-2.png" alt="" id="figure2" />
+<p class="img-caption">
+  <strong>Gambar 2.</strong> Ilustrasi tentang cara Istirahatkan menerapkan pembatasan
+  aktivitas sistem level kedua setelah perangkat diam selama jangka waktu tertentu.
+</p>
+
+<p>
+  Perhatikan, mengaktifkan layar atau mencolokkan steker perangkat akan mengeluarkan dari Istirahatkan
+  dan membuang pembatasan pemrosesan ini. Perilaku tambahan ini tidak
+  memengaruhi rekomendasi dan praktik terbaik dalam menyesuaikan aplikasi Anda dengan versi
+  Istirahatkan sebelumnya yang diperkenalkan dalam Android 6.0 (API level 23), seperti yang dibahas di
+  <a href="{@docRoot}training/monitoring-device-state/doze-standby.html">
+  Mengoptimalkan untuk Istirahatkan dan Aplikasi Siaga</a>. Anda tetap harus
+   mengikuti rekomendasi itu, seperti menggunakan Google Cloud Messaging (GCM) untuk
+  mengirim dan menerima pesan, serta mulai merencanakan pembaruan
+  untuk mengakomodasi perilaku Istirahatkan tambahan.
+</p>
+
+
+<h3 id="bg-opt">Project Svelte: Optimalisasi Latar Belakang</h3>
+
+<p>
+  Android N membuang tiga siaran implisit untuk membantu mengoptimalkan
+  penggunaan memori dan konsumsi daya. Perubahan ini penting karena siaran
+  implisit sering memulai aplikasi yang telah didaftarkan untuk mendengarkannya di
+  latar belakang. Membuang siaran ini bisa sangat menguntungkan
+  kinerja perangkat dan pengalaman pengguna.
+</p>
+
+<p>
+  Perangkat seluler seringkali mengalami perubahan konektivitas, seperti saat berpindah
+  antara Wi-Fi dan data seluler. Saat ini, aplikasi bisa memantau perubahan dalam
+  konektivitas dengan mendaftarkan suatu penerima untuk siaran implisit {@link
+  android.net.ConnectivityManager#CONNECTIVITY_ACTION} dalam manifes
+  mereka. Karena banyak aplikasi yang didaftarkan untuk menerima siaran ini, switch  jaringan tunggal
+  bisa menyebabkan semuanya aktif dan memproses siaran tersebut
+  secara bersamaan.
+</p>
+
+<p>
+  Demikian pula, dalam Android versi sebelumnya, aplikasi bisa mendaftar untuk menerima siaran implisit {@link
+  android.hardware.Camera#ACTION_NEW_PICTURE} dan {@link
+  android.hardware.Camera#ACTION_NEW_VIDEO} dari aplikasi lain, seperti
+  Kamera. Bila pengguna mengambil gambar dengan aplikasi Kamera, semua aplikasi ini akan aktif
+  untuk memproses siaran.
+</p>
+
+<p>
+  Untuk meminimalkan masalah ini, Android N menerapkan optimalisasi
+  berikut:
+</p>
+
+<ul>
+  <li>Aplikasi yang menargetkan Android N tidak menerima siaran {@link
+  android.net.ConnectivityManager#CONNECTIVITY_ACTION}, sekalipun
+  memiliki entri manifes untuk meminta pemberitahuan mengenai kejadian ini. Aplikasi
+  yang berjalan tetap bisa mendengarkan {@code CONNECTIVITY_CHANGE} pada thread utama
+  jika mereka meminta pemberitahuan dengan {@link android.content.BroadcastReceiver}.
+  </li>
+
+  <li>Aplikasi tidak bisa mengirim atau menerima siaran {@link
+  android.hardware.Camera#ACTION_NEW_PICTURE} atau {@link
+  android.hardware.Camera#ACTION_NEW_VIDEO}. Optimalisasi ini
+  memengaruhi semua aplikasi, bukan hanya aplikasi yang menargetkan Android N.
+  </li>
+</ul>
+
+<p>Jika aplikasi Anda menggunakan intent ini, Anda harus membuang dependensi padanya
+  secepat mungkin agar Anda bisa menargetkan perangkat Android N dengan benar.
+  Kerangka kerja Android menyediakan beberapa solusi untuk mengurangi kebutuhan akan
+  siaran implisit ini. Misalnya, {@link
+  android.app.job.JobScheduler} API menyediakan mekanisme yang tangguh untuk menjadwalkan
+  operasi jaringan bila kondisi yang ditetapkan, seperti koneksi ke jaringan
+  berbiaya tetap, terpenuhi. Anda juga dapat menggunakan {@link
+  android.app.job.JobScheduler} untuk bereaksi terhadap perubahan pada penyedia materi.
+</p>
+
+<p>
+  Untuk informasi selengkapnya tentang optimalisasi latar belakang di N dan cara menyesuaikan aplikasi Anda,
+  lihat <a href="{@docRoot}preview/features/background-optimization.html">Optimalisasi
+  Latar Belakang</a>.
+</p>
+
+<h2 id="perm">Perubahan Izin</h2>
+
+<p>
+  Android N menyertakan perubahan pada izin yang bisa memengaruhi aplikasi Anda.
+</p>
+
+<h3 id="permfilesys">Perubahan izin sistem file</h3>
+
+<p>
+  Guna meningkatkan keamanan file privat, direktori privat
+  aplikasi yang menargetkan Android N atau yang lebih tinggi memiliki akses terbatas (<code>0700</code>).
+  Pengaturan ini mencegah kebocoran metadata dari file privat, seperti ukuran
+  atau eksistensi. Perubahan izin ini memiliki beberapa efek samping:
+</p>
+
+<ul>
+  <li>
+    Izin file privat tidak boleh dianggap remeh oleh pemilik,
+    dan usaha untuk melakukannya menggunakan
+    {@link android.content.Context#MODE_WORLD_READABLE} dan/atau
+    {@link android.content.Context#MODE_WORLD_WRITEABLE}, akan memicu sebuah
+    {@link java.lang.SecurityException}.
+    <p class="note">
+      <strong>Catatan:</strong> Seperti sebelumnya, pembatasan ini tidak sepenuhnya diterapkan.
+      Aplikasi mungkin masih memodifikasi izin ke direktori privat mereka menggunakan
+      API asal atau {@link java.io.File File} API. Akan tetapi, kami sangat
+      tidak menyarankan Anda meremehkan izin direktori privat.
+    </p>
+  </li>
+  <li>
+    Meneruskan URI <code>file://</code> di luar domain paket dapat meninggalkan
+    penerima dengan jalur yang tidak bisa di akses. Karena itu, upaya untuk meneruskan URI
+    <code>file://</code> akan memicu
+    <code>FileUriExposedException</code>. Cara yang disarankan adalah
+    materi file privat menggunakan {@link
+    android.support.v4.content.FileProvider}.
+  </li>
+  <li>
+    {@link android.app.DownloadManager} tidak bisa lagi berbagi
+    file yang tersimpan secara privat berdasarkan nama file. Aplikasi lawas dapat mengakibatkan
+    jalur yang tidak dapat diakses saat mengakses {@link
+    android.app.DownloadManager#COLUMN_LOCAL_FILENAME}. Aplikasi yang menargetkan
+    Android N atau yang lebih tinggi akan memicu {@link java.lang.SecurityException} saat
+    berupaya mengakses
+    {@link android.app.DownloadManager#COLUMN_LOCAL_FILENAME}.
+    Aplikasi lawas yang menyetel lokasi unduhan ke lokasi publik dengan
+    menggunakan
+    {@link
+    android.app.DownloadManager.Request#setDestinationInExternalFilesDir
+    DownloadManager.Request.setDestinationInExternalFilesDir()} atau
+    {@link
+    android.app.DownloadManager.Request#setDestinationInExternalPublicDir
+    DownloadManager.Request.setDestinationInExternalPublicDir()}
+    tetap bisa mengakses jalur tersebut di
+    {@link android.app.DownloadManager#COLUMN_LOCAL_FILENAME}, akan tetapi,
+     metode ini sangat tidak disarankan. Cara yang disarankan untuk mengakses file
+    yang diekspos oleh {@link android.app.DownloadManager} adalah menggunakan
+    {@link android.content.ContentResolver#openFileDescriptor
+    ContentResolver.openFileDescriptor()}.
+  </li>
+</ul>
+
+<h2 id="sharing-files">Berbagi File Antar Aplikasi</h2>
+
+<p>
+Untuk aplikasi yang menargetkan Android N, kerangka kerja Android menerapkan
+kebijakan {@link android.os.StrictMode} API yang melarang mengekspos URI {@code file://}
+di luar aplikasi Anda. Jika sebuah intent berisi URI file meninggalkan aplikasi Anda, aplikasi tersebut akan gagal
+dengan pengecualian {@code FileUriExposedException}.
+</p>
+
+<p>
+Untuk berbagi file antar aplikasi, Anda harus mengirim URI {@code content://}
+dan memberikan izin akses sementara pada URI. Cara termudah untuk memberikan izin ini adalah dengan
+menggunakan kelas {@link android.support.v4.content.FileProvider}. Untuk informasi selengkapnya
+mengenai izin dan berbagi file,
+lihat <a href="{@docRoot}training/secure-file-sharing/index.html">Berbagi File</a>.
+</p>
+
+<h2 id="accessibility">Peningkatan Aksesibilitas</h2>
+
+<p>
+  Android N menyertakan perubahan yang bertujuan meningkatkan kegunaan
+  platform untuk pengguna dengan penglihatan yang rendah atau lemah. Perubahan ini umumnya tidak
+  memerlukan perubahan kode dalam aplikasi Anda, akan tetapi Anda harus memeriksa
+  fitur ini dan mengujinya dengan aplikasi untuk menilai kemungkinan dampaknya terhadap pengalaman
+  pengguna.
+</p>
+
+
+<h3 id="screen-zoom">Perbesaran Layar</h3>
+
+<p>
+  Android N memungkinkan pengguna menyetel <strong>Display size</strong> yang akan memperbesar
+  atau memperkecil semua elemen pada layar, sehingga meningkatkan aksesibilitas perangkat
+  bagi pengguna yang kurang melihat. Pengguna tidak bisa memperbesar layar melewati lebar layar
+  minimum <a href="http://developer.android.com/guide/topics/resources/providing-resources.html">
+  sw320dp</a>, yang merupakan lebar Nexus 4, yakni ponsel ukuran sedang pada umumnya.
+</p>
+
+<div class="cols">
+
+<div class="col-6">
+  <img src="{@docRoot}images/android-7.0/screen-zoom-1.png" alt="" height="XXX" id="figure1" />
+</div>
+<div class="col-6">
+  <img src="{@docRoot}images/android-7.0/screen-zoom-2.png" alt="" height="XXX" id="figure1" />
+</div>
+
+</div> <!-- end cols -->
+<p class="img-caption">
+  <strong>Gambar 3.</strong> Layar di sebelah kanan menampilkan efek
+ penambahan Display size perangkat yang menjalankan citra sistem Android N.
+</p>
+
+
+<p>
+  Bila kepadatan perangkat berubah, sistem akan memberi tahu aplikasi yang sedang berjalan dengan
+  cara berikut:
+</p>
+
+<ul>
+  <li>Jika aplikasi menargetkan API level 23 atau yang lebih rendah, sistem secara otomatis akan mematikan
+  semua proses latar belakang. Artinya, jika pengguna beralih dari
+  aplikasi tersebut untuk membuka layar <em>Settings</em> dan mengubah
+  setelan <strong>Display size</strong>, maka sistem akan mematikan aplikasi tersebut dengan cara yang
+  sama dengan saat memori tinggal sedikit. Jika aplikasi memiliki beberapa proses
+  latar depan, sistem akan memberi tahu proses tersebut mengenai perubahan konfigurasi seperti
+ dijelaskan dalam <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Menangani Perubahan
+  Waktu Proses</a>, seolah-olah orientasi perangkat telah berubah.
+  </li>
+
+  <li>Jika sebuah aplikasi menargetkan Android N, semua prosesnya
+  (latar depan dan latar belakang) akan diberi tahu mengenai perubahan konfigurasi seperti
+  dijelaskan dalam <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Menangani Perubahan
+  Waktu Proses</a>.
+  </li>
+</ul>
+
+<p>
+  Sebagian besar aplikasi tidak perlu melakukan perubahan untuk mendukung fitur ini, asalkan
+  aplikasi tersebut mengikuti praktik terbaik Android. Hal-hal tertentu yang harus diperiksa:
+</p>
+
+<ul>
+  <li>Uji aplikasi Anda pada perangkat dengan lebar layar <code><a href=
+  "{@docRoot}guide/topics/resources/providing-resources.html">sw320dp</a></code>
+  dan pastikan aplikasi berjalan dengan semestinya.
+  </li>
+
+  <li>Bila konfigurasi perangkat berubah, perbarui informasi cache
+  yang bergantung pada kepadatan, seperti bitmap di cache atau sumber daya yang dimuat dari
+  jaringan. Periksa perubahan konfigurasi bila aplikasi melanjutkan dari status dihentikan
+  sementara.
+    <p class="note">
+      <strong>Catatan:</strong> Catatan: Jika Anda meng-cache data yang bergantung pada konfigurasi, ada
+      baiknya untuk menyertakan metadata yang relevan seperti ukuran layar
+      atau kepadatan piksel yang sesuai untuk data tersebut. Menyimpan metadata ini memungkinkan Anda untuk
+      memutuskan apakah Anda perlu segarkan data cache setelah perubahan
+      konfigurasi.
+    </p>
+  </li>
+
+  <li>Hindari menetapkan dimensi dengan satuan px, karena satuan ini tidak diskalakan dengan
+  kepadatan layar. Sebagai gantinya, tetapkan dimensi dengan satuan <a href="{@docRoot}guide/practices/screens_support.html">piksel yang tidak bergantung kepadatan
+  </a> (<code>dp</code>).
+  </li>
+</ul>
+
+<h3 id="vision-settings">Vision Settings di Setup Wizard</h3>
+
+<p>
+  Android N menyertakan Vision Settings di layar Sambutan, di mana pengguna bisa
+  menyiapkan setelan aksesibilitas berikut pada perangkat baru:
+  <strong>Magnification gesture</strong>, <strong>Font size</strong>,
+  <strong>Display size</strong> dan <strong>TalkBack</strong>. Perubahan ini
+  meningkatkan visibilitas bug terkait dengan setelan layar yang berbeda. Untuk
+  mengurangi dampak fitur ini, Anda harus menguji aplikasi dengan setelan ini
+  diaktifkan. Anda bisa menemukannya pada <strong>Settings &gt;
+  Accessibility</strong>.
+</p>
+
+<h2 id="ndk">Penautan Aplikasi NDK ke Pustaka Platform</h2>
+
+<p>
+  Android N menyertakan perubahan ruang nama untuk mencegah pemuatan API non-publik.
+  Jika menggunakan NDK, Anda hanya boleh menggunakan API publik dari platform
+  Android. Menggunakan API non-publik dalam rilis Android resmi berikutnya
+  bisa menyebabkan aplikasi mogok.
+</p>
+
+<p>
+  Untuk memberi tahu Anda agar menggunakan API non-publik, aplikasi yang berjalan pada perangkat
+  Android N akan menghasilkan kesalahan dalam keluaran logcat bila aplikasi memanggil API non-publik.
+  Kesalahan ini juga ditampilkan di layar perangkat berupa pesan untuk membantu
+  meningkatkan kepedulian terhadap situasi ini. Anda harus memeriksa kode aplikasi untuk
+  membuang penggunaan API platform non-publik dan secara saksama menguji aplikasi Anda menggunakan
+  perangkat pratinjau atau emulator.
+</p>
+
+<p>
+  Jika aplikasi Anda bergantung pada pustaka platform, lihat dokumentasi NDK untuk
+  perbaikan tipikal guna menggantikan API privat umum dengan padanan API publik.
+  Anda mungkin juga menautkan ke pustaka platform tanpa menyadarinya,
+  terutama jika aplikasi Anda menggunakan pustaka yang merupakan bagian dari platform ini (seperti
+  <code>libpng</code>), namun bukan bagian dari NDK. Dalam hal itu, pastikan
+  APK Anda berisi semua file .so yang ingin ditautkan.
+</p>
+
+<p class="caution">
+  <strong>Perhatian:</strong> Beberapa pustaka pihak ketiga mungkin menautkan ke API
+  non-publik. Jika menggunakan pustaka ini, aplikasi Anda bisa mogok saat dijalankan
+  pada rilis resmi Android berikutnya.
+</p>
+
+<p>
+  Aplikasi tidak boleh bergantung pada atau menggunakan pustaka bawaan yang tidak disertakan dalam
+  NDK, karena bisa mengalami perubahan, atau dipindahkan dari satu rilis Android ke
+  rilis lainnya. Peralihan dari OpenSSL ke BoringSSL merupakan satu contoh dari perubahan semacam ini.
+  Selain itu, perangkat yang berbeda bisa menawarkan tingkat kompatibilitas yang berbeda, karena
+   tidak ada persyaratan kompatibilitas untuk pustaka platform yang tidak disertakan
+  dalam NDK. Jika Anda harus mengakses pustaka non-NDK pada perangkat yang lebih lama, jadikan
+  pemuatan bergantung pada level Android API.
+</p>
+
+<p>
+  Untuk membantu Anda mendiagnosis tipe masalah ini ada beberapa contoh kesalahan Java dan NDK
+  yang mungkin Anda temui saat berusaha membangun aplikasi dengan Android N:
+</p>
+
+<p>Contoh kesalahan Java:</p>
+<pre class="no-pretty-print">
+java.lang.UnsatisfiedLinkError: dlopen failed: library "/system/lib/libcutils.so"
+    is not accessible for the namespace "classloader-namespace"
+</pre>
+
+<p>Contoh kesalahan NDK:</p>
+<pre class="no-pretty-print">
+dlopen failed: cannot locate symbol "__system_property_get" referenced by ...
+</pre>
+
+
+<p>
+  Inilah beberapa perbaikan tipikal untuk aplikasi yang mengalami tipe kesalahan ini:
+</p>
+
+<ul>
+  <li>Penggunaan getJavaVM dan getJNIEnv dari libandroid_runtime.so bisa diganti
+  dengan fungsi JNI standar:
+<pre class="no-pretty-print">
+AndroidRuntime::getJavaVM -&gt; GetJavaVM from &lt;jni.h&gt;
+AndroidRuntime::getJNIEnv -&gt; JavaVM::GetEnv or
+JavaVM::AttachCurrentThread from &lt;jni.h&gt;.
+</pre>
+  </li>
+
+  <li>Penggunaan simbol {@code property_get} dari {@code libcutils.so} bisa
+    diganti dengan {@code alternative __system_property_get} publik.
+   Caranya, gunakan {@code __system_property_get} dengan menyertakan yang berikut:
+<pre>
+#include &lt;sys/system_properties.h&gt;
+</pre>
+  </li>
+
+  <li>Penggunaan simbol {@code SSL_ctrl} dari {@code libcrypto.so} harus
+    diganti dengan aplikasi versi lokal. Misalnya, Anda harus menautkan
+  {@code libcyrpto.a} secara statis dalam file {@code .so} atau menyertakan
+  {@code libcrypto.so} Anda sendiri secara dinamis dari BoringSSL atau OpenSSL dalam aplikasi Anda.
+  </li>
+</ul>
+
+<h2 id="afw">Android for Work</h2>
+<p>
+  Android N berisi perubahan untuk aplikasi yang menargetkan Android for Work, termasuk
+  perubahan pada pemasangan sertifikat, penyetelan ulang sandi, manajemen pengguna
+  tambahan, dan akses ke identifier perangkat. Jika Anda membangun aplikasi untuk
+  lingkungan Android for Work, Anda harus meninjau perubahan ini dan memodifikasi
+  aplikasi sebagaimana mestinya.
+</p>
+
+<ul>
+  <li>Anda harus pasang pemasang sertifikat yang didelegasikan sebelum DPC bisa
+  menyetelnya. Untuk aplikasi profil dan aplikasi pemilik perangkat yang menargetkan N SDK, Anda harus
+  pasang pemasang sertifikat yang didelegasikan sebelum pengontrol kebijakan
+  perangkat (DPC) memanggil
+  <code>DevicePolicyManager.setCertInstallerPackage()</code>. Jika pemasang
+  belum dipasang, sistem akan melontarkan
+  <code>IllegalArgumentException</code>.
+  </li>
+
+  <li>Pembatasan sandi penyetelan ulang untuk admin perangkat sekarang diterapkan ke pemilik
+  profil. Admin perangkat tidak bisa lagi menggunakan
+  {@code DevicePolicyManager.resetPassword()} untuk menghapus sandi atau mengubah
+  sandi yang sudah disetel. Admin perangkat tetap bisa menyetel sandi, namun hanya
+  bila perangkat belum memiliki sandi, PIN, atau pola.
+  </li>
+
+  <li>Pemilik perangkat dan profil bisa mengelola akun meskipun pembatasan
+  telah disetel. Pemilik perangkat dan pemilik profil bisa memanggil Account Management API
+  sekalipun pembatasan pengguna <code>DISALLOW_MODIFY_ACCOUNTS</code> diberlakukan.
+  </li>
+
+  <li>Pemilik perangkat bisa mengelola pengguna tambahan lebih mudah. Bila perangkat
+  berjalan dalam mode pemilik perangkat, maka pembatasan <code>DISALLOW_ADD_USER</code>
+  secara otomatis akan ditetapkan. Ini mencegah pengguna membuat pengguna tambahan yang
+  tidak terkelola. Selain itu, <code>CreateUser()</code> dan
+  <code>createAndInitializeUser()</code> metode tidak digunakan lagi; metode
+  <code>DevicePolicyManager.createAndManageUser()</code> telah menggantikannya.
+  </li>
+
+  <li>Pemilik perangkat bisa mengakses identifier perangkat. Pemilik perangkat bisa mengakses
+  alamat MAC Wi-Fi dari perangkat, menggunakan
+  <code>DevicePolicyManagewr.getWifiMacAddress()</code>. Jika Wi-Fi belum pernah
+  diaktifkan pada perangkat tersebut, metode ini akan mengembalikan nilai {@code null}.
+  </li>
+
+  <li>Setelan Mode Kerja mengontrol akses ke aplikasi kerja. Bila mode kerja tidak aktif, peluncur sistem
+  akan menunjukkan aplikasi kerja tidak tersedia dengan membuat warnanya jadi abu-abu. Mengaktifkan kembali
+ mode kerja akan memulihkan perilaku normal.
+</ul>
+
+<p>
+  Untuk informasi selengkapnya tentang perubahan Android for Work di Android N, lihat
+  <a href="{@docRoot}preview/features/afw.html">Pembaruan Android for Work</a>.
+</p>
+
+<h2 id="annotations">Retensi Anotasi</h2>
+
+<p>
+Android N memperbaiki bug dengan visibilitas anotasi diabaikan.
+Masalah ini mengaktifkan waktu proses untuk mengakses anotasi yang seharusnya tidak bisa
+dilakukan. Anotasi ini termasuk:
+</p>
+
+<ul>
+   <li>{@code VISIBILITY_BUILD}: Dimaksudkan agar hanya bisa terlihat pada waktu pembuatan.</li>
+   <li>{@code VISIBILITY_SYSTEM}: Dimaksud agar bisa terlihat pada waktu proses, namun hanya pada
+ sistem yang mendasarinya.</li>
+</ul>
+
+<p>
+Jika aplikasi Anda mengandalkan perilaku ini, tambahkan kebijakan retensi untuk anotasi yang harus
+tersedia di waktu proses. Caranya dengan menggunakan {@code @Retention(RetentionPolicy.RUNTIME)}.
+</p>
+
+<h2 id="other">Poin Penting Lainnya</h2>
+
+<ul>
+<li>Bila aplikasi berjalan pada Android N, namun menargetkan level API yang lebih rendah,
+dan pengguna mengubah ukuran tampilan, proses aplikasi akan dimatikan. Aplikasi
+harus dapat menangani skenario ini dengan lancar. Jika tidak, maka akan mogok
+bila pengguna memulihkannya dari Recents.
+
+<p>
+Anda harus menguji aplikasi untuk memastikan
+perilaku ini tidak terjadi.
+Anda bisa melakukannya dengan menyebabkan suatu mogok yang identik
+saat mematikan aplikasi secara manual melalui DDMS.
+</p>
+
+<p>
+Aplikasi yang menargetkan N dan yang di atasnya tidak secara otomatis dimatikan saat perubahan kepadatan;
+akan tetapi, aplikasi tersebut mungkin tetap merespons perubahan konfigurasi dengan buruk.
+</p>
+</li>
+
+<li>
+Aplikasi pada Android N harus mampu menangani perubahan konfigurasi dengan lancar,
+dan tidak boleh mengalami mogok pada start selanjutnya. Anda bisa memverifikasi perilaku aplikasi
+dengan mengubah ukuran font (<strong>Setting</strong> &gt;
+<strong>Display</strong> &gt; <strong>Font size</strong>), kemudian memulihkan
+aplikasi dari Recents.
+</li>
+
+<li>
+Dikarenakan adanya bug di versi Android sebelumnya, sistem tidak menandai penulisan
+  ke soket TCP di thread utama sebagai pelanggaran mode-ketat. Android N memperbaiki bug ini.
+Aplikasi yang menunjukkan perilaku ini kini melontarkan sebuah {@code android.os.NetworkOnMainThreadException}.
+Secara umum, melakukan operasi jaringan di thread utama tidak baik karena operasi ini
+biasanya memiliki latensi tinggi yang menyebabkan ANR dan jank.
+</li>
+
+<li>
+Kelompok metode {@code Debug.startMethodTracing()} kini default ke
+keluaran penyimpanan di direktori paket tertentu di penyimpanan bersama,
+sebagai ganti di level teratas
+kartu SD.  Berarti aplikasi tidak perlu lagi meminta izin {@code WRITE_EXTERNAL_STORAGE} untuk menggunakan API ini.
+</li>
+
+<li>
+Banyak platform API yang kini mulai memeriksa beban besar yang dikirim
+ke seluruh transaksi {@link android.os.Binder}, dan sistem
+kini melontarkan kembali {@code TransactionTooLargeExceptions}
+sebagai {@code RuntimeExceptions}, sebagai ganti logging secara diam-diam atau menyembunyikannya.  Satu contoh
+umum adalah menyimpan terlalu banyak data di
+{@link android.app.Activity#onSaveInstanceState Activity.onSaveInstanceState()},
+yang menyebabkan {@code ActivityThread.StopInfo} melontarkan
+{@code RuntimeException} bila aplikasi Anda menargetkan Android N.
+</li>
+
+<li>
+Jika sebuah aplikasi mengeposkan tugas {@link java.lang.Runnable} ke{@link android.view.View}, dan
+{@link android.view.View}
+tidak terpasang ke jendela, sistem
+akan mengantrekan tugas {@link java.lang.Runnable} dengan {@link android.view.View};
+tugas {@link java.lang.Runnable} tidak akan dieksekusi hingga
+{@link android.view.View} terpasang
+ke jendela. Perilaku ini mengatasi bug berikut:
+<ul>
+   <li>Jika sebuah aplikasi mengeposkan ke {@link android.view.View} dari thread selain thread UI jendela yang dimaksud,
+    maka {@link java.lang.Runnable} mungkin akan menjalankan thread yang salah.
+   </li>
+   <li>Jika tugas {@link java.lang.Runnable} diposkan dari thread selain
+   looper-thread, aplikasi bisa mengekspos tugas {@link java.lang.Runnable}.</li>
+</ul>
+</li>
+
+<li>
+Jika sebuah aplikasi di Android N dengan
+izin{@link android.Manifest.permission#DELETE_PACKAGES DELETE_PACKAGES}
+mencoba menghapus sebuah paket, namun sebuah aplikasi berbeda telah memasang paket itu,
+sistem akan memerlukan konfirmasi pengguna. Dalam skenario ini, aplikasi harus mengharapkan
+{@link android.content.pm.PackageInstaller#STATUS_PENDING_USER_ACTION STATUS_PENDING_USER_ACTION}
+sebagai status kembalian bila memanggil
+{@link android.content.pm.PackageInstaller#uninstall PackageInstaller.uninstall()}.
+</li>
+
+</ul>
+
diff --git a/docs/html-intl/intl/id/about/versions/nougat/android-7.0-samples.jd b/docs/html-intl/intl/id/about/versions/nougat/android-7.0-samples.jd
new file mode 100644
index 0000000..d31c0c0
--- /dev/null
+++ b/docs/html-intl/intl/id/about/versions/nougat/android-7.0-samples.jd
@@ -0,0 +1,85 @@
+page.title=Contoh
+page.tags="preview", "samples", "android"
+page.image=images/cards/card-n-samples_2x.png
+@jd:body
+
+<p>
+  Contoh kode berikut disediakan untuk Android N. Untuk
+  mengunduh contoh di Android Studio, pilih opsi menu <b>File &gt; Import
+  Samples</b>.
+</p>
+
+<p class="note">
+  <strong>Catatan:</strong> Proyek yang bisa diunduh ini didesain
+   untuk digunakan bersama Gradle dan Android Studio.
+</p>
+
+
+<h3 id="mw">Playground Multi-Jendela</h3>
+<img src="{@docRoot}images/android-7.0/sample-multiwindow.png" style="float: left; padding-right: 0.5em" height="250" width="156" />
+<p>
+  Contoh ini memperagakan cara memanfaatkan antarmuka pengguna
+  multi-jendela bersama aplikasi Anda.
+</p>
+<p>
+  <a href="https://github.com/googlesamples/android-MultiWindowPlayground">
+  Dapatkan di GitHub</a>
+</p>
+
+<div style="clear: both;"></div>
+<h3 id="an">Pemberitahuan Aktif</h3>
+<img src="{@docRoot}images/android-7.0/sample-activenotifications.png" style="float: left; padding-right: 0.5em" height="250" width="141" />
+<p>
+  Ini adalah contoh yang sudah ada sebelumnya, menampilkan layanan sederhana yang mengirimkan
+   pemberitahuan menggunakan NotificationCompat. Setiap percakapan yang belum dibaca dari pengguna
+  dikirimkan sebagai pemberitahuan berbeda.
+</p>
+<p>
+  Contoh ini telah diperbarui untuk memanfaatkan fitur pemberitahuan baru
+  yang tersedia di Android N.
+</p>
+<p>
+  <a href="https://github.com/googlesamples/android-ActiveNotifications">
+  Dapatkan di GitHub</a>
+</p>
+
+<div style="clear: both;"></div>
+<h3 id="ms">Layanan Perpesanan</h3>
+<img src="{@docRoot}images/android-7.0/sample-messagingservice.png" style="float: left; padding-right: 0.5em" height="250" width="150" />
+<p>
+  Ini adalah contoh yang telah ada sebelumnya yang memperagakan cara menggunakan
+  NotificationManager untuk memberi tahu jumlah pemberitahuan yang saat ini ditampilkan
+  oleh aplikasi.
+</p>
+<p>
+  Contoh ini telah diperbarui untuk memanfaatkan fitur pemberitahuan baru
+  yang tersedia di Android N.
+</p>
+<p>
+  <a href="https://github.com/googlesamples/android-MessagingService">
+  Dapatkan di GitHub</a>
+</p>
+
+<div style="clear: both;"></div>
+<h3 id="fbe">Direct Boot</h3>
+<img src="{@docRoot}images/android-7.0/sample-directboot.png" style="float: left; padding-right: 0.5em" height="250" width="141" />
+<p>
+  Contoh ini memperagakan cara menyimpan dan mengakses data dalam penyimpanan yang dienkripsi
+  dengan perangkat yang selalu tersedia saat perangkat booting.
+</p>
+<p>
+  <a href="https://github.com/googlesamples/android-DirectBoot">
+  Dapatkan di GitHub</a>
+</p>
+
+<div style="clear: both;"></div>
+<h3 id="sda">Scoped Directory Access</h3>
+<img src="{@docRoot}images/android-7.0/sample-scopeddirectoryaccess.png" style="float: left; padding-right: 0.5em" height="250" width="141" />
+<p>
+  Contoh ini memperagakan cara membaca dan menulis data dari direktori
+  spesifik, sekaligus meminta izin lebih sedikit.
+</p>
+<p>
+  <a href="https://github.com/googlesamples/android-ScopedDirectoryAccess">
+  Dapatkan di GitHub</a>
+</p>
diff --git a/docs/html-intl/intl/id/about/versions/nougat/android-7.0.jd b/docs/html-intl/intl/id/about/versions/nougat/android-7.0.jd
new file mode 100644
index 0000000..ff8af12
--- /dev/null
+++ b/docs/html-intl/intl/id/about/versions/nougat/android-7.0.jd
@@ -0,0 +1,1039 @@
+page.title=Android N for Developers
+meta.tags="preview", "androidn"
+page.tags="preview", "developer preview"
+page.image=images/cards/card-n-apis_2x.png
+@jd:body
+
+
+
+
+<div id="tb-wrapper">
+<div id="tb">
+  <h2>Fitur-fitur Utama bagi Pengembang</h2>
+  <ol>
+      <ul style="list-style-type:none;">
+        <li><a href="#multi-window_support">Dukungan Multi-Jendela</a></li>
+        <li><a href="#notification_enhancements">Pemberitahuan</a></li>
+        <li><a href="#jit_aot">Kompilasi JIT/AOT</a></li>
+        <li><a href="#quick_path_to_app_install">Jalur Cepat untuk Pasang Aplikasi</a></li>
+        <li><a href="#doze_on_the_go">Istirahatkan Kapan Saja</a></li>
+        <li><a href="#background_optimizations">Optimalisasi Latar Belakang</a></li>
+        <li><a href="#data_saver">Data Saver</a></li>
+        <li><a href="#vulkan">Vulkan API</a></li>
+        <li><a href="#tile_api">Quick Settings Tile API</a></li>
+        <li><a href="#number-blocking">Pemblokiran Nomor</a></li>
+        <li><a href="#call_screening">Penyaringan Panggilan</a></li>
+        <li><a href="#multi-locale_languages">Lokal dan Bahasa</a></li>
+        <li><a href="#emoji">Emoji Baru</a></li>
+        <li><a href="#icu4">ICU4J API di Android</a></li>
+        <li><a href="#gles_32">OpenGL ES 3.2 API</a></li>
+        <li><a href="#android_tv_recording">Perekaman Android TV</a></li>
+        <li><a href="#android_for_work">Android for Work</a></li>
+        <li><a href="#accessibility_enhancements">Aksesibilitas</a></li>
+        <li><a href="#direct_boot">Direct Boot</a></li>
+        <li><a href="#key_attestation">Key Attestation</a></li>
+        <li><a href="#network_security_config">Network Security Config</a></li>
+        <li><a href="#default_trusted_ca">CA Tepercaya Default</a></li>
+        <li><a href="#apk_signature_v2">APK Signature Scheme V2</a></li>
+        <li><a href="#scoped_directory_access">Scoped Directory Access</a></li>
+        <li><a href="#keyboard_shortcuts_helper">Keyboard Shortcuts Helper</a></li>
+        <li><a href="#sustained_performance_api">Sustained Performance API</a></li>
+        <li><a href="#vr">Dukungan VR</a></li>
+        <li><a href="#print_svc">Penyempurnaan Layanan Cetak</a></li>
+        <li><a href="#virtual_files">File Maya</a></li>
+        <li><a href="#framemetrics_api">FrameMetricsListener API</a></li>
+      </ol>
+</div>
+</div>
+
+
+
+<p>Android N masih dalam pengembangan aktif, namun Anda bisa mencobanya
+sekarang sebagai bagian dari N Developer Preview. Bagian-bagian di bawah ini akan menyoroti sebagian dari
+fitur baru untuk pengembang. </p>
+
+<p>
+  Pastikan memeriksa <a href="{@docRoot}preview/behavior-changes.html">Perubahan Perilaku</a> untuk mengetahui selengkapnya tentang
+  bagian-bagian perubahan platform yang bisa memengaruhi aplikasi Anda, lihatlah
+  panduan pengembang untuk mengetahui selengkapnya tentang fitur-fitur utama, dan unduh <a href="{@docRoot}preview/setup-sdk.html#docs-dl">Referensi API</a> untuk mengetahui detail tentang
+  API baru.
+</p>
+
+<h2 id="multi-window_support">Dukungan Multi-Jendela</h2>
+
+
+<p>Di Android N, kami memperkenalkan fitur multitasking baru dan yang banyak diminta
+ke dalam platform &mdash; dukungan multi-jendela. </p>
+
+  <p>Pengguna sekarang bisa membuka dua aplikasi sekaligus di layar. </p>
+  <ul>
+  <li>Pada ponsel dan tablet
+yang menjalankan Android N, pengguna bisa menjalankan dua aplikasi secara berdampingan atau
+satu aplikasi di atas yang lain dalam mode layar terbagi. Pengguna bisa mengubah ukuran aplikasi dengan menyeret
+pembagi di antara keduanya. </li>
+
+<li>Pada perangkat Android TV, aplikasi bisa menempatkan dirinya sendiri dalam <a href="{@docRoot}preview/features/picture-in-picture.html">mode
+gambar-dalam-gambar</a>, sehingga aplikasi bisa terus menampilkan materi sementara pengguna menjelajahi atau
+berinteraksi dengan aplikasi lain.</li>
+  </ul>
+
+<div class="col-4of10">
+<img src="{@docRoot}images/android-7.0/mw-portrait.png" alt="" style="height:460px;padding-left:1em;" id="img-split-screen" />
+<p class="img-caption">
+  <strong>Gambar 1.</strong> Aplikasi yang berjalan dalam mode layar terbagi.
+</p>
+
+  </div>
+
+<p>Khususnya pada tablet dan perangkat yang berlayar lebih besar lainnya, dukungan multi-jendela
+memberi Anda cara baru untuk memikat pengguna. Anda bahkan bisa mengaktifkan fitur seret-dan-lepas di
+aplikasi untuk memudahkan pengguna menyeret materi ke dan dari aplikasi &mdash; cara bagus
+untuk menyempurnakan pengalaman pengguna Anda. </p>
+
+<p>Tidak sulit menambahkan dukungan multi-jendela ke aplikasi Anda dan mengonfigurasi cara
+menangani tampilan multi-jendela. Misalnya, Anda bisa menetapkan dimensi
+minimum yang diizinkan aktivitas, sehingga mencegah pengguna mengubah ukuran aktivitas di bawah
+ukuran itu. Anda juga bisa menonaktifkan tampilan multi-jendela untuk aplikasi Anda, yang
+  akan memastikan sistem hanya menampilkan aplikasi dalam mode layar penuh.</p>
+
+<p>
+  Untuk informasi selengkapnya, lihat dokumentasi pengembang <a href="{@docRoot}preview/features/multi-window.html">Dukungan Multi-Jendela</a>.
+
+</p>
+
+<h2 id="notification_enhancements">Penyempurnaan Pemberitahuan</h2>
+
+<p>Di Android N kami telah mengubah desain pemberitahuan agar lebih mudah dan lebih cepat
+digunakan. Beberapa perubahan tersebut antara lain:</p>
+
+<ul>
+  <li>
+    <strong>Pembaruan template</strong>: Kami telah memperbarui template pemberitahuan untuk
+    lebih menekankan citra pahlawan dan avatar. Pengembang akan dapat
+   memanfaatkan template baru dengan penyesuaian kode yang minimal.
+  </li>
+
+  <li>
+    <strong>Penyesuaian gaya pesan</strong>: Anda bisa menyesuaikan lebih banyak
+    label antarmuka pengguna yang berkaitan dengan pemberitahuan Anda menggunakan kelas
+    <code>MessageStyle</code>. Anda bisa mengonfigurasi pesan, judul percakapan,
+    dan tampilan materi.
+  </li>
+
+  <li>
+    <strong>Bundel pemberitahuan</strong>: Sistem bisa mengelompokkan pesan,
+    misalnya menurut topik pesan, dan menampilkan kelompok pesan tersebut. Seorang pengguna bisa
+   bertindak, misalnya Tutup atau Arsipkan, atas pesan yang ditampilkan. Jika Anda sudah
+    mengimplementasikan pemberitahuan untuk Android Wear, Anda akan terbiasa dengan
+    model ini.
+  </li>
+
+  <li>
+    <strong>Balasan Langsung</strong>: Untuk aplikasi komunikasi real-time, sistem
+    Android mendukung balasan inline sehingga pengguna bisa dengan cepat membalas
+    SMS atau pesan teks secara langsung dari dalam antarmuka pemberitahuan.
+  </li>
+
+  <li>
+    <strong>Tampilan khusus</strong>: Dua API baru memungkinkan Anda memanfaatkan dekorasi sistem,
+    misalnya header pemberitahuan dan tindakan, saat menggunakan tampilan
+    khusus dalam pemberitahuan.
+  </li>
+</ul>
+
+<div class="col-4of12">
+  <img src="{@docRoot}images/android-7.0/notifications-1.png" alt="" style="padding:.5em;max-width:226px">
+</div>
+
+<div class="col-4of12">
+  <img src="{@docRoot}images/android-7.0/notifications-3.png" alt="" style="padding:.5em;max-width:226px">
+</div>
+
+<div class="col-4of12">
+  <img src="{@docRoot}images/android-7.0/notifications-2.png" alt="" style="padding:.5em;max-width:226px">
+</div>
+
+
+<p class="img-caption">
+  <strong>Gambar 2.</strong> Bundel pemberitahuan dan balasan langsung.
+</p>
+
+<p>Untuk mengetahui cara mengimplementasikan fitur-fitur
+  baru ini, lihat panduan <a href="{@docRoot}preview/features/notification-updates.html">Pemberitahuan</a>.
+</p>
+
+
+
+<h2 id="jit_aot">Kompilasi JIT/AOT yang dipandu profil</h2>
+
+<p>Di Android N, kami telah menambahkan compiler Just in Time (JIT) dengan pembuatan profil kode ke
+ART, yang memungkinkannya terus meningkatkan kinerja aplikasi Android saat
+dijalankan. Compiler JIT melengkapi compiler Ahead of Time (AOT) pada ART
+dan membantu memperbaiki kinerja waktu proses, menghemat ruang penyimpanan, dan mempercepat
+pembaruan aplikasi serta pembaruan sistem.</p>
+
+<p>Kompilasi yang dipandu profil memungkinkan ART mengelola kompilasi AOT/JIT untuk setiap aplikasi
+sesuai dengan penggunaan sebenarnya, serta kondisi pada perangkat. Misalnya
+,ART menyimpan profil setiap metode terbaik aplikasi dan bisa melakukan kompilasi lebih awal
+serta menyimpan sementara metode-metode tersebut di cache untuk mendapatkan kinerja terbaik. Hal ini membuat bagian lain dari aplikasi
+dibiarkan tidak dikompilasi hingga benar-benar digunakan.</p>
+
+<p>Di samping meningkatkan kinerja bagian-bagian penting aplikasi, kompilasi yang dipandu profil
+membantu mengurangi footprint RAM keseluruhan aplikasi, termasuk biner
+terkait. Fitur ini terutama penting pada perangkat dengan memori minim.</p>
+
+<p>ART mengelola kompilasi yang dipandu profil dengan cara yang meminimalkan dampak terhadap
+baterai perangkat. ART melakukan prakompilasi hanya bila perangkat sedang diam dan
+mengisi daya, sehingga menghemat waktu dan baterai dengan melakukan pekerjaan tersebut di awal.</p>
+
+<h2 id="quick_path_to_app_install">Jalur Cepat untuk Pasang Aplikasi</h2>
+
+<p>Salah satu manfaat paling nyata dari compiler JIT pada ART adalah kecepatan
+pemasnagan aplikasi dan pembaruan sistem. Bahkan aplikasi besar yang membutuhkan beberapa menit untuk
+dioptimalkan dan dipasang di Android 6.0 sekarang bisa dipasang hanya dalam hitungan
+detik. Pembaruan sistem juga lebih cepat, karena tidak ada lagi langkah optimalisasi. </p>
+
+<h2 id="doze_on_the_go">Istirahatkan Kapan Saja...</h2>
+
+<p>Android 6.0 memperkenalkan Istirahatkan, yaitu mode sistem yang menghemat baterai dengan menangguhkan
+aktivitas CPU dan jaringan di aplikasi bila perangkat sedang diam, misalnya saat
+diletakkan di atas meja atau dalam laci. </p>
+
+<p>Sekarang di Android N, Istirahatkan selangkah lebih maju dalam menghemat baterai kapan saja.
+Setiap kali layar mati dalam jangka waktu tertentu dan perangkat tidak terhubung ke sumber daya,
+Istirahatkan akan menerapkan subset pembatasan umum CPU dan jaringan pada aplikasi.
+Artinya pengguna bisa menghemat daya baterai meskipun perangkat dibawa di dalam
+tasnya.</p>
+
+
+<img src="/preview/images/doze-diagram-1.png" alt="" id="figure1" />
+<p class="img-caption">
+  <strong>Gambar 3.</strong> Istirahatkan sekarang menerapkan
+  pembatasan untuk meningkatkan daya tahan baterai bahkan saat perangkat sedang tidak diam.
+</p>
+
+
+<p>Tidak lama setelah layar dimatikan saat perangkat menggunakan daya baterai, Istirahatkan
+akan membatasi akses jaringan serta menangguhkan pekerjaan dan sinkronisasi. Selama jeda
+pemeliharaan, aplikasi diizinkan mengakses jaringan dan menjalankan semua
+pekerjaan/sinkronisasi yang ditangguhkan. Menyalakan layar atau mencolokkan perangkat akan mengeluarkan
+perangkat dari Istirahatkan.</p>
+
+<p>Bila perangkat dalam kondisi diam lagi, dengan layar mati dan menggunakan daya baterai selama
+jangka waktu tertentu, Istirahatkan akan menerapkan pembatasan CPU dan jaringan pada {@link
+android.os.PowerManager.WakeLock}, alarm {@link android.app.AlarmManager}, dan
+pemindaian GPS/Wi-Fi.</p>
+
+<p>Praktik terbaik untuk menyesuaikan aplikasi Anda dengan Istirahatkan adalah sama, baik
+perangkat sedang bergerak maupun diam, jadi jika Anda sudah memperbarui aplikasi untuk
+menjalankan Istirahatkan dengan lancar, berarti Anda sudah siap. Jika belum, mulailah <a href="{@docRoot}training/monitoring-device-state/doze-standby.html#assessing_your_app">menyesuaikan
+aplikasi Anda dengan Istirahatkan</a> sekarang juga.</p>
+
+<h2 id="background_optimizations">Project Svelte: Optimalisasi Latar Belakang</h2>
+
+<p>Project Svelte merupakan upaya berkelanjutan untuk meminimalkan penggunaan RAM oleh sistem dan aplikasi
+di semua jenis perangkat Android dalam ekosistem. Di Android N, Project
+Svelte berfokus pada optimalisasi cara aplikasi berjalan di latar belakang. </p>
+
+<p>Proses latar belakang merupakan bagian terpenting dari sebagian besar aplikasi. Bila ditangani dengan benar, proses
+ini bisa memberikan pengalaman pengguna yang mengagumkan &mdash; segera, cepat, dan sesuai konteks.
+Bila tidak ditangani dengan benar, proses latar belakang bisa menguras RAM (dan
+baterai) yang sebenarnya tidak perlu serta memengaruhi kinerja sistem untuk aplikasi lain. </p>
+
+<p>Sejak Android 5.0, {@link android.app.job.JobScheduler} telah menjadi
+cara yang disukai untuk melakukan pekerjaan latar belakang dengan cara yang baik
+bagi pengguna. Aplikasi bisa menjadwalkan pekerjaan sekaligus memungkinkan sistem mengoptimalkan berdasarkan
+kondisi memori, daya, dan konektivitas. JobScheduler menawarkan kontrol serta
+kemudahan, dan kami ingin semua aplikasi menggunakannya. </p>
+
+<p>
+  Opsi baik lainnya adalah <a href="https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
+  <code>GCMNetworkManager</code></a>, bagian dari Google Play Services, yang
+  menawarkan penjadwalan pekerjaan serupa dengan kompatibilitas pada semua versi lawas
+  Android.
+</p>
+
+<p>Kami terus memperluas <code>JobScheduler</code> dan
+<code>GCMNetworkManager</code> untuk memenuhi lebih banyak
+kasus penggunaan Anda &mdash; misalnya, di Android N Anda sekarang bisa menjadwalkan pekerjaan
+latar belakang berdasarkan perubahan di Content Providers. Pada saat yang sama kami mulai
+menghilangkan beberapa pola lama yang bisa mengurangi kinerja sistem,
+terutama pada perangkat yang minim memori.</p>
+
+<p>Di Android N kami membuang tiga siaran implisit yang umum digunakan &mdash;
+ {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION}, {@link
+  android.hardware.Camera#ACTION_NEW_PICTURE}, dan {@link
+  android.hardware.Camera#ACTION_NEW_VIDEO} &mdash; karena ketiganya bisa mengaktifkan
+proses latar belakang pada beberapa aplikasi sekaligus serta menguras memori dan baterai. Jika
+aplikasi Anda menerimanya, manfaatkan N Developer Preview untuk
+  beralih ke <code>JobScheduler</code> dan API terkait sebagai gantinya. </p>
+
+<p>
+  Lihat dokumentasi <a href="{@docRoot}preview/features/background-optimization.html">Optimalisasi
+  Latar Belakang</a> untuk mengetahui detailnya.
+</p>
+
+
+<h2 id="data_saver">Data Saver</h2>
+
+<div class="col-5of12" style="margin-right:1.5em;">
+<img src="{@docRoot}images/android-7.0/datasaver.png" style="border:2px solid #ddd">
+
+<p class="img-caption" style="padding-right:2em;">
+  <strong>Gambar 4.</strong> Data Saver di Settings.
+</p>
+  </div>
+
+<p>Selama penggunaan perangkat seluler, biaya paket data seluler biasanya
+  melebihi harga perangkat itu sendiri. Bagi banyak pengguna, data seluler adalah sumber daya
+mahal yang ingin mereka hemat. </p>
+
+<p>Android N memperkenalkan mode Data Saver, layanan sistem baru yang mengurangi
+penggunaan data seluler oleh aplikasi, baik saat roaming, mendekati akhir siklus tagihan,
+atau saat menggunakan paket data prabayar yang kecil. Data Saver memberi pengguna kemampuan mengontrol cara aplikasi
+menggunakan data seluler dan memungkinkan pengembang memberikan layanan yang lebih efisien bila Data
+Saver aktif. </p>
+
+<p>Bila pengguna mengaktifkan Data Saver di <strong>Settings</strong> dan perangkat
+dalam jaringan berkuota, sistem akan memblokir penggunaan data latar belakang dan memberi tahu aplikasi
+untuk menghemat penggunaan data latar depan &mdash; misalnya dengan membatasi
+kecepatan bit untuk streaming, mengurangi kualitas gambar, menangguhkan precaching optimistik,
+dan seterusnya. Pengguna bisa memasukkan aplikasi tertentu ke daftar putih untuk memungkinkan penggunaan data berkuota
+bila Data Saver diaktifkan.</p>
+
+<p>Android N memperluas {@link android.net.ConnectivityManager} untuk menyediakan cara pada aplikasi
+untuk <a href="{@docRoot}preview/features/data-saver.html#status">mengambil
+preferensi Data Saver pengguna</a> dan <a href="{@docRoot}preview/features/data-saver.html#monitor-changes">memantau
+perubahan preferensi</a>. Semua aplikasi harus memeriksa apakah pengguna telah mengaktifkan Data
+Saver dan berusaha membatasi penggunaan data latar belakang dan latar depan.</p>
+
+
+<h2 id="vulkan">Vulkan API</h2>
+
+<p>
+  Android N mengintegrasikan <a href="http://www.khronos.org/vulkan" class="external-link">Vulkan™</a>, sebuah API rendering 3D baru, ke dalam platform. Seperti
+  <a href="https://www.khronos.org/opengles/" class="external-link">OpenGL™
+  ES</a>, Vulkan merupakan standar terbuka untuk grafik 3D dan rendering yang dikelola
+  oleh Khronos Group.
+</p>
+
+<p>
+  Vulkan didesain dari nol untuk meminimalkan overhead CPU dalam driver,
+  dan memungkinkan aplikasi Anda mengontrol operasi GPU lebih langsung. Vulkan
+  juga memungkinkan paralelisasi yang lebih baik dengan mengizinkan beberapa thread menjalankan
+  pekerjaan seperti pembuatan buffer perintah sekaligus.
+</p>
+
+<p>
+  Pustaka dan alat pengembangan Vulkan telah dimasukkan ke dalam Android NDK. Ini
+  berisi:
+</p>
+
+<ul>
+  <li>Header
+  </li>
+
+  <li>Layer validasi (pustaka debug)
+  </li>
+
+  <li>SPIR-V shader compiler
+  </li>
+
+  <li>Pustaka kompilasi shader waktu proses SPIR-V
+  </li>
+</ul>
+
+<p>
+  Vulkan hanya tersedia untuk aplikasi pada perangkat dengan perangkat keras yang mendukung Vulkan,
+  seperti Nexus 5X, Nexus 6P, dan Nexus Player. Kami bekerja sama erat dengan mitra
+  agar secepatnya makin banyak perangkat yang dilengkapi Vulkan.
+</p>
+
+<p>
+  Untuk informasi selengkapnya, lihat <a href="{@docRoot}ndk/guides/graphics/index.html">dokumentasi API</a>.
+</p>
+
+<h2 id="tile_api">Quick Settings Tile API</h2>
+
+
+<div style="float:right;max-width:320px">
+<img src="{@docRoot}images/android-7.0/quicksettings.png" style="padding-left:1.5em;">
+
+<p class="img-caption" style="padding-left:2em;">
+  <strong>Gambar 5.</strong> Quick Settings Tile dalam bayangan pemberitahuan.
+</p>
+
+
+  </div><p>Quick Settings adalah cara populer dan mudah untuk mengekspos setelan dan tindakan utama,
+langsung dari bayangan pemberitahuan. Di Android N, kami telah memperluas lingkup
+Quick Settings untuk membuatnya lebih berguna dan praktis lagi. </p>
+
+<p>Kami telah menambahkan ruang lebih banyak untuk petak Quick Settings tambahan, yang bisa
+diakses pengguna di semua bagian area tampilan halaman bernomor dengan mengusap ke kiri atau kanan. Kami juga memberi pengguna
+kontrol untuk mengatur letak dan petak Quick Settings apa yang akan
+ditampilkan &mdash; pengguna bisa menambahkan atau memindahkan petak dengan menyeret dan melepasnya. </p>
+
+<p>Bagi pengembang, Android N juga menambahkan API baru yang memungkinkan Anda mendefinisikan
+  petak Quick Settings untuk memberi akses mudah kepada pengguna ke berbagai kontrol dan tindakan utama dalam aplikasi Anda.</p>
+
+<p>
+  Petak Quick Settings dicadangkan untuk kontrol atau tindakan yang
+  mendesak atau sering digunakan, dan tidak boleh digunakan sebagai pintasan untuk
+ membuka aplikasi.
+</p>
+
+<p>
+  Setelah mendefinisikan petak, Anda bisa menyediakannya kepada pengguna, yang bisa mereka tambahkan
+  ke Quick Settings cukup dengan seret dan lepas.
+</p>
+
+<p>
+  Untuk informasi tentang pembuatan petak aplikasi, lihat dokumentasi untuk
+  <code>android.service.quicksettings.Tile</code> dalam <a href="{@docRoot}preview/setup-sdk.html#docs-dl">Referensi API</a> yang bisa diunduh.
+</p>
+
+
+
+<h2 id="number-blocking">Pemblokiran Nomor</h2>
+
+<p>Android N sekarang mendukung pemblokiran nomor di platform dan menyediakan
+API kerangka kerja agar penyedia layanan bisa mengelola daftar nomor blokir. Aplikasi SMS
+default, aplikasi telepon default, dan aplikasi operator bisa membaca dari dan
+menulis ke daftar nomor blokir. Daftar ini tidak dapat diakses oleh aplikasi lain.</p>
+
+<p>Dengan membuat pemblokiran nomor sebagai fitur standar pada platformnya, Android menyediakan
+cara konsisten bagi aplikasi untuk mendukung pemblokiran nomor di berbagai
+perangkat. Manfaat lain yang bisa diperoleh aplikasi antara lain:</p>
+
+<ul>
+  <li> Nomor yang diblokir untuk panggilan juga akan diblokir untuk SMS
+  <li> Nomor yang diblokir tetap disimpan saat pengaturan ulang dan pada berbagai perangkat melalui fitur Backup &amp;
+Restore.
+  <li> Beberapa aplikasi sekaligus bisa menggunakan daftar nomor blokir yang sama.
+</ul>
+
+<p>Selain itu, dengan integrasi aplikasi operator melalui Android berarti operator bisa
+membaca daftar nomor blokir pada perangkat dan melakukan pemblokiran di sisi layanan
+bagi pengguna tersebut untuk menghentikan panggilan dan SMS yang tidak diinginkan
+agar tidak sampai ke pengguna lewat media apa pun, misalnya VOIP-endpoint atau meneruskan panggilan telepon.</p>
+
+<p>
+  Untuk informasi selengkapnya, lihat <code>android.provider.BlockedNumberContract</code>
+  dalam <a href="{@docRoot}preview/setup-sdk.html#docs-dl">Referensi
+  API</a> yang bisa diunduh.
+</p>
+
+<h2 id="call_screening">Penyaringan Panggilan</h2>
+
+<p>
+  Android N memungkinkan aplikasi telepon default untuk menyaring panggilan masuk. Aplikasi
+  telepon melakukannya dengan mengimplementasikan <code>CallScreeningService</code> baru,
+  yang memungkinkan aplikasi telepon untuk melakukan sejumlah tindakan berdasarkan
+  {@link android.telecom.Call.Details Call.Details} panggilan masuk, misalnya:
+</p>
+
+<ul>
+  <li> Menolak panggilan masuk
+  <li> Tidak mengizinkan panggilan tersebut disimpan ke log panggilan
+  <li> Tidak menampilkan pemberitahuan untuk panggilan tersebut kepada pengguna
+</ul>
+
+<p>
+  Untuk informasi selengkapnya, lihat <code>android.telecom.CallScreeningService</code>
+  dalam <a href="{@docRoot}preview/setup-sdk.html#docs-dl">Referensi
+  API</a> yang bisa diunduh.
+</p>
+
+
+<h2 id="multi-locale_languages">Dukungan Multilokal, Lebih Banyak Bahasa yang Didukung</h2>
+
+
+<p>Android N kini memungkinkan pengguna memilih <strong>banyak lokal</strong> di Settings,
+untuk mendukung kasus penggunaan dwibahasa dengan lebih baik. Aplikasi bisa menggunakan
+API baru untuk mendapatkan lokal pilihan pengguna kemudian menawarkan pengalaman pengguna
+yang lebih canggih untuk pengguna multilokal &mdash; seperti menampilkan hasil telusur dalam
+banyak bahasa dan tidak menawarkan untuk menerjemahkan halaman web dalam bahasa
+yang sudah diketahui pengguna.</p>
+
+<p>Bersama dukungan multilokal, Android N juga memperluas ragam bahasa
+yang tersedia untuk pengguna. Masing-masing ditawarkan lebih dari 25 varian untuk bahasa yang umum
+digunakan seperti Inggris, Spanyol, Prancis, dan Arab. Juga ditambahkan dukungan
+parsial untuk lebih dari 100 bahasa baru.</p>
+
+<p>Aplikasi bisa mendapatkan daftar lokal yang disetel oleh pengguna dengan memanggil
+<code>LocaleList.GetDefault()</code>.  Untuk mendukung jumlah lokal yang diperluas, Android N sedang
+ mengubah cara mengatasi masalah sumber daya. Pastikan Anda menguji dan memverifikasi bahwa aplikasi Anda
+berfungsi seperti yang diharapkan dengan logika resolusi sumber daya baru.</p>
+
+<p>Untuk mengetahui tentang perilaku resolusi sumber daya baru dan praktik terbaik yang
+harus Anda ikuti, lihat <a href="{@docRoot}preview/features/multilingual-support.html">Dukungan Multibahasa</a>.</p>
+
+
+<h2 id="emoji">Emoji Baru</h2>
+
+<p>
+  Android N memperkenalkan emoji tambahan dan fitur terkait emoji termasuk
+  emoji warna kulit dan dukungan untuk pemilih
+  variasi. Jika aplikasi Anda mendukung emoji,
+  ikuti panduan berikut untuk memanfaatkan fitur terkait emoji ini.
+</p>
+
+<ul>
+  <li>
+    <strong>Periksa apakah perangkat berisi emoji sebelum memasukannya.</strong>
+    Untuk memeriksa emoji mana yang terdapat di
+    font sistem, gunakan metode {@link android.graphics.Paint#hasGlyph(String)}.
+  </li>
+  <li>
+    <strong>Periksa apakah emoji mendukung pemilih variasi.</strong>
+    Pemilih variasi memungkinkan Anda
+    menampilkan emoji tertentu berwarna atau hitam-putih.
+    Pada perangkat seluler, aplikasi akan menghadirkan emoji berwarna daripada hitam-putih. Akan tetapi,
+    jika aplikasi Anda menampilkan emoji sebaris dengan teks, maka harus menggunakan variasi hitam-putih.
+    Untuk menentukan apakah sebuah emoji memiliki variasi, gunakan pemilih variasi.
+    Untuk daftar lengkap dari karakter dengan variasinya, tinjaulah bagian
+    <em>rangkaian variasi emoji</em> pada
+    <a class="external-link" href="http://www.unicode.org/Public/9.0.0/ucd/StandardizedVariants-9.0.0d1.txt">
+      dokumentasi Unicode mengenai variasi</a>.
+  </li>
+  <li>
+    <strong>Periksa apakah emoji mendukung warna kulit.</strong> Android N memungkinkan pengguna memodifikasi
+    warna kulit emoji yang dirender sesuai dengan preferensi mereka. Aplikasi keyboard harus menyediakan indikasi
+    visual untuk emoji yang memiliki beberapa warna kulit dan harus memungkinkan pengguna
+    memilih warna kulit yang mereka sukai. Untuk menentukan apakah emoji sistem memiliki
+    modifier warna kulit, gunakan metode {@link android.graphics.Paint#hasGlyph(String)}.
+ Anda bisa menentukan emoji mana yang menggunakan warna kulit dengan membaca
+    <a class="external-link" href="http://unicode.org/emoji/charts/full-emoji-list.html">
+     dokumentasi Unicode</a>.
+  </li>
+</ul>
+
+
+<h2 id="icu4">ICU4J API di Android</h2>
+
+<p>
+  Android N kini menawarkan subset <a href="http://site.icu-project.org/">ICU4J</a> API dalam kerangka kerja Android pada paket
+  <code>android.icu</code>. Migrasi mudah, dan biasanya hanya perlu
+  mengubah dari ruang nama <code>com.java.icu</code> ke
+  <code>android.icu</code>. Jika Anda sudah menggunakan bundel ICU4J dalam aplikasi,
+  maka beralih ke <code>android.icu</code> API yang disediakan dalam kerangka kerja
+  Android bisa menghasilkan penghematan besar dalam ukuran APK.
+</p>
+
+<p>
+  Untuk mengetahui selengkapnya tentang Android ICU4J API, lihat <a href="{@docRoot}preview/features/icu4j-framework.html">Dukungan ICU4J</a>.
+</p>
+
+
+
+<h2 id="gles_32">OpenGL&trade; ES 3.2 API</h2>
+
+<p>Android N menambahkan antarmuka kerangka kerja dan dukungan platform untuk OpenGL ES 3.2, termasuk:</p>
+
+<ul>
+  <li> Semua ekstensi dari <a class="external-link" href="https://www.khronos.org/registry/gles/extensions/ANDROID/ANDROID_extension_pack_es31a.txt">
+Android Extension Pack</a></a> (AEP) kecuali untuk <code>EXT_texture_sRGB_decode</code>.
+  <li> Floating-point framebuffer untuk HDR dan shading yang ditangguhkan.
+  <li> Panggilan draw BaseVertex agar batching dan streaming jadi lebih baik.
+  <li> Kontrol akses buffer yang tangguh untuk mengurangi overhead WebGL.
+</ul>
+
+<p>API kerangka kerja untuk OpenGL ES 3.2 di Android N dilengkapi dengan kelas
+  <code>GLES32</code>. Saat menggunakan OpenGL ES 3.2, pastikan
+mendeklarasikan persyaratan dalam file manifes Anda, dengan tag <code>&lt;uses-feature&gt;</code> dan
+atribut <code>android:glEsVersion</code>. </p>
+
+<p>Untuk informasi tentang menggunakan OpenGL ES, termasuk cara memeriksa versi
+OpenGL ES yang didukung perangkat saat waktu proses, lihat <a href="{@docRoot}guide/topics/graphics/opengl.html">Panduan OpenGL ES API</a>.</p>
+
+
+<h2 id="android_tv_recording">Perekaman Android TV</h2>
+
+<p>Android N menambahkan kemampuan untuk merekam dan memutar kembali materi dari layanan masukan
+Android TV melalui API perekaman baru.  Karena dibangun dengan API perekaman yang sudah
+ada, layanan masukan TV bisa mengontrol data saluran apa yang bisa direkam, cara menyimpan
+sesi rekaman, dan mengelola interaksi pengguna dengan materi rekaman. </p>
+
+<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}preview/features/tv-recording-api.html">API Perekaman Android TV</a>.</p>
+
+
+<h2 id="android_for_work">Android for Work</h2>
+
+<p>Android for Work menambahkan berbagai fitur dan API baru untuk perangkat yang menjalankan Android N.
+Beberapa fitur unggulannya ada di bawah ini &mdash; untuk mengetahui daftar lengkap perubahannya, lihat
+<a href="{@docRoot}preview/features/afw.html">Pembaruan Android for Work</a>.</p>
+
+<h3 id="work_profile_security_challenge">Pertanyaan Keamanan Profil Kerja </h3>
+
+<p>
+  Pemilik profil yang menargetkan N SDK
+  bisa menetapkan pertanyaan keamanan terpisah untuk aplikasi yang berjalan di
+  profil kerja. Pertanyaan kerja ditampilkan bila pengguna mencoba membuka
+  aplikasi kerja apa pun. Jawaban pertanyaan keamanan yang benar akan membuka
+  profil kerja dan mendekripsinya jika diperlukan. Untuk pemilik profil,
+  <code>ACTION_SET_NEW_PASSWORD</code> akan meminta pengguna untuk menetapkan pertanyaan
+  kerja, dan <code>ACTION_SET_NEW_PARENT_PROFILE_PASSWORD</code> meminta
+  pengguna menyetel kunci perangkat.
+</p>
+
+<p>
+  Pemilik profil bisa menyetel kebijakan kode sandi untuk pertanyaan kerja
+  (seperti berapa lama seharusnya PIN, atau apakah sidik jari bisa digunakan
+  untuk membuka kunci profil) menggunakan <code>setPasswordQuality()</code>,
+  <code>setPasswordMinimumLength()</code> dan metode terkait. Pemilik profil
+  juga bisa menyetel kunci perangkat, menggunakan instance <code>DevicePolicyManager</code>
+  yang dikembalikan oleh metode <code>getParentProfileInstance()</code>  baru.
+  Selain itu, pemilik profil bisa menyesuaikan layar kredensial untuk
+ pertanyaan kerja menggunakan metode baru <code>setOrganizationColor()</code> dan
+  <code>setOrganizationName()</code>.
+</p>
+<h3 id="turn_off_work">Menonaktifkan pekerjaan </h3>
+
+<p>Pada perangkat dengan profil kerja, pengguna bisa beralih mode kerja. Bila mode
+kerja dinonaktifkan, profil yang dikelola akan dinonaktifkan untuk sementara, yang akan menonaktifkan aplikasi
+profil kerja, sinkronisasi latar belakang, dan pemberitahuan. Termasuk aplikasi pemilik
+profil. Bila profil kerja dinonaktifkan, sistem akan menampilkan ikon status
+tetap untuk mengingatkan pengguna bahwa mereka tidak bisa meluncurkan aplikasi kerja. Peluncur
+menunjukkan bahwa aplikasi kerja dan widget tidak bisa diakses. </p>
+
+<h3 id="always_on_vpn">Always-On VPN </h3>
+
+<p>Pemilik perangkat dan pemilik profil bisa memastikan bahwa aplikasi kerja selalu menghubungkan
+melalui VPN yang ditetapkan. Sistem secara otomatis akan memulai VPN itu setelah booting
+perangkat.</p>
+
+<p>
+  Metode <code>DevicePolicyManager</code> baru adalah
+  <code>setAlwaysOnVpnPackage()</code> dan
+  <code>getAlwaysOnVpnPackage()</code>.
+</p>
+
+<p>Karena layanan VPN bisa diikat langsung oleh sistem tanpa interaksi
+aplikasi, klien VPN perlu menangani titik masuk baru untuk Always-On VPN. Seperti
+sebelumnya, layanan ditunjukkan ke sistem melalui
+tindakan pencocokan filter intent <code>android.net.VpnService</code>. </p>
+
+<p>
+  Pengguna bisa secara manual menyetel klien Always-On VPN yang mengimplementasikan
+  metode <code>VPNService</code> dalam pengguna utama dengan menggunakan
+  <strong>Settings&gt;More&gt;Vpn</strong>.
+</p>
+
+<h3 id="custom_provisioning">Penyediaan yang disesuaikan</h3>
+
+<p>
+  Aplikasi bisa menyesuaikan alur penyediaan pemilik profil dan pemilik perangkat
+  dengan warna dan logo perusahaan.
+  <code>DevicePolicyManager.EXTRA_PROVISIONING_MAIN_COLOR</code> menyesuaikan
+  warna alur. <code>DevicePolicyManager.EXTRA_PROVISIONING_LOGO_URI</code>
+  menyesuaikan alur dengan logo perusahaan.
+</p>
+
+<h2 id="accessibility_enhancements">Penyempurnaan Aksesibilitas</h2>
+
+<p>Android N saat ini menawarkan Vision Settings langsung di layar Sambutan untuk
+persiapan perangkat baru. Ini sangat memudahkan pengguna untuk menemukan dan mengonfigurasi
+fitur aksesibilitas pada perangkat mereka, termasuk isyarat perbesaran, ukuran
+font, ukuran layar, dan TalkBack. </p>
+
+<p>Dengan fitur aksesibilitas yang penempatannya semakin jelas, pengguna Anda
+kemungkinan besar akan mencoba aplikasi dengan fitur-fitur yang diaktifkan itu. Pastikan Anda menguji aplikasi
+lebih dini dengan mengaktifkan dahulu setelan ini. Anda bisa mengaktifkannya dari Settings &gt;
+Accessibility.</p>
+
+<p>Di Android N, layanan aksesibilitas sekarang bisa membantu pengguna yang mengalami gangguan
+motorik untuk menyentuh layar. API baru memungkinkan membangun layanan dengan
+fitur-fitur seperti pelacakan wajah, pelacakan mata, pemindaian titik, dan seterusnya, untuk
+memenuhi kebutuhan para pengguna tersebut.</p>
+
+<p>Untuk informasi selengkapnya, lihat <code>android.accessibilityservice.GestureDescription</code>
+ dalam <a href="{@docRoot}preview/setup-sdk.html#docs-dl">Referensi  API</a> yang bisa diunduh.</p>
+
+
+<h2 id="direct_boot">Direct Boot</h2>
+
+<p>Direct Boot memperbaiki waktu startup perangkat dan memungkinkan aplikasi
+yang telah didaftarkan memiliki fungsionalitas terbatas bahkan setelah boot ulang tak terduga.
+Misalnya, jika perangkat yang dienkripsi melakukan boot ulang selagi pengguna tidur,
+alarm terdaftar, pesan dan panggilan masuk sekarang bisa terus memberi tahu
+pengguna seperti biasa. Ini juga berarti layanan aksesibilitas bisa
+  segera tersedia setelah restart.</p>
+
+<p>Direct Boot memanfaatkan enkripsi berbasis file di Android N
+untuk mengaktifkan kebijakan enkripsi yang telah disesuaikan bagi sistem dan data aplikasi.
+Sistem akan menggunakan penyimpanan yang dienkripsi dengan perangkat untuk data sistem terpilih dan data
+aplikasi yang terdaftar secara eksplisit. Secara default, penyimpanan yang dienkripsi dengan kredensial digunakan untuk semua
+  data sistem lainnya, data pengguna, aplikasi, dan data aplikasi. </p>
+
+<p>Saat booting, sistem dimulai dalam mode terbatas dengan akses
+ke data yang dienkripsi dengan perangkat saja, dan tanpa akses umum ke aplikasi atau data.
+Jika Anda memiliki komponen yang ingin Anda jalankan dalam mode ini, Anda bisa mendaftarkannya
+dengan menyetel flag dalam manifes. Setelah restart, sistem akan mengaktifkan
+komponen terdaftar dengan menyiarkan intent <code>LOCKED_BOOT_COMPLETED</code>.
+ Sistem akan memastikan data aplikasi yang dienkripsi dengan perangkat tersedia
+sebelum membuka kunci. Semua data lainnya tidak tersedia sebelum Pengguna mengonfirmasi
+  kredensial layar kunci mereka untuk mendekripsinya. </p>
+
+Untuk informasi selengkapnya, lihat <a href="{@docRoot}preview/features/direct-boot.html">Direct Boot</a>.</p>
+</p>
+
+
+<h2 id="key_attestation">Key Attestation</h2>
+
+<p>Keystore yang didukung perangkat keras menyediakan metode yang jauh lebih aman untuk membuat, menyimpan,
+dan menggunakan kunci kriptografi pada perangkat Android. Keystore itu melindungi kunci dari
+kernel Linux, potensi kerentanan Android, dan ekstraksi
+dari perangkat yang di-root.</p>
+
+<p>Agar lebih mudah dan lebih aman dalam menggunakan keystore yang didukung perangkat keras,
+Android N memperkenalkan Key Attestation. Aplikasi dan perangkat-nonaktif bisa menggunakan Key
+Attestation untuk menentukan apakah penyandingan kunci RSA atau EC
+didukung perangkat keras, apa properti dari penyandingan kunci, dan batasan
+  apa yang diterapkan terhadap penggunaan dan validitasnya. </p>
+
+<p>Aplikasi dan layanan perangkat-nonaktif bisa meminta informasi tentang penyandingan kunci
+melalui sertifikat pengesahan X.509 yang harus ditandatangani dengan kunci
+pengesahan yang valid. Kunci pengesahan adalah kunci penandatanganan ECDSA yang
+telah diinjeksikan ke dalam keystore yang didukung perangkat keras pada perangkat saat di pabriknya.
+Karena itu, sertifikat pengesahan yang ditandatangani oleh kunci pengesahan yang
+valid akan mengonfirmasi keberadaan keystore yang didukung perangkat keras, bersama
+  detail pasangan kunci dalam keystore itu.</p>
+
+<p>Untuk memastikan perangkat ini menggunakan citra Android resmi yang
+aman dari pabrik, Key Attestation mengharuskan <a class="external-link" href="https://source.android.com/security/verifiedboot/verified-boot.html#bootloader_requirements">bootloader</a> perangkat
+menyediakan informasi berikut pada <a class="external-link" href="https://source.android.com/security/trusty/index.html">Trusted
+Execution Environment (TEE)</a>:</p>
+
+<ul>
+<li>Versi OS dan level patch yang dipasang pada perangkat</li>
+<li>Kunci publik <a href="https://source.android.com/security/verifiedboot/index.html" class="external-link">Verified Boot</a> dan status kunci</li>
+  </ul>
+
+<p>Untuk informasi selengkapnya tentang fitur keystore yang didukung perangkat keras,
+lihat panduan untuk <a href="https://source.android.com/security/keystore/" class="external-link">Keystore yang Didukung Perangkat Keras</a>.</p>
+
+<p>Selain Key Attestation, Android N juga memperkenalkan
+  kunci yang terikat sidik jari yang tidak dipanggil saat pendaftaran sidik jari.</p>
+
+<h2 id="network_security_config">Network Security Config</h2>
+
+<p>Di Android N, aplikasi bisa menyesuaikan perilaku koneksi aman mereka
+(HTTPS, TLS) secara aman, tanpa modifikasi kode, dengan menggunakan
+<em>Network Security Config</em> deklaratif sebagai ganti menggunakan API programatik
+konvensional yang rawan kesalahan (mis. X509TrustManager).</p>
+
+  <p>Fitur yang didukung:</p>
+<ul>
+<li><b>Trust-anchor khusus.</b> Memungkinkan aplikasi menyesuaikan
+Certificate Authorities (CA) mana yang dipercaya untuk koneksi amannya. Misalnya,
+mempercayai sertifikat tertentu yang ditandatangani sendiri atau set CA publik yang dibatasi.
+</li>
+<li><b>Penggantian hanya-debug.</b> Memungkinkan pengembang aplikasi dengan aman men-debug
+koneksi aman aplikasi mereka tanpa menambah risiko pada basis yang sudah
+dipasang.
+</li>
+<li><b>Berhenti dari lalu lintas cleartext.</b> Memungkinkan aplikasi melindungi dirinya sendiri dari
+penggunaan lalu lintas cleartext yang tidak disengaja.</li>
+<li><b>Penyematan sertifikat.</b> Sebuah fitur canggih yang memungkinkan aplikasi
+  membatasi kunci server mana yang dipercaya untuk koneksi aman.</li>
+</ul>
+
+<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}preview/features/security-config.html">Network Security
+Config</a>.</p>
+
+<h2 id="default_trusted_ca">Certificate Authority Tepercaya Default</h2>
+
+<p>Secara default, aplikasi yang menargetkan Android N hanya mempercayai sertifikat yang disediakan sistem
+dan tidak lagi mempercayai Certificate Authorities (CA) yang ditambahkan pengguna. Aplikasi yang menargetkan Android
+N dan ingin mempercayai CA yang ditambahkan pengguna harus menggunakan
+<a href="{@docRoot}preview/features/security-config.html">Network Security Config</a> untuk
+menetapkan cara mempercayai CA pengguna.</p>
+
+<h2 id="apk_signature_v2">APK Signature Scheme v2</h2>
+
+<p>
+  Android N memperkenalkan APK Signature Scheme v2, sebuah skema penandatanganan aplikasi baru yang
+  menawarkan waktu pasang aplikasi lebih cepat dan lebih banyak perlindungan terhadap perubahan
+ tidak sah pada file APK. Secara default, Android Studio 2.2 dan Android
+  Plugin untuk Gradle 2.2 menandatangani aplikasi Anda menggunakan APK Signature Scheme v2 dan
+  skema penandatanganan tradisional, yang menggunakan penandatanganan JAR.
+</p>
+
+<p>
+  Meskipun kami menyarankan untuk menerapkan APK Signature Scheme v2 pada aplikasi Anda, skema
+  baru ini tidak wajib. Jika aplikasi Anda tidak dibangun dengan benar saat menggunakan APK
+  Signature Scheme v2, Anda bisa menonaktifkan skema baru ini. Proses penonaktifan
+  menyebabkan Android Studio 2.2 dan Android Plugin untuk Gradle 2.2 menandatangani aplikasi Anda
+  menggunakan skema penandatanganan tradisional saja. Untuk menandatangani dengan
+ skema tradisional saja, buka file <code>build.gradle</code> level-modul, kemudian
+  tambahkan baris <code>v2SigningEnabled false</code> ke konfigurasi
+  penandatanganan rilis Anda:
+</p>
+
+<pre>
+  android {
+    ...
+    defaultConfig { ... }
+    signingConfigs {
+      release {
+        storeFile file("myreleasekey.keystore")
+        storePassword "password"
+        keyAlias "MyReleaseKey"
+        keyPassword "password"
+        <strong>v2SigningEnabled false</strong>
+      }
+    }
+  }
+</pre>
+
+<p class="caution"><strong>Perhatian: </strong> Jika Anda menandatangani aplikasi menggunakan APK
+  Signature Scheme v2 dan membuat perubahan lebih jauh pada aplikasi, tanda tangan aplikasi
+  menjadi tidak valid. Untuk alasan ini, gunakan alat seperti <code>zipalign</code>
+  sebelum menandatangani aplikasi Anda menggunakan APK Signature Scheme v2, bukan setelahnya.
+</p>
+
+<p>
+  Untuk informasi selengkapnya, baca dokumen Android Studio yang menjelaskan cara
+  <a href="{@docRoot}studio/publish/app-signing.html#release-mode">
+  menandatangani aplikasi</a> di Android Studio dan cara<a href="{@docRoot}studio/build/build-variants.html#signing"> mengonfigurasi
+  file build untuk menandatangani aplikasi</a> menggunakan Android Plugin untuk Gradle.
+</p>
+
+<h2 id="scoped_directory_access">Scoped Directory Access</h2>
+
+<p>Di Android N, aplikasi bisa menggunakan API baru untuk meminta akses ke direktori <a href="{@docRoot}guide/topics/data/data-storage.html#filesExternal">penyimpanan
+eksternal</a> tertentu, termasuk direktori di media lepas-pasang seperti kartu
+SD. API baru ini sangat menyederhanakan cara aplikasi Anda mengakses direktori
+penyimpanan eksternal standar, seperti direktori <code>Pictures</code>. Aplikasi
+seperti aplikasi foto bisa menggunakan API ini sebagai ganti menggunakan
+<code>READ_EXTERNAL_STORAGE</code>, yang memberikan akses ke semua direktori
+penyimpanan, atau Storage Access Framework, yang membuat pengguna mengarah ke
+direktori tersebut.</p>
+
+<p>Selain itu, API baru ini menyederhanakan langkah-langkah yang diambil pengguna untuk memberikan akses
+penyimpanan eksternal ke aplikasi Anda. Bila Anda menggunakan API baru, sistem akan menggunakan UI izin
+sederhana yang memperinci dengan jelas direktori apa yang aksesnya diminta
+oleh aplikasi.</p>
+
+<p>Untuk informasi selengkapnya, lihat dokumentasi pengembang
+<a href="{@docRoot}preview/features/scoped-folder-access.html">Scoped
+Directory Access</a>.</p>
+
+<h2 id="keyboard_shortcuts_helper">Keyboard Shortcuts Helper</h2>
+
+<p>
+Di Android N, pengguna bisa menekan "Alt + /" untuk memunculkan layar <em>Keyboard Shortcuts</em>
+yang menampilkan semua pintasan yang tersedia baik dari sistem maupun dari
+aplikasi yang sedang mendapatkan fokus. Ini diambil secara otomatis dari menu aplikasi
+jika tersedia, namun pengembang bisa menyediakan daftar pintasan yang telah disesuaikan
+untuk layar. Anda bisa melakukannya dengan mengganti metode
+<code>Activity.onProvideKeyboardShortcuts()</code> baru, yang dijelaskan dalam
+<a href="{@docRoot}preview/setup-sdk.html#docs-dl">Referensi API</a> yang bisa diunduh.
+</p>
+
+<p>
+Untuk memunculkan Keyboard Shortcuts Helper dari mana saja di aplikasi Anda,
+panggil {@code Activity.requestKeyboardShortcutsHelper()} untuk aktivitas terkait.
+</p>
+
+<h2 id="sustained_performance_api">Sustained Performance API</h2>
+
+<p>
+Kinerja bisa berfluktuasi secara dramatis untuk aplikasi yang berjalan lama, karena
+sistem melakukan throttle pada mesin sistem-di-chip saat komponen perangkat mencapai
+batas suhunya. Fluktuasi ini memberikan target bergerak bagi pengembang
+aplikasi yang sedang membuat aplikasi berkinerja tinggi dan berjalan lama.
+</p>
+
+<p>
+Untuk menangani batasan ini, Android N menyertakan dukungan untuk
+<em>mode kinerja kontinu</em>, yang memungkinkan OEM memberikan petunjuk mengenai kemampuan kinerja
+perangkat untuk aplikasi yang berjalan lama. Pengembang aplikasi
+bisa menggunakan petunjuk ini untuk menyesuaikan aplikasi agar kinerja perangkat bisa diprediksi
+dan pada level yang konsisten dalam jangka waktu lama.
+</p>
+
+<p>
+Pengembang aplikasi bisa mencoba API baru ini dalam N Developer Preview pada
+perangkat Nexus 6P saja. Untuk menggunakan fitur ini,
+setel flag jendela kinerja kontinu
+yang ingin Anda jalankan dalam mode kinerja kontinu. Setel flag ini menggunakan metode
+{@code Window.setSustainedPerformanceMode()}. Sistem secara otomatis
+akan menonaktifkan mode ini bila jendela tidak lagi mendapatkan fokus.
+</p>
+
+<h2 id="vr">Dukungan VR</h2>
+
+<p>
+Android N menambahkan dukungan platform dan optimalisasi untuk VR Mode baru yang memungkinkan
+pengembang membuat pengalaman VR berkualitas tinggi di seluler bagi para pengguna. Ada banyak perbaikan
+kinerja, termasuk akses ke inti CPU yang eksklusif untuk aplikasi VR.
+Di dalam aplikasi, Anda bisa memanfaatkan pelacakan kepala yang cerdas,
+dan pemberitahuan stereo yang bekerja untuk VR. Hal terpenting adalah Android N menyediakan
+grafis dengan latensi sangat rendah. Untuk informasi selengkapnya tentang membangun aplikasi VR untuk Android N,
+lihat <a href="https://developers.google.com/vr/android/">Google VR SDK untuk Android</a>.
+</p>
+
+
+<h2 id="print_svc">Penyempurnaan Layanan Cetak</h2>
+
+<p>
+  Di Android N, pengembang layanan cetak kini bisa menampilkan informasi tambahan
+  tentang masing-masing printer dan pekerjaan cetak.
+</p>
+
+<p>
+  Saat mendaftarkan masing-masing printer, layanan cetak kini bisa menyetel
+  ikon per printer dalam dua cara:
+</p>
+
+<ul>
+  <li>Anda bisa menyetel ikon dari ID sumber daya dengan memanggil
+  <code>PrinterInfo.Builder.setResourceIconId()</code>
+  </li>
+
+  <li>Anda bisa menampilkan ikon dari jaringan dengan memanggil
+  <code>PrinterInfo.Builder.setHasCustomPrinterIcon()</code>, dan menyetel sebuah
+ callback bila ikon diminta menggunakan
+  <code>android.printservice.PrinterDiscoverySession.onRequestCustomPrinterIcon()</code>
+  </li>
+</ul>
+
+<p>
+  Selain itu, Anda bisa menyediakan aktivitas per printer untuk menampilkan informasi
+  tambahan dengan memanggil <code>PrinterInfo.Builder.setInfoIntent()</code>.
+</p>
+
+<p>
+  Anda bisa menunjukkan kemajuan dan status pekerjaan cetak di
+  pemberitahuan pekerjaan cetak dengan memanggil masing-masing
+  <code>android.printservice.PrintJob.setProgress()</code> dan
+  <code>android.printservice.PrintJob.setStatus()</code>.
+</p>
+
+<p>
+  Untuk informasi selengkapnya tentang metode ini,lihat  dalam <a href="{@docRoot}preview/setup-sdk.html#docs-dl">Referensi  API</a> yang bisa diunduh.
+</p>
+
+<h2 id="framemetrics_api">FrameMetricsListener API</h2>
+
+<p>
+FrameMetricsListener API memungkinkan aplikasi untuk memantau
+kinerja rendering UI. API tersebut menyediakan kemampuan ini dengan mengekspos Pub/Sub API streaming
+untuk mentransfer info frame-timing untuk jendela aplikasi saat ini. Data yang dikembalikan
+setara dengan yang ditampilkan <code><a href="{@docRoot}tools/help/shell.html#shellcommands">adb shell</a>
+dumpsys gfxinfo framestats</code>, namun tidak dibatasi pada 120 bingkai.
+</p>
+
+<p>
+Anda bisa menggunakan FrameMetricsListener untuk mengukur kinerja UI
+level interaksi di produksi, tanpa koneksi USB. API
+ini memungkinkan pengumpulan data dengan granularitas lebih tinggi daripada
+{@code adb shell dumpsys gfxinfo}. Granularitas lebih tinggi ini dimungkinkan karena
+sistem bisa mengumpulkan data untuk interaksi tertentu di aplikasi; sistem
+tidak perlu merekam ringkasan global untuk keseluruhan kinerja
+aplikasi, atau mengosongkan status global yang ada. Anda bisa menggunakan kemampuan ini
+untuk mengumpulkan data kinerja dan menangkap regresi di kinerja UI
+untuk kasus penggunaan sungguhan di dalam aplikasi.
+</p>
+
+<p>
+Untuk memantau sebuah jendela, implementasikan metode callback <code>FrameMetricsListener.onMetricsAvailable()</code>
+dan daftarkan di jendela itu. Untuk informasi selengkapnya, lihat
+dokumentasi kelas {@code FrameMetricsListener} di
+<a href="{@docRoot}preview/setup-sdk.html#docs-dl">Referensi API</a> yang bisa diunduh.
+</p>
+
+<p>
+API menyediakan objek {@code FrameMetrics}, yang berisi data timing yang
+dilaporkan subsistem rendering untuk berbagai tahap pencapaian dalam daur hidup bingkai.
+Metrik yang didukung adalah: {@code UNKNOWN_DELAY_DURATION},
+{@code INPUT_HANDLING_DURATION}, {@code ANIMATION_DURATION},
+{@code LAYOUT_MEASURE_DURATION}, {@code DRAW_DURATION}, {@code SYNC_DURATION},
+{@code COMMAND_ISSUE_DURATION}, {@code SWAP_BUFFERS_DURATION},
+{@code TOTAL_DURATION}, dan {@code FIRST_DRAW_FRAME}.
+</p>
+
+
+<h2 id="virtual_files">File Maya</h2>
+
+<p>
+  Di versi Android sebelumnya, aplikasi Anda bisa menggunakan Storage Access
+  Framework untuk memungkinkan pengguna memilih file dari akun penyimpanan awan mereka,
+  seperti Google Drive. Akan tetapi, tidak ada cara untuk merepresentasikan file yang
+  tidak memiliki representasi bytecode langsung; setiap file diharuskan menyediakan
+  aliran masukan.
+</p>
+
+<p>
+  Android N menambahkan konsep <em>file maya</em> pada Storage Access
+  Framework. Fitur file maya memungkinkan
+  {@link android.provider.DocumentsProvider} Anda mengembalikan URI dokumen yang bisa
+  digunakan bersama intent {@link android.content.Intent#ACTION_VIEW} sekalipun
+  tidak memiliki representasi bytecode langsung. Android N juga memungkinkan Anda untuk
+  menyediakan format alternatif untuk file pengguna, maya atau dengan cara lain.
+</p>
+
+<p>
+  Untuk mendapatkan URI sebuah dokumen maya di aplikasi Anda, terlebih dahulu Anda membuat
+  {@link android.content.Intent} untuk membuka UI pemilih file. Karena aplikasi
+  tidak bisa membuka file maya secara langsung dengan menggunakan metode
+  {@link android.content.ContentResolver#openInputStream(Uri) openInputStream()},
+   aplikasi Anda tidak akan menerima file maya jika Anda memasukkan kategori
+  {@link android.content.Intent#CATEGORY_OPENABLE}.
+</p>
+
+<p>
+  Setelah pengguna menentukan pilihan, sistem akan memanggil metode
+  {@link android.app.Activity#onActivityResult onActivityResult()}.
+  Aplikasi Anda bisa mengambil URI file maya dan mendapatkan aliran masukan, seperti yang
+  diperagakan dalam cuplikan kode di bawah.
+</p>
+
+<pre>
+  // Other Activity code ...
+
+  final static private int REQUEST_CODE = 64;
+
+  // We listen to the OnActivityResult event to respond to the user's selection.
+  &#64;Override
+  public void onActivityResult(int requestCode, int resultCode,
+    Intent resultData) {
+      try {
+        if (requestCode == REQUEST_CODE &amp;&amp;
+            resultCode == Activity.RESULT_OK) {
+
+            Uri uri = null;
+
+            if (resultData != null) {
+                uri = resultData.getData();
+
+                ContentResolver resolver = getContentResolver();
+
+                // Before attempting to coerce a file into a MIME type,
+                // check to see what alternative MIME types are available to
+                // coerce this file into.
+                String[] streamTypes =
+                  resolver.getStreamTypes(uri, "*/*");
+
+                AssetFileDescriptor descriptor =
+                    resolver.openTypedAssetFileDescriptor(
+                        uri,
+                        streamTypes[0],
+                        null);
+
+                // Retrieve a stream to the virtual file.
+                InputStream inputStream = descriptor.createInputStream();
+            }
+        }
+      } catch (Exception ex) {
+        Log.e("EXCEPTION", "ERROR: ", ex);
+      }
+  }
+</pre>
+
+<p>
+  Untuk informasi selengkapnya tentang mengakses file pengguna, lihat
+  <a href="{@docRoot}guide/topics/providers/document-provider.html">Panduan Storage
+  Access Frameworks</a>.
+</p>
diff --git a/docs/html-intl/intl/id/about/versions/nougat/index.jd b/docs/html-intl/intl/id/about/versions/nougat/index.jd
new file mode 100644
index 0000000..212870a
--- /dev/null
+++ b/docs/html-intl/intl/id/about/versions/nougat/index.jd
@@ -0,0 +1,110 @@
+page.title=Android 7.0 Nougat
+page.tags="androidn","versions"
+meta.tags="android n", "nougat", "android 7.0"
+fullpage=true
+forcelocalnav=true
+header.hide=1
+footer.hide=1
+@jd:body
+
+<section class="dac-expand dac-hero dac-light">
+  <div class="wrap" style="max-width:1100px;margin-top:0">
+  <a href="{@docRoot}about/versions/nougat/android-7.0.html">
+    <div class="cols dac-hero-content" style="padding-bottom:1em;">
+
+      <div class="col-7of16 col-push-8of16" style="padding-left:2em">
+        <h1 class="dac-hero-title">Android 7.0 Nougat</h1>
+        <p class="dac-hero-description">
+          Bersiaplah menyambut Android Nougat!
+          <strong>Uji aplikasi Anda</strong> pada perangkat Nexus dan perangkat lainnya. Dukung perilaku sistem
+          baru untuk <strong>menghemat daya dan memori</strong>.
+          Tambah aplikasi Anda dengan <strong>UI multi-jendela</strong>,
+          <strong>pemberitahuan balasan langsung</strong> dan lainnya.
+        </p>
+
+        <a class="dac-hero-cta" href="{@docRoot}about/versions/nougat/android-7.0.html">
+          <span class="dac-sprite dac-auto-chevron"></span>
+          Mulai
+        </a>
+      </div>
+      <div class="col-7of16 col-pull-6of16 dac-hero-figure" style="margin-top:1.5em;padding-right:1.5em;">
+        <a  href="{@docRoot}about/versions/nougat/android-7.0.html">
+        <img class="dac-hero-image" src="{@docRoot}images/home/n-preview-hero.png"
+             srcset="{@docRoot}images/home/n-preview-hero.png 1x,
+             {@docRoot}images/home/n-preview-hero_2x.png 2x" />
+           </a>
+      </div>
+    </div></a>
+    <div class="dac-section dac-small">
+      <div class="resource-widget resource-flow-layout col-16"
+           data-query="collection:nougat/landing/resources"
+           data-cardSizes="6x2"
+           data-maxResults="3"></div>
+         </div>
+  </div>
+</section>
+
+
+<div class="dac-section dac-slim dac-gray dac-expand">
+  <div class="wrap dac-offset-parent">
+    <a class="dac-fab dac-scroll-button" data-scroll-button href="#latest">
+      <i class="dac-sprite dac-arrow-down-gray"></i>
+    </a>
+    <ul class="dac-actions">
+      <li class="dac-action">
+        <a class="dac-action-link" href="https://source.android.com/source/report-bugs.html">
+          <i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
+          Laporkan masalah
+        </a>
+      </li>
+      <li class="dac-action">
+        <a class="dac-action-link" href="{@docRoot}preview/dev-community">
+          <i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
+          Bergabunglah dengan komunitas pengembang
+        </a>
+      </li>
+    </ul>
+  </div><!-- end .wrap -->
+</div><!-- end .dac-actions -->
+
+<section class="dac-section dac-light dac-small" id="latest"><div class="wrap">
+  <h2 class="norule">Terbaru</h2>
+  <div class="resource-widget resource-flow-layout col-16"
+    data-query="type:blog+tag:androidn+tag:featured, type:youtube+tag:androidn+tag:featured"
+    data-sortOrder="-timestamp"
+    data-cardSizes="6x6"
+    data-items-per-page="6"
+    data-maxResults="15"
+    data-initial-results="3"></div>
+</div></section>
+
+<section class="dac-section dac-gray" id="videos"><div class="wrap">
+  <h1 class="dac-section-title">Videos</h1>
+  <div class="dac-section-subtitle">
+    New Android capabilities and the right way to use them in your apps.
+  </div>
+
+  <div class="resource-widget resource-flow-layout col-16"
+    data-query="collection:nougat/landing/videos/first,type:youtube+tag:androidn"
+    data-sortOrder="-timestamp"
+    data-cardSizes="6x6"
+    data-items-per-page="6"
+    data-maxResults="15"
+    data-initial-results="3">
+  </div>
+</div></section>
+
+<section class="dac-section dac-light" id="resources"><div class="wrap">
+  <h1 class="dac-section-title">Sumber Daya</h1>
+  <div class="dac-section-subtitle">
+    Informasi penting guna membantu mempersiapkan aplikasi untuk Android Nougat.
+  </div>
+
+  <div class="resource-widget resource-flow-layout col-16"
+       data-query="collection:nougat/landing/more"
+       data-cardSizes="6x6"
+       data-items-per-page="6"
+       data-maxResults="15"
+       data-initial-results="6"></div>
+  </div>
+</section>
\ No newline at end of file
diff --git a/docs/html-intl/intl/id/design/get-started/principles.jd b/docs/html-intl/intl/id/design/get-started/principles.jd
new file mode 100644
index 0000000..2a1d194
--- /dev/null
+++ b/docs/html-intl/intl/id/design/get-started/principles.jd
@@ -0,0 +1,307 @@
+page.title=Prinsip Desain Android
+@jd:body
+
+<p>Prinsip desain ini dikembangkan oleh dan untuk Tim Pengalaman Pengguna
+ Android agar selalu mempertimbangkan kepentingan pengguna.
+Untuk pengembang dan desainer Android, mereka terus
+meletakkan dasar pedoman desain yang lebih detail untuk beragam tipe
+perangkat.</p>
+
+<p>
+Perhatikan prinsip-prinsip ini saat Anda menerapkan
+kreativitas dan pemikiran desain sendiri. Menyimpang dengan sengaja.
+</p>
+
+<h2 id="enchant-me">Pikat Saya</h2>
+
+<div class="cols">
+  <div class="col-7">
+
+<h4 id="delight-me">Senangkan saya dengan cara yang mengejutkan</h4>
+<p>Permukaan yang cantik, animasi yang ditempatkan dengan hati-hati, atau efek suara di saat yang tepat sungguh menyenangkan untuk
+dinikmati. Efek yang lembut menimbulkan perasaan serba mudah dan kesadaran bahwa kekuatan yang
+bisa diandalkan ada dalam genggaman.</p>
+
+  </div>
+  <div class="col-6">
+
+    <img src="{@docRoot}design/media/principles_delight.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="cols">
+  <div class="col-7">
+
+<h4 id="real-objects-more-fun">Objek sungguhan lebih menyenangkan daripada tombol dan menu</h4>
+<p>Biarkan orang langsung menyentuh dan memanipulasi objek dalam aplikasi Anda. Ini mengurangi upaya kognitif
+yang diperlukan untuk menjalankan tugas sekaligus membuatnya lebih memuaskan secara emosional.</p>
+
+  </div>
+  <div class="col-6">
+
+    <img src="{@docRoot}design/media/principles_real_objects.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="cols">
+  <div class="col-7">
+
+<h4 id="make-it-mine">Biarkan saya memilikinya</h4>
+<p>Orang suka menambahkan sentuhan pribadi karena membantu mereka merasa betah dan memegang kendali. Memberikan
+default yang pantas dan indah, tetapi juga mempertimbangkan penyesuaian opsional yang menyenangkan, yang tidak mengganggu
+tugas utama.</p>
+
+  </div>
+  <div class="col-6">
+
+    <img src="{@docRoot}design/media/principles_make_it_mine.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="cols">
+  <div class="col-7">
+
+<h4 id="get-to-know-me">Kenali saya</h4>
+<p>Pelajari preferensi orang dari waktu ke waktu. Daripada meminta mereka untuk membuat pilihan yang sama
+berulang-ulang, tempatkan pilihan sebelumnya agar mudah dijangkau.</p>
+
+  </div>
+  <div class="col-6">
+
+    <img src="{@docRoot}design/media/principles_get_to_know_me.png">
+
+  </div>
+</div>
+
+<h2 id="simplify-my-life">Sederhanakan Hidup Saya</h2>
+
+<div class="cols">
+  <div class="col-7">
+
+<h4 id="keep-it-brief">Persingkat</h4>
+<p>Gunakan frasa pendek dengan kata-kata sederhana. Orang cenderung melewatkan kalimat-kalimat panjang.</p>
+
+  </div>
+  <div class="col-6">
+
+    <img src="{@docRoot}design/media/principles_keep_it_brief.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="cols">
+  <div class="col-7">
+
+<h4 id="pictures-faster-than-words">Gambar lebih cepat dibanding kata-kata</h4>
+<p>Pertimbangkan menggunakan gambar untuk menjelaskan gagasan. Gambar menarik perhatian orang dan bisa jauh lebih efisien
+dibanding kata-kata.</p>
+
+  </div>
+  <div class="col-6">
+
+    <img src="{@docRoot}design/media/principles_pictures.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="cols">
+  <div class="col-7">
+
+<h4 id="decide-for-me">Putuskan untuk saya tetapi biarkan saya yang menentukan</h4>
+<p>Gunakan tebakan terbaik Anda dan bertindaklah daripada meminta terlebih dahulu. Terlalu banyak pilihan dan keputusan membuat orang
+tidak suka. Untuk berjaga-jaga jika Anda salah, izinkan 'pembatalan'.</p>
+
+  </div>
+  <div class="col-6">
+
+    <img src="{@docRoot}design/media/principles_decide_for_me.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="cols">
+  <div class="col-7">
+
+<h4 id="only-show-when-i-need-it">Cukup tunjukkan yang saya perlukan ketika saya memerlukannya</h4>
+<p>Orang merasa kewalahan ketika melihat terlalu banyak hal sekaligus. Uraikan tugas dan informasi menjadi potongan-potongan
+kecil yang mudah dicerna. Sembunyikan opsi yang tidak perlu pada saat ini, dan ajari orang sambil jalan.</p>
+
+  </div>
+  <div class="col-6">
+
+    <img src="{@docRoot}design/media/principles_information_when_need_it.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="cols">
+  <div class="col-7">
+
+<h4 id="always-know-where-i-am">Saya harus selalu tahu di mana saya berada</h4>
+<p>Beri orang kepercayaan diri bahwa mereka tahu di mana berada. Buat agar tempat-tempat dalam aplikasi Anda terlihat berbeda dan
+gunakan transisi untuk menunjukkan hubungan antar layar. Berikan umpan balik tentang tugas yang sedang berlangsung.</p>
+
+  </div>
+  <div class="col-6">
+
+    <img src="{@docRoot}design/media/principles_navigation.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="cols">
+  <div class="col-7">
+
+<h4 id="never-lose-my-stuff">Jangan sekali-kali menghilangkan milik saya</h4>
+<p>Simpan apa yang telah susah-payah dibuat orang dan biarkan mereka mengaksesnya dari mana saja. Ingat pengaturan,
+sentuhan pribadi, dan kreasi lintas ponsel, tablet, dan komputer. Itu membuat pemutakhiran menjadi
+hal termudah di dunia.</p>
+
+  </div>
+  <div class="col-6">
+
+    <img src="{@docRoot}design/media/principles_never_lose_stuff.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="cols">
+  <div class="col-7">
+
+<h4 id="looks-same-should-act-same">Jika terlihat sama, seharusnya fungsinya sama</h4>
+<p>Bantu orang merasakan perbedaan fungsional dengan membuat mereka terlihat berbeda daripada mirip.
+Hindari mode, yaitu tempat yang terlihat mirip tetapi berbeda fungsinya pada input yang sama.</p>
+
+  </div>
+  <div class="col-6">
+
+    <img src="{@docRoot}design/media/principles_looks_same.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="cols">
+  <div class="col-7">
+
+<h4 id="interrupt-only-if-important">Sela saya jika penting saja</h4>
+<p>Layaknya asisten pribadi yang baik, lindungi orang dari detail yang tidak penting. Orang ingin tetap
+fokus, dan kecuali jika memang penting dan sensitif waktu, interupsi bisa melelahkan dan menjengkelkan.</p>
+
+  </div>
+  <div class="col-6">
+
+    <img src="{@docRoot}design/media/principles_important_interruption.png">
+
+  </div>
+</div>
+
+<h2 id="make-me-amazing">Buat Saya Terpesona</h2>
+
+<div class="cols">
+  <div class="col-7">
+
+<h4 id="give-me-tricks">Beri saya trik yang efektif di mana saja</h4>
+<p>Orang merasa senang ketika mereka memahami sendiri sesuatu. Jadikan aplikasi Anda lebih mudah dipelajari dengan
+memanfaatkan pola visual dan memori otot dari aplikasi Android lainnya. Misalnya, gerakan menggeser
+dapat menjadi pintasan navigasi yang bagus.</p>
+
+  </div>
+  <div class="col-6">
+
+    <img src="{@docRoot}design/media/principles_tricks.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="cols">
+  <div class="col-7">
+
+<h4 id="its-not-my-fault">Bukan salah saya</h4>
+<p>Bersikap ramahlah dalam meminta orang untuk melakukan koreksi. Mereka ingin merasa pintar ketika menggunakan
+aplikasi Anda. Jika terjadi kesalahan, berikan petunjuk perbaikan yang jelas tetapi lepaskan mereka dari detail teknis.
+Jika Anda dapat memperbaikinya secara diam-diam, tentu lebih baik.</p>
+
+  </div>
+  <div class="col-6">
+
+    <img src="{@docRoot}design/media/principles_error.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="cols">
+  <div class="col-7">
+
+<h4 id="sprinkle-encouragement">Berikan dorongan</h4>
+<p>Uraikan tugas-tugas rumit menjadi langkah-langkah kecil yang dapat dilakukan dengan mudah. Beri umpan balik tentang tindakan,
+meskipun hanya sesuatu yang sederhana.</p>
+
+  </div>
+  <div class="col-6">
+
+    <img src="{@docRoot}design/media/principles_sprinkle_encouragement.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="cols">
+  <div class="col-7">
+
+<h4 id="do-heavy-lifting-for-me">Lakukan pekerjaan yang sulit untuk saya</h4>
+<p>Buatlah pemula merasa seperti ahli dengan memungkinkan mereka untuk melakukan hal-hal yang mereka pikir tidak akan bisa.
+Misalnya, pintasan yang menggabungkan beberapa efek foto dapat membuat foto amatir terlihat mengagumkan hanya
+dalam beberapa langkah.</p>
+
+  </div>
+  <div class="col-6">
+
+    <img src="{@docRoot}design/media/principles_heavy_lifting.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="cols">
+  <div class="col-7">
+
+<h4 id="make-important-things-fast">Percepat hal penting</h4>
+<p>Tidak semua tindakan itu sama. Putuskan apa yang terpenting dalam aplikasi Anda dan permudah untuk menemukannya serta
+cepat untuk digunakan, seperti tombol rana pada kamera, atau tombol jeda pada pemutar musik.</p>
+
+  </div>
+  <div class="col-6">
+
+    <img src="{@docRoot}design/media/principles_make_important_fast.png">
+
+  </div>
+</div>
diff --git a/docs/html-intl/intl/id/design/material/index.jd b/docs/html-intl/intl/id/design/material/index.jd
new file mode 100644
index 0000000..0cb4dbc
--- /dev/null
+++ b/docs/html-intl/intl/id/design/material/index.jd
@@ -0,0 +1,186 @@
+page.title=Material Design for Android
+page.tags=Material,design
+page.type=design
+page.image=images/cards/design-material-for-android_2x.jpg
+
+@jd:body
+
+<!-- developer docs box -->
+<a class="notice-developers right" href="{@docRoot}training/material/index.html">
+  <div>
+    <h3>Dokumen Pengembang</h3>
+    <p>Membuat Aplikasi dengan Desain Bahan</p>
+  </div>
+</a>
+
+<!-- video box -->
+<a class="notice-developers-video" href="https://www.youtube.com/watch?v=p4gmvHyuZzw">
+<div>
+    <h3>Video</h3>
+    <p>Pengantar Desain Bahan</p>
+</div>
+</a>
+
+<!-- video box -->
+<a class="notice-developers-video" href="https://www.youtube.com/watch?v=YaG_ljfzeUw">
+<div>
+    <h3>Video</h3>
+    <p>Kertas dan Tinta: Bahan Penting</p>
+</div>
+</a>
+
+<!-- video box -->
+<a class="notice-developers-video" href="https://www.youtube.com/watch?v=XOcCOBe8PTc">
+<div>
+    <h3>Video</h3>
+    <p>Desain Bahan di Aplikasi Google I/O</p>
+</div>
+</a>
+
+
+
+<p itemprop="description">Desain bahan adalah panduan komprehensif untuk desain visual, gerak, dan
+interaksi lintas platform dan perangkat. Android kini menyertakan dukungan untuk
+aplikasi desain bahan. Untuk menggunakan desain bahan di aplikasi Android, ikuti panduan yang didefinisikan
+dalam <a href="http://www.google.com/design/spec">spesifikasi desain bahan</a> dan gunakan
+komponen dan fungsionalitas baru yang tersedia di Android 5.0 (API level 21) ke atas.</p>
+
+<p>Android menyediakan elemen berikut untuk membangun aplikasi desain bahan:</p>
+
+<ul>
+  <li>Tema baru</li>
+  <li>Widget baru untuk tampilan yang kompleks</li>
+  <li>API baru untuk animasi dan bayangan custom</li>
+</ul>
+
+<p>Untuk informasi selengkapnya tentang mengimplementasikan desain bahan pada Android, lihat
+<a href="{@docRoot}training/material/index.html">Membuat Aplikasi dengan Desain Bahan</a>.</p>
+
+
+<h3>Tema Bahan</h3>
+
+<p>Tema bahan menyediakan gaya baru untuk aplikasi Anda, widget sistem yang memungkinkan Anda mengatur
+palet warnanya, dan animasi default untuk umpan balik sentuh dan transisi aktivitas.</p>
+
+<!-- two columns -->
+<div style="width:700px;margin-top:25px;margin-bottom:20px">
+<div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
+  <img src="{@docRoot}design/material/images/MaterialDark.png" width="500" height="238" />
+  <div style="width:140px;margin:0 auto">
+  <p style="margin-top:8px">Tema bahan gelap</p>
+  </div>
+</div>
+<div style="float:left;width:250px;margin-right:0px;">
+  <img src="{@docRoot}design/material/images/MaterialLight.png" width="500" height="238" />
+  <div style="width:140px;margin:0 auto">
+  <p style="margin-top:8px">Tema bahan terang</p>
+  </div>
+</div>
+<br style="clear:left"/>
+</div>
+
+<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/theme.html">Menggunakan Tema
+Bahan</a>.</p>
+
+
+<h3>Daftar dan Kartu</h3>
+
+<p>Android menyediakan dua widget baru untuk menampilkan kartu dan daftar dengan gaya desain bahan
+dan animasi:</p>
+
+<!-- two columns -->
+<div style="width:700px;margin-top:25px;margin-bottom:20px">
+<div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
+  <img src="{@docRoot}design/material/images/list_mail.png" width="500" height="426" />
+  <p>Widget <code>RecyclerView</code> baru adalah versi <code>ListView</code>
+ yang lebih mudah dimasukkan dan mendukung beragam tipe layout serta memberikan peningkatan kinerja.</p>
+</div>
+<div style="float:left;width:250px;margin-right:0px;">
+  <img src="{@docRoot}design/material/images/card_travel.png" width="500" height="426" />
+  <p>Widget <code>CardView</code> baru memungkinkan Anda menampilkan potongan informasi penting dalam
+  kartu yang memiliki tampilan dan cara kerja yang konsisten.</p>
+</div>
+<br style="clear:left"/>
+</div>
+
+<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/lists-cards.html">Membuat Daftar
+dan Kartu</a>.</p>
+
+
+<h3>Bayangan Tampilan</h3>
+
+<p>Selain properti X dan Y, tampilan di Android kini memiliki
+properti Z. Properti baru ini mewakili ketinggian tampilan, yang menentukan:</p>
+
+<ul>
+<li>Ukuran bayangan: tampilan dengan nilai Z lebih tinggi menghasilkan bayangan lebih besar.</li>
+<li>Urutan penggambaran: tampilan dengan nilai Z lebih tinggi muncul di atas tampilan lainnya.</li>
+</ul>
+
+<div style="width:290px;margin-left:35px;float:right">
+  <div class="framed-nexus5-port-span-5">
+  <video class="play-on-hover" autoplay>
+    <source src="{@docRoot}design/material/videos/ContactsAnim.mp4"/>
+    <source src="{@docRoot}design/videos/ContactsAnim.webm"/>
+    <source src="{@docRoot}design/videos/ContactsAnim.ogv"/>
+  </video>
+  </div>
+  <div style="font-size:10pt;margin-left:20px;margin-bottom:30px">
+    <em>Untuk memutar ulang film, klik layar perangkat</em>
+  </div>
+</div>
+
+<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/shadows-clipping.html">Mendefinisikan
+Bayangan dan Memangkas Tampilan</a>.</p>
+
+
+<h3>Animasi</h3>
+
+<p>API animasi baru memungkinkan Anda membuat animasi custom untuk umpan balik sentuh dalam kontrol UI,
+perubahan status tampilan, dan transisi aktivitas.</p>
+
+<p>API ini memungkinkan Anda:</p>
+
+<ul>
+<li style="margin-bottom:15px">
+Merespons kejadian sentuh dalam tampilan Anda dengan animasi <strong>umpan balik sentuh</strong>.
+</li>
+<li style="margin-bottom:15px">
+Menyembunyikan dan memperlihatkan tampilan dengan animasi <strong>membuka melingkar</strong>.
+</li>
+<li style="margin-bottom:15px">
+Peralihan antar aktivitas dengan animasi <strong>transisi aktivitas</strong> custom.
+</li>
+<li style="margin-bottom:15px">
+Membuat animasi yang lebih alami dengan <strong>gerak melengkung</strong>.
+</li>
+<li style="margin-bottom:15px">
+Menganimasikan perubahan dalam satu atau beberapa properti tampilan dengan animasi <strong>perubahan status tampilan</strong>.
+</li>
+<li style="margin-bottom:15px">
+Menampilkan animasi di <strong>drawable daftar status</strong> di antara perubahan status tampilan.
+</li>
+</ul>
+
+<p>Animasi umpan balik sentuh dimasukkan ke dalam beberapa tampilan standar, misalnya tombol. API baru
+ini memungkinkan Anda menyesuaikan animasi ini dan menambahkannya ke tampilan custom Anda.</p>
+
+<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/animations.html">Mendefinisikan Animasi
+Custom</a>.</p>
+
+
+<h3>Drawable</h3>
+
+<p>Kemampuan baru untuk drawable ini membantu Anda mengimplementasikan aplikasi desain bahan:</p>
+
+<ul>
+<li><strong>Drawable vektor</strong> bisa diubah skalanya tanpa kehilangan definisi dan cocok
+untuk ikon satu-warna dalam-aplikasi.</li>
+<li><strong>Pewarnaan drawable</strong> memungkinkan Anda mendefinisikan bitmap sebagai alpha-mask dan mewarnainya
+saat runtime.</li>
+<li><strong>Ekstraksi warna</strong> memungkinkan Anda mengekstrak warna mencolok secara otomatis dari
+gambar bitmap.</li>
+</ul>
+
+<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/drawables.html">Bekerja dengan
+Drawable</a>.</p>
diff --git a/docs/html-intl/intl/id/design/patterns/compatibility.jd b/docs/html-intl/intl/id/design/patterns/compatibility.jd
new file mode 100644
index 0000000..cafaac4
--- /dev/null
+++ b/docs/html-intl/intl/id/design/patterns/compatibility.jd
@@ -0,0 +1,70 @@
+page.title=Kompatibilitas Mundur
+page.tags="support"
+page.metaDescription=Catatan tentang bagaimana Android 4.x menyesuaikan UI yang didesain untuk perangkat keras dan versi OS yang lebih lama.
+@jd:body
+
+<a class="notice-developers" href="{@docRoot}training/basics/supporting-devices/index.html">
+  <div>
+    <h3>Dokumen Pengembang</h3>
+    <p>Mendukung Perangkat Berbeda</p>
+  </div>
+</a>
+
+<p>Perubahan signifikan dalam Android 3.0 meliputi:</p>
+<ul>
+<li>Dihilangkannya tombol perangkat keras navigasi (Back, Menu, Search, Home) untuk membantu menangani navigasi
+  melalui kontrol maya (Back, Home, Recents).</li>
+<li>Pola yang tangguh untuk penggunaan menu pada action-bar.</li>
+</ul>
+<p>Android 4.0 membawa perubahan ini untuk tablet dengan platform ponsel.</p>
+
+<h2 id="older-hardware">Menyesuaikan Android 4.0 dengan Perangkat Keras dan Aplikasi yang Lebih Lama</h2>
+
+<div class="cols">
+  <div class="col-6">
+
+<h4>Ponsel dengan kontrol navigasi virtual</h4>
+<p>Aplikasi Android yang ditulis untuk Android 3.0 dan yang lebih baru menampilkan tindakan dalam action-bar. Tindakan yang tidak
+muat dalam action-bar atau tidak cukup penting untuk ditampilkan di tingkat atas akan muncul dalam
+action-overflow.</p>
+<p>Pengguna mengakses action-overflow dengan menyentuhnya dalam action-bar.</p>
+
+  </div>
+  <div class="col-7">
+
+    <img src="{@docRoot}design/media/compatibility_virtual_nav.png">
+
+  </div>
+</div>
+
+<div class="cols">
+  <div class="col-6">
+
+<h4>Ponsel dengan tombol navigasi fisik</h4>
+<p>Ponsel Android dengan tombol perangkat keras navigasi biasa tidak menampilkan baris navigasi virtual di
+bagian bawah layar. Sebagai gantinya, action-overflow tersedia dari tombol perangkat keras menu. Popup
+tindakan yang dihasilkan memiliki gaya yang sama dengan contoh sebelumnya, tetapi ditampilkan di bagian bawah layar.</p>
+
+  </div>
+  <div class="col-7">
+
+    <img src="{@docRoot}design/media/compatibility_physical_buttons.png">
+
+  </div>
+</div>
+
+<div class="cols">
+  <div class="col-6">
+
+<h4>Aplikasi lama pada ponsel dengan kontrol navigasi virtual</h4>
+<p>Bila Anda menjalankan aplikasi yang dibuat untuk Android 2.3 atau yang lebih lama pada ponsel
+dengan kontrol navigasi virtual, sebuah kontrol action-overflow akan muncul di sebelah kanan baris navigasi virtual. Anda
+dapat menyentuh kontrol itu untuk menampilkan tindakan aplikasi dalam gaya menu Android biasa.</p>
+
+  </div>
+  <div class="col-7">
+
+    <img src="{@docRoot}design/media/compatibility_legacy_apps.png">
+
+  </div>
+</div>
diff --git a/docs/html-intl/intl/id/design/patterns/confirming-acknowledging.jd b/docs/html-intl/intl/id/design/patterns/confirming-acknowledging.jd
new file mode 100644
index 0000000..d22e924
--- /dev/null
+++ b/docs/html-intl/intl/id/design/patterns/confirming-acknowledging.jd
@@ -0,0 +1,70 @@
+page.title=Mengonfirmasi &amp; Mengakui
+page.tags=dialog,toast,notification
+@jd:body
+
+<p>Dalam beberapa situasi, bila pengguna memanggil suatu tindakan dalam aplikasi Anda, ada baiknya <em>mengonfirmasi</em> atau <em>mengakui</em> tindakan itu melalui teks.</p>
+
+<div class="cols">
+  <div class="col-6">
+    <img src="{@docRoot}design/media/confirm_ack_confirming.png">
+    <p><strong>Mengonfirmasi</strong> adalah meminta pengguna untuk memverifikasi bahwa mereka benar-benar ingin melanjutkan tindakan yang baru saja mereka panggil. Dalam beberapa kasus, konfirmasi ditampilkan bersama-sama dengan peringatan atau informasi penting yang terkait dengan tindakan yang perlu mereka pertimbangkan.</p>
+  </div>
+  <div class="col-6">
+    <img src="{@docRoot}design/media/confirm_ack_acknowledge.png">
+    <p><strong>Mengakui</strong> adalah menampilkan teks untuk memberi tahu pengguna bahwa tindakan yang baru mereka panggil sudah dilakukan. Ini menghilangkan ketidakpastian tentang operasi implisit yang dilakukan sistem. Dalam beberapa kasus, pengakuan ditampilkan bersama dengan opsi untuk membatalkan tindakan.</p>
+  </div>
+</div>
+
+<p>Berkomunikasi pada pengguna dengan cara ini bisa membantu mengurangi ketidakpastian tentang hal-hal yang sudah atau akan terjadi. Mengonfirmasi atau mengakui juga dapat mencegah pengguna melakukan kesalahan yang akan mereka sesali.</p>
+
+<h2>Kapan Harus Mengonfirmasi atau Mengakui Tindakan Pengguna</h2>
+<p>Tidak semua tindakan memerlukan konfirmasi atau pengakuan. Gunakan bagan alur ini untuk memandu keputusan desain Anda.</p>
+<img src="{@docRoot}design/media/confirm_ack_flowchart.png">
+
+<h2>Mengonfirmasi</h2>
+<div class="cols">
+  <div class="col-6">
+    <h4>Contoh: Google Play Books</h4>
+    <img src="{@docRoot}design/media/confirm_ack_ex_books.png">
+    <p>Dalam contoh ini, pengguna telah meminta untuk menghapus sebuah buku dari perpustakaan Google Play mereka. Sebuah <a href="{@docRoot}design/building-blocks/dialogs.html#alerts">peringatan</a> muncul untuk mengonfirmasi tindakan ini karena perlu dipahami bahwa buku tersebut tidak akan tersedia lagi dari perangkat apa pun.</p>
+    <p>Saat membuat dialog konfirmasi, buat judul bermakna dengan mencerminkan tindakan yang diminta.</p>
+  </div>
+  <div class="col-7">
+    <h4>Contoh: Android Beam</h4>
+    <img src="{@docRoot}design/media/confirm_ack_ex_beam.png">
+    <p>Konfirmasi tidak harus ditampilkan dalam peringatan dengan dua tombol. Setelah menjalankan Android Beam, pengguna diminta untuk menyentuh konten yang akan dibagikan (dalam contoh ini, sebuah foto). Jika mereka memutuskan untuk tidak melanjutkan, mereka tinggal memindahkan ponsel.</p>
+  </div>
+</div>
+
+<h2>Mengakui</h2>
+<div class="cols">
+  <div class="col-6">
+    <h4>Contoh: Draf Gmail batal yang disimpan</h4>
+    <img src="{@docRoot}design/media/confirm_ack_ex_draftsave.png">
+    <p>Dalam contoh ini, jika pengguna menyusuri ke belakang atau ke atas dari layar pembuatan email di Gmail, sesuatu yang tak diharapkan bisa terjadi: draf saat itu akan disimpan secara otomatis. Pengakuan dalam bentuk pemberitahuan akan lebih jelas. Ini menghilang setelah beberapa detik.</p>
+    <p>Pembatalan tidak cocok di sini karena penyimpanan dilakukan oleh aplikasi, bukan pengguna. Cepat dan mudah untuk melanjutkan penulisan pesan dengan menyusuri daftar draf.</p>
+
+  </div>
+  <div class="col-6">
+    <h4>Contoh: Percakapan Gmail dihapus</h4>
+    <img src="{@docRoot}design/media/confirm_ack_draft_deleted.png">
+    <p>Setelah pengguna menghapus percakapan dari daftar dalam Gmail, sebuah pengakuan muncul tanpa opsi pembatalan. Pengakuan tetap ada sampai pengguna melakukan tindakan yang tidak berkaitan, seperti menggulir daftar.</p>
+  </div>
+</div>
+
+<h2>Tidak ada Konfirmasi atau Pengakuan</h2>
+<div class="cols">
+  <div class="col-6">
+    <h4>Contoh: memberikan +1</h4>
+    <img style="padding: 33px 0 30px;" src="{@docRoot}design/media/confirm_ack_ex_plus1.png">
+    <p><strong>Konfirmasi tidak diperlukan</strong>. Jika pengguna telah memberikan +1 secara tidak sengaja, tidak masalah. Mereka cukup menyentuh kembali tombol itu untuk membatalkan tindakan.</p>
+    <p><strong>Pengakuan tidak diperlukan</strong>. Pengguna akan melihat tombol +1 memantul dan berubah merah. Itu tanda yang sangat jelas.</p>
+  </div>
+  <div class="col-7">
+    <h4>Contoh: Menghapus aplikasi dari Layar Beranda</h4>
+    <img src="{@docRoot}design/media/confirm_ack_ex_removeapp.png">
+    <p><strong>Konfirmasi tidak diperlukan</strong>. Ini adalah tindakan yang disengaja: pengguna harus menyeret dan meletakkan sebuah item di atas target yang relatif besar dan terpisah. Karena itu, kecil kemungkinan terjadi ketidaksengajaan. Tetapi jika pengguna menyesali keputusan itu, maka hanya perlu beberapa detik untuk mengembalikannya lagi.</p>
+    <p><strong>Pengakuan tidak diperlukan</strong>. Pengguna akan mengetahui bahwa aplikasi itu tidak ada di Layar Beranda karena mereka menghilangkannya dengan cara menyeretnya.</p>
+
+  </div>
+</div>
diff --git a/docs/html-intl/intl/id/design/patterns/navigation.jd b/docs/html-intl/intl/id/design/patterns/navigation.jd
new file mode 100644
index 0000000..4915700
--- /dev/null
+++ b/docs/html-intl/intl/id/design/patterns/navigation.jd
@@ -0,0 +1,213 @@
+page.title=Navigasi dengan Back dan Up
+page.tags="navigation","activity","task","up navigation","back navigation"
+page.image=/design/media/navigation_between_siblings_gmail.png
+@jd:body
+
+<a class="notice-developers" href="{@docRoot}training/implementing-navigation/index.html">
+  <div>
+    <h3>Dokumen Pengembang</h3>
+    <p>Mengimplementasikan Navigasi yang Efektif</p>
+  </div>
+</a>
+
+<p itemprop="description">Navigasi yang konsisten merupakan komponen penting dari keseluruhan pengalaman pengguna. Hampir tidak ada yang lebih membingungkan
+pengguna selain navigasi dasar yang perilakunya tidak konsisten dan tidak sesuai harapan. Android 3.0
+memperkenalkan perubahan besar dalam perilaku navigasi global. Mengikuti dengan saksama
+panduan untuk Back dan Up akan membuat navigasi aplikasi Anda dapat diprediksi dan dapat diandalkan pengguna.</p>
+<p>Android 2.3 dan versi sebelumnya mengandalkan tombol <em>Back</em> sistem untuk mendukung navigasi dalam
+aplikasi. Dengan diperkenalkannya action-bar dalam Android 3.0, mekanisme navigasi kedua muncul:
+tombol <em>Up</em>, yang terdiri dari ikon aplikasi dan tanda panah yang menunjuk ke kiri.</p>
+
+<img src="{@docRoot}design/media/navigation_with_back_and_up.png">
+
+<h2 id="up-vs-back">Up vs. Back</h2>
+
+<p>Tombol Up digunakan untuk berpindah dalam aplikasi berdasarkan hubungan hierarki
+antar layar. Misalnya, jika layar A menampilkan daftar item, dan memilih sebuah item akan membuka
+layar B (yang menampilkan item tersebut secara lebih detail), maka layar B akan menawarkan tombol Up untuk
+kembali ke layar A.</p>
+<p>Jika suatu layar merupakan yang teratas dalam aplikasi (yaitu layar Home aplikasi), maka tidak perlu menampilkan tombol
+Up.</p>
+
+<p>Tombol Back sistem digunakan untuk berpindah, dalam urutan kronologis terbalik, melalui riwayat
+layar yang baru dibuka oleh pengguna. Biasanya ini berdasarkan hubungan sementara
+antar layar, dan bukan hierarki aplikasi.</p>
+
+<p>Bila layar yang dilihat sebelumnya juga merupakan induk hierarki dari layar yang sekarang, menekan tombol
+Back akan sama hasilnya dengan menekan tombol Up&mdash;ini adalah kejadian
+biasa. Akan tetapi, berbeda dengan tombol Up, yang memastikan pengguna tetap berada dalam aplikasi Anda, tombol Back
+dapat mengembalikan pengguna ke layar Home, atau bahkan ke aplikasi lain.</p>
+
+<img src="{@docRoot}design/media/navigation_up_vs_back_gmail.png">
+
+<p>Tombol Back juga mendukung beberapa perilaku yang tidak terkait langsung dengan navigasi antar layar:
+</p>
+<ul>
+<li>Menghilangkan jendela mengambang (dialog, popup)</li>
+<li>Menghilangkan action-bar kontekstual, dan menghapus sorotan dari item yang dipilih</li>
+<li>Menyembunyikan keyboard di layar (IME)</li>
+</ul>
+<h2 id="within-app">Navigasi Dalam Aplikasi Anda</h2>
+
+<h4>Berpindah ke layar yang memiliki beberapa titik masuk</h4>
+<p>Kadang-kadang layar tidak memiliki posisi pasti dalam hierarki aplikasi, dan bisa dimasuki
+dari berbagai titik masuk&mdash;seperti layar pengaturan yang dapat dibuka dari layar lain
+dalam aplikasi Anda. Dalam hal ini, tombol Up akan memilih untuk kembali ke layar pengarah, yang cara kerjanya
+sama dengan tombol Back.</p>
+<h4>Mengubah tampilan dalam layar</h4>
+<p>Mengubah opsi tampilan untuk layar tidak mengubah perilaku Up atau Back: layar tetap
+berada di tempat yang sama dalam hierarki aplikasi, dan tidak dibuat riwayat navigasi yang baru.</p>
+<p>Contoh perubahan tampilan tersebut adalah:</p>
+<ul>
+<li>Mengganti tampilan menggunakan tab dan/atau geser kiri dan kanan</li>
+<li>Mengubah tampilan menggunakan tarik-turun (alias tab turun)</li>
+<li>Memfilter daftar</li>
+<li>Menyortir daftar</li>
+<li>Mengubah karakteristik tampilan (seperti zoom)</li>
+</ul>
+<h4>Berpindah antar layar yang seinduk</h4>
+<p>Bila aplikasi Anda mendukung navigasi dari daftar item ke tampilan detail salah satu item tersebut, aplikasi
+juga sering diharapkan mendukung navigasi langsung dari item itu ke item sebelumnya atau
+sesudahnya dalam daftar. Misalnya, dalam Gmail, begitu mudah untuk bergeser ke kiri atau kanan dari sebuah percakapan
+untuk melihat percakapan yang lebih baru atau lebih lama dalam Inbox yang sama. Sama seperti saat mengubah tampilan dalam layar, navigasi
+ini tidak mengubah perilaku Up atau Back.</p>
+
+<img src="{@docRoot}design/media/navigation_between_siblings_gmail.png">
+
+<p>Akan tetapi, pengecualian khusus terhadap hal ini terjadi saat menjelajah di antara tampilan detail terkait yang tidak disatukan
+oleh daftar yang merujuknya&mdash;misalnya, saat menjelajahi Play Store di antara aplikasi dari
+pengembang yang sama, atau album dari artis yang sama. Dalam hal ini, mengikuti setiap tautan akan membuat
+riwayat, sehingga tombol Back akan menyusuri setiap layar yang dilihat sebelumnya. Tombol Up akan terus
+melewatkan semua layar terkait ini dan berpindah ke layar kontainer yang terakhir dilihat.</p>
+
+<img src="{@docRoot}design/media/navigation_between_siblings_market1.png">
+
+<p>Anda dapat menjadikan perilaku tombol Up lebih cerdas lagi berdasarkan pengetahuan Anda tentang tampilan
+detail. Dengan memperluas contoh Play Store dari atas, bayangkan pengguna yang telah berpindah dari Buku
+terakhir yang dilihat ke detail untuk adaptasi Film. Dalam hal itu, tombol Up dapat kembali ke kontainer
+(Movies) yang sebelumnya belum dilalui pengguna.</p>
+
+<img src="{@docRoot}design/media/navigation_between_siblings_market2.png">
+
+<h2 id="into-your-app">Navigasi ke Aplikasi Anda melalui Widget dan Pemberitahuan Layar Home</h2>
+
+<p>Anda bisa menggunakan widget atau pemberitahuan layar Home untuk membantu pengguna berpindah langsung ke layar
+jauh dalam hierarki aplikasi Anda. Misalnya, widget Inbox dan pemberitahuan pesan baru di Gmail dapat
+melewatkan layar Inbox, dan membawa pengguna langsung ke tampilan percakapan.</p>
+
+<p>Untuk kedua kasus ini, tangani tombol Up sebagai berikut:</p>
+
+<ul>
+<li><em>Jika layar tujuan biasanya dicapai dari satu layar tertentu dalam aplikasi
+Anda</em>, tombol Up akan mengarahkannya ke layar itu.</li>
+<li><em>Jika tidak</em>, tombol Up akan mengarahkan ke layar teratas ("Home") dari aplikasi Anda.</li>
+</ul>
+
+<p>Dalam hal tombol Back, Anda harus membuat navigasi lebih bisa diprediksi dengan menyisipkan ke dalam
+back-stack tugas path navigasi naik lengkap menuju layar teratas aplikasi. Ini memungkinkan pengguna
+yang lupa cara masuk ke aplikasi Anda untuk berpindah ke layar teratas aplikasi sebelum
+keluar.</p>
+
+<p>Sebagai contoh, widget layar Home di Gmail memiliki tombol untuk menuju langsung ke layar
+Compose. Tombol Up atau Back dari layar Compose akan membawa pengguna ke Inbox, dan dari sana tombol
+Back berlanjut ke Home.</p>
+
+<img src="{@docRoot}design/media/navigation_from_outside_back.png">
+
+<h4>Pemberitahuan tidak langsung</h4>
+
+<p>Jika aplikasi Anda perlu menampilkan informasi tentang beberapa kejadian sekaligus, aplikasi dapat menggunakan
+pemberitahuan tunggal yang mengarahkan pengguna ke layar antara. Layar ini merangkum semua
+kejadian tersebut, dan menyediakan path bagi pengguna untuk menjelajah ke dalam aplikasi. Pemberitahuan dengan gaya seperti ini
+disebut <em>pemberitahuan tidak langsung</em>.</p>
+
+<p>Berbeda dengan pemberitahuan standar (langsung), menekan tombol Back dari
+layar antara pada pemberitahuan tidak langsung akan mengembalikan pengguna ke titik pemicu pemberitahuan tersebut&mdash;tidak ada
+layar tambahan yang disisipkan ke dalam back-stack. Setelah pengguna melanjutkan ke dalam aplikasi dari
+layar antara, tombol Up dan Back akan berperilaku seperti pada pemberitahuan standar, sebagaimana dijelaskan di atas:
+menyusuri ke dalam aplikasi dan bukan kembali ke layar antara.</p>
+
+<p>Misalnya, anggaplah seorang pengguna di Gmail menerima pemberitahuan tidak langsung dari Kalender. Menyentuh
+pemberitahuan ini akan membuka layar antara, yang menampilkan pengingat beberapa macam
+kejadian. Menyentuh Back dari layar antara akan mengembalikan pengguna ke Gmail. Menyentuh kejadian
+tertentu akan membawa pengguna dari layar antara ke aplikasi Kalender lengkap untuk menampilkan detail
+kejadian. Dari detail kejadian, tombol Up dan Back akan mengarahkan ke tampilan Kalender tingkat atas.</p>
+
+<img src="{@docRoot}design/media/navigation_indirect_notification.png">
+
+<h4>Pemberitahuan pop-up</h4>
+
+<p><em>Pemberitahuan pop-up</em> akan melewatkan laci pemberitahuan, bukan muncul secara langsung di
+hadapan pengguna. Ini jarang digunakan, dan <strong>harus dicadangkan untuk peristiwa yang memerlukan respons tepat waktu
+dan diperlukan interupsi dari konteks pengguna</strong>. Misalnya,
+Talk menggunakan gaya ini untuk memberi tahu pengguna tentang ajakan dari teman untuk bergabung dalam chatting video, karena
+ajakan ini akan kedaluwarsa secara otomatis setelah beberapa detik.</p>
+
+<p>Dalam hal perilaku navigasi, pemberitahuan pop-up sangat mirip perilaku pemberitahuan
+tidak langsung pada layar antara. Tombol Back akan menghilangkan pemberitahuan pop-up. Jika pengguna berpindah
+dari pop-up ke aplikasi yang memberi tahu, tombol Up dan Back akan mengikuti aturan pemberitahuan standar,
+berpindah dalam aplikasi.</p>
+
+<img src="{@docRoot}design/media/navigation_popup_notification.png">
+
+<h2 id="between-apps">Navigasi Antar Aplikasi</h2>
+
+<p>Salah satu kekuatan dasar sistem Android adalah kemampuan aplikasi untuk saling
+mengaktifkan, sehingga pengguna dapat berpindah langsung dari satu aplikasi ke aplikasi lainnya. Misalnya, sebuah
+aplikasi yang perlu mengambil foto dapat mengaktifkan aplikasi Kamera, yang akan mengembalikan foto
+ke aplikasi perujuk. Ini sangat menguntungkan pengembang, yang bisa dengan mudah memanfaatkan
+kode dari aplikasi lain, maupun pengguna, yang menikmati pengalaman konsisten untuk tindakan yang biasa
+dilakukan.</p>
+
+<p>Untuk memahami navigasi antar aplikasi, maka perlu memahami perilaku kerangka kerja Android
+yang akan dibahas di bawah ini.</p>
+
+<h4>Aktivitas, tugas, dan intent</h4>
+
+<p>Dalam Android, <strong>aktivitas</strong> adalah komponen aplikasi yang mendefinisikan layar
+informasi dan semua tindakan terkait yang dapat dilakukan pengguna. Aplikasi Anda adalah kumpulan
+aktivitas, yang terdiri dari aktivitas yang Anda buat dan aktivitas yang Anda gunakan ulang dari aplikasi lain.</p>
+
+<p><strong>Tugas</strong> adalah urutan aktivitas yang diikuti pengguna untuk mencapai tujuan.
+Tugas tunggal dapat memanfaatkan aktivitas dari satu aplikasi saja, atau dapat memanfaatkan aktivitas dari sejumlah
+aplikasi berbeda.</p>
+
+<p><strong>Intent</strong> adalah mekanisme bagi satu aplikasi untuk memberi isyarat minta bantuan
+aplikasi lain dalam menjalankan suatu tindakan. Aktivitas aplikasi dapat menunjukkan intent
+ apa saja yang dapat diresponsnya. Untuk intent umum seperti "Share", pengguna mungkin telah menginstal beberapa aplikasi
+yang dapat memenuhi permintaan itu.</p>
+
+<h4>Contoh: berpindah antar aplikasi untuk mendukung berbagi</h4>
+
+<p>Untuk memahami cara kerja sama aktivitas, tugas, dan intent, perhatikan bagaimana sebuah aplikasi memungkinkan pengguna
+untuk berbagi konten dengan menggunakan aplikasi lain. Misalnya, membuka aplikasi Play Store dari Home akan memulai
+Task A baru (lihat gambar di bawah). Setelah menyusuri Play Store dan menyentuh buku yang dipromosikan
+untuk melihat detailnya, pengguna tetap berada dalam tugas yang sama, memperluasnya dengan menambahkan aktivitas. Memicu
+tindakan Share akan memberi tahu pengguna dengan dialog berisi daftar aktivitas (dari aplikasi berbeda)
+yang telah terdaftar untuk menangani intent Share.</p>
+
+<img src="{@docRoot}design/media/navigation_between_apps_inward.png">
+
+<p>Bila pengguna memilih untuk berbagi melalui Gmail, aktivitas penulisan di Gmail akan ditambahkan sebagai kelanjutan dari
+Task A&mdash;tidak ada tugas baru yang dibuat. Jika Gmail sedang menjalankan tugasnya di latar belakang, maka
+tidak akan terpengaruh.</p>
+
+<p>Dari aktivitas penulisan, mengirim pesan atau menyentuh tombol Back akan mengembalikan pengguna ke
+aktivitas detail buku tersebut. Penyentuhan tombol Back berikutnya akan terus mengarahkan kembali melalui Play
+Store, sampai akhirnya tiba di Home.</p>
+
+<img src="{@docRoot}design/media/navigation_between_apps_back.png">
+
+<p>Akan tetapi, dengan menyentuh tombol Up dari aktivitas penulisan, pengguna menunjukkan keinginan untuk tetap berada di
+Gmail. Aktivitas daftar percakapan Gmail muncul, Task B yang baru akan dibuat untuk itu. Tugas baru
+selalu terkait ke Home, maka menyentuh tombol Back dari daftar percakapan akan mengembalikan ke sana.</p>
+
+<img src="{@docRoot}design/media/navigation_between_apps_up.png">
+
+<p>Task A tetap berjalan di latar belakang, dan pengguna nanti dapat kembali ke sana (misalnya, melalui layar
+Recents). Jika Gmail sedang menjalankan tugasnya di latar belakang, maka itu akan digantikan
+dengan Task B&mdash;konteks sebelumnya akan diabaikan demi tujuan baru pengguna.</p>
+
+<p>Jika register aplikasi Anda menangani intent dengan aktivitas yang jauh di dalam hierarki aplikasi,
+lihat <a href="#into-your-app">Navigasi Aplikasi Anda melalui Widget Layar Home dan
+Pemberitahuan</a> untuk panduan mengenai cara menetapkan navigasi Up.</p>
diff --git a/docs/html-intl/intl/id/guide/components/activities.jd b/docs/html-intl/intl/id/guide/components/activities.jd
new file mode 100644
index 0000000..bbc061c
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/components/activities.jd
@@ -0,0 +1,756 @@
+page.title=Aktivitas
+page.tags=aktivitas,intent
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>Dalam dokumen ini</h2>
+<ol>
+  <li><a href="#Creating">Membuat Aktivitas</a>
+    <ol>
+      <li><a href="#UI">Mengimplementasikan antarmuka pengguna</a></li>
+      <li><a href="#Declaring">Mendeklarasikan aktivitas dalam manifes</a></li>
+    </ol>
+  </li>
+  <li><a href="#StartingAnActivity">Memulai Aktivitas</a>
+    <ol>
+      <li><a href="#StartingAnActivityForResult">Memulai aktivitas agar berhasil</a></li>
+    </ol>
+  </li>
+  <li><a href="#ShuttingDown">Mematikan Aktivitas</a></li>
+  <li><a href="#Lifecycle">Mengelola Daur Hidup Aktivitas</a>
+    <ol>
+      <li><a href="#ImplementingLifecycleCallbacks">Mengimplementasikan callback daur hidup</a></li>
+      <li><a href="#SavingActivityState">Menyimpan status aktivitas</a></li>
+      <li><a href="#ConfigurationChanges">Menangani perubahan konfigurasi</a></li>
+      <li><a href="#CoordinatingActivities">Mengoordinasikan aktivitas</a></li>
+    </ol>
+  </li>
+</ol>
+
+<h2>Kelas-kelas utama</h2>
+<ol>
+  <li>{@link android.app.Activity}</li>
+</ol>
+
+<h2>Lihat juga</h2>
+<ol>
+  <li><a href="{@docRoot}guide/components/tasks-and-back-stack.html">Tugas dan
+Back-Stack</a></li>
+</ol>
+
+</div>
+</div>
+
+
+
+<p>{@link android.app.Activity} adalah sebuah komponen aplikasi yang menyediakan layar yang digunakan
+pengguna untuk berinteraksi guna melakukan sesuatu, misalnya memilih nomor telepon, mengambil foto, mengirim email, atau
+menampilkan peta. Tiap aktivitas diberi sebuah jendela untuk menggambar antarmuka penggunanya. Jendela ini
+biasanya mengisi layar, namun mungkin lebih kecil daripada layar dan mengambang di atas
+jendela lain.</p>
+
+<p> Sebuah aplikasi biasanya terdiri atas beberapa aktivitas yang terikat secara longgar
+satu sama lain. Biasanya, satu aktivitas dalam aplikasi ditetapkan sebagai aktivitas "utama", yang
+ditampilkan kepada pengguna saat membuka aplikasi untuk pertama kali. Tiap
+aktivitas kemudian bisa memulai aktivitas lain untuk melakukan berbagai tindakan. Tiap kali
+aktivitas baru dimulai, aktivitas sebelumnya akan dihentikan, namun sistem mempertahankan aktivitas
+dalam sebuah tumpukan ("back-stack"). Bila sebuah aktivitas baru dimulai, aktivitas itu akan didorong ke atas back-stack dan
+mengambil fokus pengguna. Back-stack mematuhi mekanisme dasar tumpukan "masuk terakhir, keluar pertama",
+jadi, bila pengguna selesai dengan aktivitas saat ini dan menekan tombol <em>Back</em>, aktivitas
+akan dikeluarkan dari tumpukan (dan dimusnahkan) dan aktivitas sebelumnya akan dilanjutkan. (Back-stack
+dibahas selengkapnya dalam dokumen <a href="{@docRoot}guide/components/tasks-and-back-stack.html">Tugas
+dan Back-Stack</a>.)</p>
+
+<p>Bila aktivitas dihentikan karena ada aktivitas baru yang dimulai, aktivitas lama akan diberi tahu tentang perubahan status ini
+melalui metode callback daur hidupnya.
+Ada beberapa metode callback yang mungkin diterima aktivitas, karena sebuah perubahan dalam
+statusnya&mdash;apakah sistem sedang membuatnya, menghentikannya, melanjutkannya, atau menghapuskannya&mdash;dan
+masing-masing callback memberi Anda kesempatan melakukan pekerjaan tertentu yang
+sesuai untuk perubahan status itu. Misalnya, bila dihentikan, aktivitas Anda harus melepas
+objek besar, seperti koneksi jaringan atau database. Bila aktivitas dilanjutkan, Anda bisa
+memperoleh kembali sumber daya yang diperlukan dan melanjutkan tindakan yang terputus. Transisi status ini
+semuanya bagian dari daur hidup aktivitas.</p>
+
+<p>Bagian selebihnya dari dokumen ini membahas dasar-dasar cara membuat dan menggunakan aktivitas,
+yang meliputi satu pembahasan lengkap tentang cara kerja daur hidup aktivitas, sehingga Anda bisa dengan benar mengelola
+transisi di antara berbagai status aktivitas.</p>
+
+
+
+<h2 id="Creating">Membuat Aktivitas</h2>
+
+<p>Untuk membuat sebuah aktivitas, Anda harus membuat subkelas {@link android.app.Activity} (atau
+subkelasnya yang ada). Dalam subkelas itu, Anda perlu mengimplementasikan metode-metode callback yang
+dipanggil sistem saat aktivitas bertransisi di antara berbagai status daur hidupnya, misalnya saat
+aktivitas sedang dibuat, dihentikan, dilanjutkan, atau dimusnahkan. Dua metode callback
+terpenting adalah:</p>
+
+<dl>
+  <dt>{@link android.app.Activity#onCreate onCreate()}</dt>
+  <dd>Anda harus mengimplementasikan metode ini. Sistem memanggilnya saat membuat
+    aktivitas Anda. Dalam implementasi, Anda harus menginisialisasi komponen-komponen esensial
+aktivitas.
+    Yang terpenting, inilah tempat Anda harus memanggil {@link android.app.Activity#setContentView
+    setContentView()} untuk mendefinisikan layout untuk antarmuka pengguna aktivitas.</dd>
+  <dt>{@link android.app.Activity#onPause onPause()}</dt>
+  <dd>Sistem memanggil metode ini sebagai pertanda pertama bahwa pengguna sedang meninggalkan
+aktivitas Anda (walau itu tidak selalu berarti aktivitas sedang dimusnahkan). Inilah biasanya tempat Anda
+harus mengikat setiap perubahan yang harus dipertahankan selepas sesi pengguna saat ini (karena
+pengguna mungkin tidak kembali).</dd>
+</dl>
+
+<p>Ada beberapa metode callback daur hidup lainnya yang harus Anda gunakan untuk memberikan
+pengalaman pengguna yang mengalir di antara aktivitas dan menangani interupsi tidak terduga yang menyebabkan aktivitas Anda
+dihentikan dan bahkan dimusnahkan. Semua metode callback daur hidup akan dibahas nanti, di
+bagian tentang <a href="#Lifecycle">Mengelola Daur Hidup Aktivitas</a>.</p>
+
+
+
+<h3 id="UI">Mengimplementasikan antarmuka pengguna</h3>
+
+<p> Antarmuka pengguna aktivitas disediakan oleh hierarki objek&mdash;tampilan yang diturunkan
+dari kelas {@link android.view.View}.  Tiap tampilan mengontrol sebuah ruang persegi panjang tertentu
+dalam jendela aktivitas dan bisa merespons interaksi pengguna. Misalnya, sebuah tampilan mungkin berupa sebuah
+tombol yang mengawali suatu tindakan bila pengguna menyentuhnya.</p>
+
+<p>Android menyediakan sejumlah tampilan siap-dibuat yang bisa Anda gunakan untuk mendesain dan mengatur
+layout. "Widget" adalah tampilan yang menyediakan elemen-elemen visual (dan interaktif) untuk layar,
+misalnya tombol, bidang teks, kotak cek, atau sekadar sebuah gambar. "Layout" adalah tampilan yang diturunkan dari {@link
+android.view.ViewGroup} yang memberikan sebuah model layout unik untuk tampilan anaknya, misalnya
+layout linier, layout grid, atau layout relatif. Anda juga bisa mensubkelaskan kelas-kelas {@link android.view.View} dan
+{@link android.view.ViewGroup} (atau subkelas yang ada) untuk membuat widget dan
+layout Anda sendiri dan menerapkannya ke layout aktivitas Anda.</p>
+
+<p>Cara paling umum untuk mendefinisikan layout dengan menggunakan tampilan adalah dengan file layout XML yang disimpan dalam
+sumber daya aplikasi Anda. Dengan cara ini, Anda bisa memelihara desain antarmuka pengguna Anda secara terpisah dari
+kode yang mendefinisikan perilaku aktivitas. Anda bisa mengatur layout sebagai UI
+aktivitas Anda dengan {@link android.app.Activity#setContentView(int) setContentView()}, dengan meneruskan
+ID sumber daya untuk layout itu. Akan tetapi, Anda juga bisa membuat {@link android.view.View} baru dalam
+kode aktivitas dan membuat hierarki tampilan dengan menyisipkan {@link
+android.view.View} baru ke dalam {@link android.view.ViewGroup}, kemudian menggunakan layout itu dengan meneruskan akar
+{@link android.view.ViewGroup} ke {@link android.app.Activity#setContentView(View)
+setContentView()}.</p>
+
+<p>Untuk informasi tentang cara membuat antarmuka pengguna, lihat dokumentasi <a href="{@docRoot}guide/topics/ui/index.html">Antarmuka Pengguna</a>.</p>
+
+
+
+<h3 id="Declaring">Mendeklarasikan aktivitas dalam manifes</h3>
+
+<p>Anda harus mendeklarasikan aktivitas dalam file manifes agar file itu
+bisa diakses oleh sistem. Untuk mendeklarasikan aktivitas, bukalah file manifes Anda dan tambahkan sebuah elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
+sebagai anak elemen <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a>
+. Misalnya:</p>
+
+<pre>
+&lt;manifest ... &gt;
+  &lt;application ... &gt;
+      &lt;activity android:name=".ExampleActivity" /&gt;
+      ...
+  &lt;/application ... &gt;
+  ...
+&lt;/manifest &gt;
+</pre>
+
+<p>Ada beberapa atribut lain yang bisa Anda sertakan dalam elemen ini, untuk mendefinisikan properti
+misalnya label untuk aktivitas, ikon untuk aktivitas, atau tema untuk memberi gaya ke
+UI aktivitas. Atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">{@code android:name}</a>
+ adalah satu-satunya atribut yang diperlukan&mdash;atribut ini menetapkan nama kelas aktivitas. Setelah
+Anda mempublikasikan aplikasi, Anda tidak boleh mengubah nama ini, karena jika melakukannya, Anda bisa merusak
+sebagian fungsionalitas, misalnya pintasan aplikasi (bacalah posting blog berjudul <a href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things
+That Cannot Change</a>).</p>
+
+<p>Lihat acuan elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
+untuk informasi selengkapnya tentang cara mendeklarasikan aktivitas Anda dalam manifes.</p>
+
+
+<h4>Menggunakan filter intent</h4>
+
+<p>Elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
+&lt;activity&gt;}</a> juga bisa menetapkan berbagai filter intent&mdash;dengan menggunakan elemen <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code
+&lt;intent-filter&gt;}</a> &mdash;untuk mendeklarasikan cara komponen aplikasi lain
+mengaktifkannya.</p>
+
+<p>Bila Anda membuat aplikasi baru dengan Android SDK Tools, aktivitas stub
+yang dibuat untuk Anda secara otomatis menyertakan filter intent yang mendeklarasikan respons
+aktivitas pada tindakan "main" (utama) dan harus diletakkan dalam kategori "launcher"). Filter intent
+terlihat seperti ini:</p>
+
+<pre>
+&lt;activity android:name=".ExampleActivity" android:icon="@drawable/app_icon"&gt;
+    &lt;intent-filter&gt;
+        &lt;action android:name="android.intent.action.MAIN" /&gt;
+        &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
+    &lt;/intent-filter&gt;
+&lt;/activity&gt;
+</pre>
+
+<p>Elemen <a href="{@docRoot}guide/topics/manifest/action-element.html">{@code
+&lt;action&gt;}</a> menetapkan bahwa ini adalah titik masuk "main" ke aplikasi. Elemen <a href="{@docRoot}guide/topics/manifest/category-element.html">{@code
+&lt;category&gt;}</a> menetapkan bahwa aktivitas ini harus tercantum dalam launcher aplikasi
+sistem (untuk memungkinkan pengguna meluncurkan aktivitas ini).</p>
+
+<p>Jika Anda bermaksud agar aplikasi dimuat dengan sendirinya dan tidak memperbolehkan aplikasi lain
+mengaktifkan aktivitasnya, maka Anda tidak memerlukan filter intent lain. Hanya satu aktivitas yang boleh
+memiliki tindakan "main" dan kategori "launcher", seperti dalam contoh sebelumnya. Aktivitas yang
+tidak ingin Anda sediakan untuk aplikasi lain tidak boleh memiliki filter intent dan Anda bisa
+memulai sendiri aktivitas dengan menggunakan intent secara eksplisit (seperti dibahas di bagian berikut).</p>
+
+<p>Akan tetapi, jika ingin aktivitas Anda merespons intent implisit yang dikirim dari
+aplikasi lain (dan aplikasi Anda sendiri), maka Anda harus mendefinisikan filter intent tambahan untuk
+aktivitas. Untuk masing-masing tipe intent yang ingin direspons, Anda harus menyertakan sebuah <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code
+&lt;intent-filter&gt;}</a> yang menyertakan elemen
+<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code
+&lt;action&gt;}</a> dan, opsional, sebuah elemen <a href="{@docRoot}guide/topics/manifest/category-element.html">{@code
+&lt;category&gt;}</a> dan/atau elemen <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code
+&lt;data&gt;}</a>. Elemen-elemen ini menetapkan tipe intent yang bisa
+direspons oleh aktivitas Anda.</p>
+
+<p>Untuk informasi selengkapnya tentang cara aktivitas Anda merespons intent, lihat dokumen <a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter Intent</a>.
+</p>
+
+
+
+<h2 id="StartingAnActivity">Memulai Aktivitas</h2>
+
+<p>Anda bisa memulai aktivitas lain dengan memanggil {@link android.app.Activity#startActivity
+  startActivity()}, dengan meneruskan sebuah {@link android.content.Intent} yang menjelaskan aktivitas
+  yang ingin Anda mulai. Intent menetapkan aktivitas persis yang ingin Anda mulai atau menjelaskan
+  tipe tindakan yang ingin Anda lakukan (dan sistem akan memilih aktivitas yang sesuai untuk Anda,
+yang bahkan
+  bisa berasal dari aplikasi berbeda). Intent juga bisa membawa sejumlah kecil data untuk
+  digunakan oleh aktivitas yang dimulai.</p>
+
+<p>Saat bekerja dalam aplikasi sendiri, Anda nanti akan sering meluncurkan aktivitas yang dikenal saja.
+ Anda bisa melakukannya dengan membuat intent yang mendefinisikan secara eksplisit aktivitas yang ingin Anda mulai,
+dengan menggunakan nama kelas. Misalnya, beginilah cara satu aktivitas memulai aktivitas lain bernama {@code
+SignInActivity}:</p>
+
+<pre>
+Intent intent = new Intent(this, SignInActivity.class);
+startActivity(intent);
+</pre>
+
+<p>Akan tetapi, aplikasi Anda mungkin juga perlu melakukan beberapa tindakan, misalnya mengirim email,
+  pesan teks, atau pembaruan status, dengan menggunakan data dari aktivitas Anda. Dalam hal ini, aplikasi Anda mungkin
+ tidak memiliki aktivitasnya sendiri untuk melakukan tindakan tersebut, sehingga Anda bisa memanfaatkan aktivitas
+  yang disediakan oleh aplikasi lain pada perangkat, yang bisa melakukan tindakan itu untuk Anda. Inilah saatnya
+intent benar-benar berharga&mdash;Anda bisa membuat intent yang menjelaskan tindakan yang ingin
+dilakukan dan sistem
+  akan meluncurkan aktivitas yang tepat dari aplikasi lain. Jika ada
+  beberapa aktivitas yang bisa menangani intent itu, pengguna bisa memilih aktivitas yang akan digunakan. Misalnya,
+  jika Anda ingin memperbolehkan pengguna mengirim pesan email, Anda bisa membuat
+  intent berikut:</p>
+
+<pre>
+Intent intent = new Intent(Intent.ACTION_SEND);
+intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
+startActivity(intent);
+</pre>
+
+<p>Ekstra {@link android.content.Intent#EXTRA_EMAIL} yang ditambahkan ke intent adalah sebuah larik string
+  alamat email yang menjadi tujuan pengiriman email. Bila aplikasi email merespons intent ini,
+ aplikasi itu akan membaca larik string yang disediakan dalam ekstra dan meletakkannya dalam bidang "to"
+  pada formulir penulisan email. Dalam situasi ini, aktivitas aplikasi email dimulai dan bila
+  pengguna selesai, aktivitas Anda akan dilanjutkan.</p>
+
+
+
+
+<h3 id="StartingAnActivityForResult">Memulai aktivitas agar berhasil</h3>
+
+<p>Kadang-kadang, Anda mungkin ingin menerima hasil dari aktivitas yang Anda mulai. Dalam hal itu,
+  mulailah aktivitas dengan memanggil {@link android.app.Activity#startActivityForResult
+  startActivityForResult()} (sebagai ganti {@link android.app.Activity#startActivity
+  startActivity()}). Untuk menerima hasil dari
+aktivitas selanjutnya nanti, implementasikan metode callback {@link android.app.Activity#onActivityResult onActivityResult()}
+. Bila aktivitas selanjutnya selesai, aktivitas akan mengembalikan hasil dalam {@link
+android.content.Intent} kepada metode {@link android.app.Activity#onActivityResult onActivityResult()}
+Anda.</p>
+
+<p>Misalnya, mungkin Anda ingin pengguna mengambil salah satu kontaknya, sehingga aktivitas Anda bisa
+melakukan sesuatu dengan informasi dalam kontak itu. Begini caranya membuat intent tersebut dan
+menangani hasilnya:</p>
+
+<pre>
+private void pickContact() {
+    // Create an intent to "pick" a contact, as defined by the content provider URI
+    Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
+    startActivityForResult(intent, PICK_CONTACT_REQUEST);
+}
+
+&#64;Override
+protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+    // If the request went well (OK) and the request was PICK_CONTACT_REQUEST
+    if (resultCode == Activity.RESULT_OK &amp;&amp; requestCode == PICK_CONTACT_REQUEST) {
+        // Perform a query to the contact's content provider for the contact's name
+        Cursor cursor = getContentResolver().query(data.getData(),
+        new String[] {Contacts.DISPLAY_NAME}, null, null, null);
+        if (cursor.moveToFirst()) { // True if the cursor is not empty
+            int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
+            String name = cursor.getString(columnIndex);
+            // Do something with the selected contact's name...
+        }
+    }
+}
+</pre>
+
+<p>Contoh ini menunjukkan logika dasar yang harus Anda gunakan dalam metode {@link
+android.app.Activity#onActivityResult onActivityResult()} Anda untuk menangani
+hasil aktivitas. Syarat pertama memeriksa apakah permintaan berhasil&mdash;jika ya, maka
+ {@code resultCode} akan berupa {@link android.app.Activity#RESULT_OK}&mdash;dan apakah permintaan
+yang direspons hasil ini dikenal&mdash;dalam hal ini, {@code requestCode} cocok dengan
+parameter kedua yang dikirim dengan {@link android.app.Activity#startActivityForResult
+startActivityForResult()}. Dari sana, kode akan menangani hasil aktivitas dengan membuat query
+data yang dihasilkan dalam{@link android.content.Intent} (parameter {@code data}).</p>
+
+<p>Yang terjadi adalah {@link
+android.content.ContentResolver} melakukan query terhadap penyedia konten, yang menghasilkan
+{@link android.database.Cursor} yang memperbolehkan data query dibaca. Untuk informasi selengkapnya, lihat dokumen
+<a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Konten</a>.</p>
+
+<p>Untuk informasi selengkapnya tentang menggunakan intent, lihat dokumen <a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter
+Intent</a>.</p>
+
+
+<h2 id="ShuttingDown">Mematikan Aktivitas</h2>
+
+<p>Anda bisa mematikan aktivitas dengan memanggil metode {@link android.app.Activity#finish
+finish()}-nya. Anda juga bisa mematikan aktivitas terpisah yang sebelumnya Anda mulai dengan memanggil
+{@link android.app.Activity#finishActivity finishActivity()}.</p>
+
+<p class="note"><strong>Catatan:</strong> Pada umumnya, Anda tidak boleh secara eksplisit mengakhiri aktivitas
+dengan menggunakan metode-metode ini. Seperti yang dibahas di bagian berikut tentang daur hidup aktivitas,
+sistem Android mengelola hidup aktivitas untuk Anda, sehingga Anda tidak perlu menyelesaikan sendiri
+aktivitas tersebut. Memanggil metode-metode ini bisa berpengaruh negatif pada pengalaman
+pengguna yang diharapkan dan hanya boleh digunakan bila Anda benar-benar tidak ingin pengguna kembali ke
+instance aktivitas ini.</p>
+
+
+<h2 id="Lifecycle">Mengelola Daur Hidup Aktivitas</h2>
+
+<p>Mengelola daur hidup aktivitas dengan mengimplementasikan metode-metode callback sangat
+penting untuk mengembangkan
+aplikasi yang kuat dan fleksibel. Daur hidup aktivitas dipengaruhi langsung oleh kaitannya dengan
+aktivitas lain, tugasnya, serta back-stack.</p>
+
+<p>Pada dasarnya, sebuah aktivitas bisa berada dalam tiga status:</p>
+
+<dl>
+  <dt><i>Dilanjutkan</i></dt>
+    <dd>Aktivitas berada di latar depan layar dan mendapatkan fokus pengguna. (Status ini
+kadang-kadang disebut juga dengan "running" (berjalan).)</dd>
+
+  <dt><i>Dihentikan sementara</i></dt>
+    <dd>Aktivitas lain berada di latar depan dan mendapat fokus, namun aktivitas ini masih terlihat. Yakni,
+aktivitas lain terlihat di atas aplikasi ini dan aktivitas itu setengah transparan atau tidak
+menuutpi seluruh layar. Aktivitas yang dihentikan sementara adalah benar-benar hidup (objek {@link android.app.Activity}
+dipertahankan dalam memori, objek itu memelihara semua informasi status dan anggota, dan tetap dikaitkan dengan
+window manager), namun bisa dimatikan oleh sistem dalam situasi memori sangat rendah.</dd>
+
+  <dt><i>Dihentikan</i></dt>
+    <dd>Aktivitas ditutupi sepenuhnya oleh aktivitas lain (aktivitas sekarang berada di
+"latar belakang"). Aktivitas yang dihentikan juga masih hidup (objek {@link android.app.Activity}
+dipertahankan dalam memori, objek itu menjaga semua informasi status dan anggota, namun <em>tidak</em>
+dikaitkan dengan window manager). Akan tetapi, aktivitas tidak lagi terlihat bagi pengguna dan
+bisa dimatikan oleh sistem bila memori diperlukan di lain.</dd>
+</dl>
+
+<p>Jika aktivitas dihentikan sementara atau dihentikan, sistem bisa mengeluarkannya dari memori baik dengan memintanya agar
+diakhiri (memanggil metode {@link android.app.Activity#finish finish()}-nya), atau sekadar mematikan
+prosesnya.  Bila dibuka lagi (setelah diakhiri atau dimatikan), aktivitas harus dibuat dari
+awal.</p>
+
+
+
+<h3 id="ImplementingLifecycleCallbacks">Mengimplementasikan callback daur hidup</h3>
+
+<p>Saat bertransisi ke dalam dan ke luar berbagai status yang dijelaskan di atas, aktivitas diberi tahu
+melalui berbagai metode callback. Semua metode callback adalah sangkutan yang
+bisa Anda kesampingkan untuk melakukan pekerjaan yang sesuai saat status aktivitas Anda berubah. Aktivitas skeleton
+berikut menyertakan setiap metode daur hidup mendasar:</p>
+
+
+<pre>
+public class ExampleActivity extends Activity {
+    &#64;Override
+    public void {@link android.app.Activity#onCreate onCreate}(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        // The activity is being created.
+    }
+    &#64;Override
+    protected void {@link android.app.Activity#onStart onStart()} {
+        super.onStart();
+        // The activity is about to become visible.
+    }
+    &#64;Override
+    protected void {@link android.app.Activity#onResume onResume()} {
+        super.onResume();
+        // The activity has become visible (it is now "resumed").
+    }
+    &#64;Override
+    protected void {@link android.app.Activity#onPause onPause()} {
+        super.onPause();
+        // Another activity is taking focus (this activity is about to be "paused").
+    }
+    &#64;Override
+    protected void {@link android.app.Activity#onStop onStop()} {
+        super.onStop();
+        // The activity is no longer visible (it is now "stopped")
+    }
+    &#64;Override
+    protected void {@link android.app.Activity#onDestroy onDestroy()} {
+        super.onDestroy();
+        // The activity is about to be destroyed.
+    }
+}
+</pre>
+
+<p class="note"><strong>Catatan:</strong> Implementasi Anda terhadap metode-metode daur hidup ini harus
+selalu memanggil implementasi superkelas sebelum melakukan pekerjaan apa pun, seperti yang ditampilkan dalam contoh-contoh di atas.</p>
+
+<p>Bersama-sama, semua metode ini mendefinisikan seluruh daur hidup sebuah aktivitas. Dengan mengimplementasikan
+metode-metode ini, Anda bisa memantau tiga loop tersarang (nested loop) dalam daur hidup aktivitas: </p>
+
+<ul>
+<li><b>Seluruh masa hidup</b> aktivitas berlangsung antara panggilan ke {@link
+android.app.Activity#onCreate onCreate()} dan panggilan ke {@link
+android.app.Activity#onDestroy}. Aktivitas Anda harus melakukan penyiapan
+status "global" (misalnya mendefinisikan layout) dalam {@link android.app.Activity#onCreate onCreate()}, dan
+melepas semua sisa sumber daya dalam {@link android.app.Activity#onDestroy}. Misalnya, jika
+aktivitas Anda memiliki sebuah thread yang berjalan di latar belakang untuk mengunduh data dari jaringan, aktivitas itu bisa membuat
+thread itu dalam {@link android.app.Activity#onCreate onCreate()} kemudian menghentikan thread dalam {@link
+android.app.Activity#onDestroy}.</li>
+
+<li><p><b>Masa pakai terlihat</b> (visible lifetime) aktivitas berlangsung antara panggilan ke {@link
+android.app.Activity#onStart onStart()} dan panggilan ke {@link
+android.app.Activity#onStop onStop()}. Selama ini, pengguna bisa melihat aktivitas
+pada layar dan berinteraksi dengannya. Misalnya, {@link android.app.Activity#onStop onStop()} dipanggil
+bila sebuah aktivitas baru dimulai dan aktivitas ini tidak lagi terlihat. Di antara dua metode ini, Anda bisa
+memelihara sumber daya yang diperlukan untuk menampilkan aktivitas kepada pengguna. Misalnya, Anda bisa mendaftarkan sebuah
+{@link android.content.BroadcastReceiver} dalam {@link
+android.app.Activity#onStart onStart()} untuk memantau perubahan yang berdampak pada UI Anda, dan mencabut pendaftarannya
+dalam {@link android.app.Activity#onStop onStop()} bila pengguna tidak bisa lagi melihat apa yang sedang Anda
+tampilkan. Sistem bisa memanggil {@link android.app.Activity#onStart onStart()} dan {@link
+android.app.Activity#onStop onStop()} beberapa kali selama masa pakai aktivitas, sambil
+aktivitas berganti-ganti antara terlihat dan tersembunyi bagi pengguna.</p></li>
+
+<li><p><b>Masa pakai latar depan</b> aktivitas berlangsung antara panggilan ke {@link
+android.app.Activity#onResume onResume()} dan panggilan ke {@link android.app.Activity#onPause
+onPause()}. Selama waktu ini, aktivitas berada di depan semua aktivitas lain pada layar dan mendapatkan
+fokus input pengguna.  Aktivitas bisa sering bertransisi ke dalam dan ke luar latar depan&mdash;misalnya,
+ {@link android.app.Activity#onPause onPause()} dipanggil bila perangkat masuk ke mode tidur atau
+bila dialog muncul. Karena status ini bisa sering bertransisi, kode dalam dua metode ini harus
+cukup ringan untuk menghindari transisi lamban yang membuat pengguna menunggu.</p></li>
+</ul>
+
+<p>Gambar 1 mengilustrasikan loop dan path yang mungkin diambil sebuah aktivitas di antara status-status.
+Persegi panjang mewakili metode callback yang bisa Anda implementasikan untuk melakukan operasi saat
+aktivitas bertransisi di antara status. <p>
+
+<img src="{@docRoot}images/activity_lifecycle.png" alt="" />
+<p class="img-caption"><strong>Gambar 1.</strong> Daur hidup aktivitas.</p>
+
+<p>Metode-metode callback daur hidup yang sama tercantum dalam tabel 1, yang menjelaskan setiap metode callback
+secara lebih detail dan menentukan lokasinya masing-masing dalam
+daur hidup aktivitas keseluruhan, termasuk apakah sistem bisa mematikan aktivitas setelah
+metode callback selesai.</p>
+
+<p class="table-caption"><strong>Tabel 1.</strong> Rangkuman metode callback
+daur hidup aktivitas.</p>
+
+<table border="2" width="85%" frame="hsides" rules="rows">
+<colgroup align="left" span="3"></colgroup>
+<colgroup align="left"></colgroup>
+<colgroup align="center"></colgroup>
+<colgroup align="center"></colgroup>
+
+<thead>
+<tr><th colspan="3">Metode</th> <th>Keterangan</th> <th>Bisa dimatikan setelahnya?</th> <th>Berikutnya</th></tr>
+</thead>
+
+<tbody>
+<tr>
+  <td colspan="3" align="left"><code>{@link android.app.Activity#onCreate onCreate()}</code></td>
+  <td>Dipanggil saat aktivitas pertama kali dibuat.
+      Di sinilah Anda harus melakukan semua persiapan statis normal &mdash;
+      membuat tampilan, mengikat data ke daftar, dan sebagainya.  Metode ini diberi
+      sebuah objek Bundle yang berisi status aktivitas sebelumnya, jika
+      status itu tertangkap (lihat <a href="#actstate">Menyimpan Status Aktivitas</a>,
+      nanti).
+      <p>Selalu diikuti oleh {@code onStart()}.</p></td>
+  <td align="center">Tidak</td>
+      <td align="center">{@code onStart()}</td>
+</tr>
+
+<tr>
+   <td rowspan="5" style="border-left: none; border-right: none;">&nbsp;&nbsp;&nbsp;&nbsp;</td>
+   <td colspan="2" align="left"><code>{@link android.app.Activity#onRestart
+onRestart()}</code></td>
+   <td>Dipanggil setelah aktivitas dihentikan, tepat sebelum
+       dimulai lagi.
+       <p>Selalu diikuti oleh {@code onStart()}</p></td>
+   <td align="center">Tidak</td>
+   <td align="center">{@code onStart()}</td>
+</tr>
+
+<tr>
+   <td colspan="2" align="left"><code>{@link android.app.Activity#onStart onStart()}</code></td>
+   <td>Dipanggil tepat sebelum aktivitas menjadi terlihat bagi pengguna.
+       <p>Diikuti oleh {@code onResume()} jika aktivitas maju
+       ke latar depan, atau {@code onStop()} jika menjadi tersembunyi.</p></td>
+    <td align="center">Tidak</td>
+    <td align="center">{@code onResume()} <br/>atau<br/> {@code onStop()}</td>
+</tr>
+
+<tr>
+   <td rowspan="2" style="border-left: none;">&nbsp;&nbsp;&nbsp;&nbsp;</td>
+   <td align="left"><code>{@link android.app.Activity#onResume onResume()}</code></td>
+   <td>Dipanggil tepat sebelum aktivitas mulai
+       berinteraksi dengan pengguna.  Pada titik ini, aktivitas berada di
+       puncak tumpukan aktivitas, dengan input pengguna menuju kepadanya.
+       <p>Selalu diikuti oleh {@code onPause()}.</p></td>
+   <td align="center">Tidak</td>
+   <td align="center">{@code onPause()}</td>
+</tr>
+
+<tr>
+   <td align="left"><code>{@link android.app.Activity#onPause onPause()}</code></td>
+   <td>Dipanggil bila sistem akan memulai pelanjutan
+       aktivitas lain.  Metode ini biasanya digunakan untuk menerapkan (commit) perubahan yang tidak tersimpan pada
+       data persisten, menghentikan animasi dan hal-hal lain yang mungkin menghabiskan
+       CPU, dan sebagainya.  Metode ini harus melakukan apa saja yang dilakukannya dengan sangat cepat, karena
+       aktivitas berikutnya tidak akan dilanjutkan hingga aktivitas ini kembali.
+       <p>Diikuti oleh {@code onResume()} jika aktivitas
+       kembali ke depan, atau oleh {@code onStop()} jika menjadi
+       tidak terlihat bagi pengguna.</td>
+   <td align="center"><strong style="color:#800000">Ya</strong></td>
+   <td align="center">{@code onResume()} <br/>atau<br/> {@code onStop()}</td>
+</tr>
+
+<tr>
+   <td colspan="2" align="left"><code>{@link android.app.Activity#onStop onStop()}</code></td>
+   <td>Dipanggil bila aktivitas tidak lagi terlihat bagi pengguna.  Hal ini
+       bisa terjadi karena aktivitas sedang dimusnahkan, atau karena aktivitas lain
+       (aktivitas yang ada atau yang baru) telah dilanjutkan dan sedang menutupinya.
+       <p>Diikuti oleh {@code onRestart()} jika
+       aktivitas kembali untuk berinteraksi dengan pengguna, atau oleh
+       {@code onDestroy()} jika aktivitas ini akan menghilang.</p></td>
+   <td align="center"><strong style="color:#800000">Ya</strong></td>
+   <td align="center">{@code onRestart()} <br/>atau<br/> {@code onDestroy()}</td>
+</tr>
+
+<tr>
+   <td colspan="3" align="left"><code>{@link android.app.Activity#onDestroy
+onDestroy()}</code></td>
+   <td>Dipanggil sebelum aktivitas dimusnahkan.  Inilah panggilan terakhir
+       yang akan diterima aktivitas.  Metode ini bisa dipanggil karena
+       aktivitas selesai (seseorang memanggil <code>{@link android.app.Activity#finish
+       finish()}</code> padanya), atau karena sistem memusnahkan sementara
+       instance aktivitas ini untuk menghemat tempat.  Anda bisa membedakan
+       kedua skenario ini dengan metode <code>{@link
+       android.app.Activity#isFinishing isFinishing()}</code>.</td>
+   <td align="center"><strong style="color:#800000">Ya</strong></td>
+   <td align="center"><em>tidak ada</em></td>
+</tr>
+</tbody>
+</table>
+
+<p>Kolom berlabel "Bisa dimatikan setelahnya?" menunjukkan apakah sistem bisa
+atau tidak mematikan proses yang menjadi host aktivitas kapan saja <em>setelah metode kembali</em>, tanpa
+menjalankan baris lain pada kode aktivitas.  Tiga metode ini ditandai "ya": ({@link
+android.app.Activity#onPause
+onPause()}, {@link android.app.Activity#onStop onStop()}, dan {@link android.app.Activity#onDestroy
+onDestroy()}). Karena {@link android.app.Activity#onPause onPause()} adalah yang pertama
+dari tiga, begitu aktivitas dibuat, {@link android.app.Activity#onPause onPause()} adalah
+metode terakhir yang dipastikan akan dipanggil sebelum proses <em>bisa</em> dimatikan&mdash;jika
+sistem harus memulihkan memori dalam keadaan darurat, maka {@link
+android.app.Activity#onStop onStop()} dan {@link android.app.Activity#onDestroy onDestroy()} mungkin
+tidak dipanggil. Karena itu, Anda harus menggunakan {@link android.app.Activity#onPause onPause()} untuk menulis
+data persisten yang penting (misalnya hasil edit pengguna) ke penyimpanan. Akan tetapi, Anda harus selektif dalam hal
+informasi yang harus dipertahankan selama {@link android.app.Activity#onPause onPause()}, karena setiap
+prosedur pemblokiran dalam metode ini akan memblokir transisi ke aktivitas berikutnya dan memperlambat
+pengalaman pengguna.</p>
+
+<p> Metode-metode yang ditandai "Tidak" dalam kolom <b>Bisa dimatikan</b> melindungi proses yang menjadi host
+aktivitas dari dimatikan sejak saat metode dipanggil.  Jadi, aktivitas bisa dimatikan
+sejak {@link android.app.Activity#onPause onPause()} kembali hingga waktu
+{@link android.app.Activity#onResume onResume()} dipanggil. Aktivitas tidak akan lagi bisa dimatikan hingga
+{@link android.app.Activity#onPause onPause()} dipanggil lagi dan kembali. </p>
+
+<p class="note"><strong>Catatan:</strong> Aktivitas yang tidak "bisa dimatikan" secara teknis oleh
+definisi dalam tabel 1 masih bisa dimatikan oleh sistem&mdash;namun itu hany terjadi dalam
+situasi ekstrem bila tidak ada jalan lain. Kapan aktivitas bisa dimatikan
+akan dibahas selengkapnya dalam dokumen <a href="{@docRoot}guide/components/processes-and-threads.html">Proses dan
+Threading</a>.</p>
+
+
+<h3 id="SavingActivityState">Menyimpan status aktivitas</h3>
+
+<p>Pengantar untuk <a href="#Lifecycle">Mengelola Daur Hidup Aktivitas</a> secara ringkas menyebutkan
+bahwa
+bila aktivitas dihentikan sementara atau dihentikan, status aktivitas akan dipertahankan. Hal itu terjadi karena
+objek {@link android.app.Activity} masih ditahan dalam memori saat aktivitas dihentikan sementara atau
+dihentikan&mdash;semua informasi tentang anggota dan statusnya saat ini masih hidup. Jadi, setiap perubahan
+yang dibuat pengguna dalam aktivitas akan dipertahankan sehingga bila aktivitas kembali ke
+latar depan (bila "dilanjutkan"), perubahan itu masih ada.</p>
+
+<p>Akan tetapi, bila sistem memusnahkan aktivitas untuk memulihkan memori, objek {@link
+android.app.Activity} akan dimusnahkan, sehingga sistem tidak bisa sekadar melanjutkan aktivitas dengan status
+tidak berubah. Sebagai gantinya, sistem harus membuat ulang objek {@link android.app.Activity} jika pengguna
+menyusuri kembali ke aktivitas tersebut. Namun, pengguna tidak menyadari
+bahwa sistem memusnahkan aktivitas dan membuatnya kembali dan, karena itu, mungkin
+mengharapkan aktivitas untuk sama persis dengan sebelumnya. Dalam situasi ini, Anda bisa memastikan bahwa
+informasi penting tentang status aktivitas tetap terjaga dengan mengimplementasikan
+metode callback tambahan yang memungkinkan Anda menyimpan informasi tentang status aktivitas: {@link
+android.app.Activity#onSaveInstanceState onSaveInstanceState()}.</p>
+
+<p>Sistem memanggil {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}
+sebelum membuat aktivitas rawan terhadap pemusnahan. Sistem meneruskan ke metode ini
+sebuah {@link android.os.Bundle} tempat Anda bisa menyimpan
+informasi status tentang aktivitas sebagai pasangan nama-nilai, dengan menggunakan metode-metode misalnya {@link
+android.os.Bundle#putString putString()} dan {@link
+android.os.Bundle#putInt putInt()}. Kemudian, jika sistem mematikan proses aplikasi Anda
+dan pengguna menyusuri kembali ke aktivitas tersebut, sistem akan membuat kembali aktivitas dan meneruskan
+{@link android.os.Bundle} ke {@link android.app.Activity#onCreate onCreate()} maupun {@link
+android.app.Activity#onRestoreInstanceState onRestoreInstanceState()}. Dengan menggunakan salah satu
+metode ini, Anda bisa mengekstrak status tersimpan dari {@link android.os.Bundle} dan memulihkan
+status aktivitas. Jika tidak ada informasi status untuk dipulihkan, maka {@link
+android.os.Bundle} yang diteruskan kepada adalah Anda null (yang akan terjadi bila aktivitas dibuat untuk
+pertama kali).</p>
+
+<img src="{@docRoot}images/fundamentals/restore_instance.png" alt="" />
+<p class="img-caption"><strong>Gambar 2.</strong> Ada dua cara yang bisa digunakan aktivitas untuk kembali ke fokus pengguna
+dengan status tetap: aktivitas dimusnahkan, kemudian dibuat kembali, dan aktivitas harus memulihkan
+status yang disimpan sebelumnya, atau aktivitas dihentikan, kemudian dilanjutkan dengan status aktivitas
+tetap.</p>
+
+<p class="note"><strong>Catatan:</strong> Tidak ada jaminan bahwa {@link
+android.app.Activity#onSaveInstanceState onSaveInstanceState()} akan dipanggil sebelum
+aktivitas Anda dimusnahkan, karena bisa saja terjadi aktivitas tidak perlu menyimpan status
+(misalnya saat pengguna meninggalkan aktivitas Anda dengan menggunakan tombol <em>Back</em>, karena pengguna menutup aktivitas
+secara eksplisit
+). Jika sistem memanggil {@link android.app.Activity#onSaveInstanceState
+onSaveInstanceState()}, ini akan dilakukan sebelum {@link
+android.app.Activity#onStop onStop()} dan mungkin sebelum {@link android.app.Activity#onPause
+onPause()}.</p>
+
+<p>Akan tetapi, sekalipun Anda tidak melakukan apa-apa dan tidak mengimplementasikan {@link
+android.app.Activity#onSaveInstanceState onSaveInstanceState()}, beberapa status aktivitas
+akan dipulihkan oleh implementasi default {@link
+android.app.Activity#onSaveInstanceState onSaveInstanceState()} dalam kelas {@link android.app.Activity}. Khususnya,
+implementasi default akan memanggil metode {@link
+android.view.View#onSaveInstanceState onSaveInstanceState()} yang sesuai untuk setiap {@link
+android.view.View} dalam layout, yang memungkinkan setiap tampilan untuk memberi informasi tentang dirinya
+yang harus disimpan. Hampir setiap widget dalam kerangka kerja Android mengimplementasikan metode ini
+sebagaimana mestinya, sehingga setiap perubahan yang terlihat pada UI akan disimpan dan dipulihkan secara otomatis bila
+aktivitas Anda dibuat kembali. Misalnya, widget {@link android.widget.EditText} menyimpan teks apa saja
+yang dimasukkan oleh pengguna dan widget {@link android.widget.CheckBox} menyimpan baik teks itu diperiksa maupun
+tidak. Satu-satunya pekerjaan yang Anda perlukan adalah memberikan ID unik (dengan atribut <a href="{@docRoot}guide/topics/resources/layout-resource.html#idvalue">{@code android:id}</a>
+) untuk masing-masing widget yang ingin disimpan statusnya. Jika widget tidak memiliki ID, maka sistem
+tidak bisa menyimpan statusnya.</p>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<p>Anda juga bisa menghentikan secara eksplisit sebuah tampilan dalam layout Anda agar tidak menyimpan statusnya dengan mengatur atribut
+{@link android.R.attr#saveEnabled android:saveEnabled} ke {@code "false"} atau dengan memanggil
+metode {@link android.view.View#setSaveEnabled setSaveEnabled()}. Biasanya, Anda tidak boleh
+menonaktifkannya, namun Anda boleh melakukannya jika ingin memulihkan status UI aktivitas secara berbeda.</p>
+</div>
+</div>
+
+<p>Walaupun implementasi default {@link
+android.app.Activity#onSaveInstanceState onSaveInstanceState()} menyimpan informasi yang berguna tentang
+UI aktivitas, Anda mungkin masih perlu mengesampingkannya untuk menyimpan informasi tambahan.
+Misalnya, Anda mungkin perlu menyimpan nilai-nilai anggota yang berubah selama masa pakai aktivitas (yang
+mungkin berkorelasi dengan nilai-nilai yang dipulihkan dalam UI, namun anggota-anggota yang menyimpan nilai-nilai UI itu tidak
+dipulihkan, secara default).</p>
+
+<p>Karena implementasi default {@link
+android.app.Activity#onSaveInstanceState onSaveInstanceState()} membantu menyimpan status UI, jika
+Anda mengesampingkan metode ini untuk menyimpan informasi tambahan status, Anda harus selalu memanggil
+implementasi superkelas {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}
+sebelum melakukan pekerjaan apa pun. Demikian pula, Anda juga harus memanggil implementasi superkelas {@link
+android.app.Activity#onRestoreInstanceState onRestoreInstanceState()} jika Anda mengesampingkannya, sehingga
+implementasi default bisa memulihkan status tampilan.</p>
+
+<p class="note"><strong>Catatan:</strong> Karena {@link android.app.Activity#onSaveInstanceState
+onSaveInstanceState()} tidak dijamin
+akan dipanggil, Anda harus menggunakannya hanya untuk mencatat status aktivitas sementara (transient) (status
+UI)&mdash;Anda tidak boleh menggunakannya untuk menyimpan data persisten.  Sebagai gantinya, Anda harus menggunakan {@link
+android.app.Activity#onPause onPause()} untuk menyimpan data persisten (misalnya data yang harus disimpan
+ke database) saat pengguna meninggalkan aktivitas.</p>
+
+<p>Salah satu cara yang baik untuk menguji kemampuan aplikasi dalam memulihkan statusnya adalah cukup dengan memutar
+perangkat sehingga orientasi layarnya berubah. Bila orientasi layar berubah, sistem
+akan memusnahkan dan membuat kembali aktivitas untuk menerapkan sumber daya alternatif yang mungkin tersedia
+untuk konfigurasi layar baru. Karena alasan ini saja, sangat penting bahwa aktivitas Anda
+memulihkan statusnya secara lengkap saat dibuat kembali, karena pengguna memutar layar secara rutin saat
+menggunakan aplikasi.</p>
+
+
+<h3 id="ConfigurationChanges">Menangani perubahan konfigurasi</h3>
+
+<p>Sebagian konfigurasi perangkat bisa berubah saat runtime (misalnya orientasi layar, ketersediaan keyboard
+, dan bahasa). Bila terjadi perubahan demikian, Android akan membuat kembali aktivitas yang berjalan
+(sistem akan memanggil {@link android.app.Activity#onDestroy}, kemudian segera memanggil {@link
+android.app.Activity#onCreate onCreate()}). Perilaku ini
+didesain untuk membantu aplikasi Anda menyesuaikan diri dengan konfigurasi baru dengan cara memuat ulang
+aplikasi Anda secara otomatis dengan sumber daya alternatif yang telah Anda sediakan (misalnya layout yang berbeda untuk
+layar orientasi dan ukuran yang berbeda).</p>
+
+<p>Jika Anda mendesain aktivitas dengan benar untuk menangani restart karena perubahan orientasi layar dan
+memulihkan status aktivitas seperti yang dijelaskan di atas, aplikasi Anda akan lebih tahan terhadap
+kejadian tidak terduga lainnya dalam daur hidup aktivitas.</p>
+
+<p>Cara terbaik menangani restart tersebut adalah
+  menyimpan dan memulihkan status aktivitas Anda dengan menggunakan {@link
+  android.app.Activity#onSaveInstanceState onSaveInstanceState()} dan {@link
+android.app.Activity#onRestoreInstanceState onRestoreInstanceState()} (atau {@link
+android.app.Activity#onCreate onCreate()}), seperti yang dibahas di bagian sebelumnya.</p>
+
+<p>Untuk informasi selengkapnya tentang konfigurasi perubahan yang terjadi saat program berjalan dan cara menanganinya
+, bacalah panduan untuk <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Menangani
+Perubahan Runtime</a>.</p>
+
+
+
+<h3 id="CoordinatingActivities">Mengoordinasikan aktivitas</h3>
+
+ <p>Bila suatu aktivitas memulai aktivitas lain, keduanya akan mengalami transisi daur hidup. Aktivitas pertama
+akan berhenti sementara dan berhenti sama sekali (walau tidak akan berhenti jika masih terlihat di latar belakang), saat
+aktivitas lain dibuat. Jika aktivitas-aktivitas ini berbagi data yang disimpan ke disk atau di tempat lain, Anda perlu
+memahami bahwa aktivitas pertama tidak dihentikan sepenuhnya sebelum aktivitas kedua dibuat.
+Sebagai gantinya, proses akan memulai aktivitas kedua secara tumpang tindih dengan proses penghentian
+aktivitas pertama.</p>
+
+<p>Urutan callback daur hidup didefinisikan dengan baik, khususnya bila kedua aktivitas berada dalam
+proses yang sama dan salah satunya memulai yang lain. Berikut ini adalah urutan operasi yang terjadi bila Aktivitas
+A memulai Aktivitas B: </p>
+
+<ol>
+<li>Metode {@link android.app.Activity#onPause onPause()} Aktivitas A berjalan.</li>
+
+<li>Metode-metode {@link android.app.Activity#onCreate onCreate()}, {@link
+android.app.Activity#onStart onStart()}, dan {@link android.app.Activity#onResume onResume()}
+Aktivitas B berjalan secara berurutan. (Aktivitas B sekarang mendapatkan fokus pengguna.)</li>
+
+<li>Kemudian, jika Aktivitas A tidak lagi terlihat di layar, metode {@link
+android.app.Activity#onStop onStop()}-nya akan dijalankan.</li>
+</ol>
+
+ <p>Urutan callback daur hidup yang bisa diramalkan ini memungkinkan Anda mengelola transisi
+informasi dari satu aktivitas ke aktivitas lainnya. Misalnya, jika Anda harus menulis ke database saat
+aktivitas pertama berhenti agar aktivitas berikutnya bisa membacanya, maka Anda harus menulis ke
+database selama {@link android.app.Activity#onPause onPause()} sebagai ganti selama {@link
+android.app.Activity#onStop onStop()}.</p>
+
+<!--
+<h2>Beginner's Path</h2>
+
+<p>For more information about how Android maintains a history of activities and
+enables user multitasking, continue with the <b><a
+href="{@docRoot}guide/components/tasks-and-back-stack.html">Tasks and Back
+Stack</a></b> document.</p>
+-->
diff --git a/docs/html-intl/intl/id/guide/components/bound-services.jd b/docs/html-intl/intl/id/guide/components/bound-services.jd
new file mode 100644
index 0000000..6e5e65a1
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/components/bound-services.jd
@@ -0,0 +1,658 @@
+page.title=Layanan Terikat
+parent.title=Layanan
+parent.link=services.html
+@jd:body
+
+
+<div id="qv-wrapper">
+<ol id="qv">
+<h2>Dalam dokumen ini</h2>
+<ol>
+  <li><a href="#Basics">Dasar-Dasar</a></li>
+  <li><a href="#Creating">Membuat Layanan Terikat</a>
+    <ol>
+      <li><a href="#Binder">Memperluas kelas Binder</a></li>
+      <li><a href="#Messenger">Menggunakan Messenger</a></li>
+    </ol>
+  </li>
+  <li><a href="#Binding">Mengikat ke Layanan</a></li>
+  <li><a href="#Lifecycle">Mengelola Daur Hidup Layanan Terikat</a></li>
+</ol>
+
+<h2>Kelas-kelas utama</h2>
+<ol>
+  <li>{@link android.app.Service}</li>
+  <li>{@link android.content.ServiceConnection}</li>
+  <li>{@link android.os.IBinder}</li>
+</ol>
+
+<h2>Contoh</h2>
+<ol>
+  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
+      RemoteService}</a></li>
+  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
+      LocalService}</a></li>
+</ol>
+
+<h2>Lihat juga</h2>
+<ol>
+  <li><a href="{@docRoot}guide/components/services.html">Layanan</a></li>
+</ol>
+</div>
+
+
+<p>Layanan terikat adalah server di antarmuka klien-server. Layanan terikat memungkinkan komponen-komponen
+(seperti aktivitas) untuk diikat ke layanan, mengirim permintaan, menerima respons, dan bahkan melakukan
+komunikasi antarproses (IPC). Layanan terikat biasanya hidup hanya saat melayani
+komponen aplikasi lain dan tidak berjalan di latar belakang terus-menerus.</p>
+
+<p>Dokumen ini menampilkan cara membuat layanan terikat, termasuk cara mengikat
+ke layanan dari komponen aplikasi lain. Akan tetapi, Anda juga harus mengacu dokumen <a href="{@docRoot}guide/components/services.html">Layanan</a> untuk
+informasi tambahan tentang layanan secara umum, seperti cara menyampaikan pemberitahuan dari layanan, mengatur
+layanan agar berjalan di latar depan, dan lain-lain.</p>
+
+
+<h2 id="Basics">Dasar-Dasar</h2>
+
+<p>Layanan terikat adalah implementasi kelas {@link android.app.Service} yang memungkinkan
+aplikasi lain diikat padanya dan berinteraksi dengannya. Untuk menyediakan pengikatan bagi sebuah
+layanan, Anda harus mengimplementasikan metode callback {@link android.app.Service#onBind onBind()}. Metode ini
+menghasilkan objek {@link android.os.IBinder} yang mendefinisikan antarmuka pemprograman yang
+bisa digunakan klien untuk berinteraksi dengan layanan.</p>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+  <h3>Mengikat ke Layanan yang Sudah Dimulai</h3>
+
+<p>Seperti dibahas dalam dokumen <a href="{@docRoot}guide/components/services.html">Layanan</a>
+, Anda bisa membuat layanan yang dimulai sekaligus diikat. Yakni, layanan bisa
+dimulai dengan memanggil {@link android.content.Context#startService startService()}, yang memungkinkan
+layanan berjalan terus-menerus, dan juga membolehkan klien untuk mengikat ke layanan dengan memanggil {@link
+android.content.Context#bindService bindService()}.
+  <p>Jika Anda mengizinkan layanan dimulai dan diikat, lalu ketika layanan telah
+dimulai, sistem <em>tidak</em> menghapus layanan ketika semua klien melepas ikatan. Sebagai gantinya, Anda harus
+menghentikan layanan secara eksplisit, dengan memanggil {@link android.app.Service#stopSelf stopSelf()} atau {@link
+android.content.Context#stopService stopService()}.</p>
+
+<p>Walaupun Anda biasanya harus mengimplementasikan {@link android.app.Service#onBind onBind()}
+<em>atau</em> {@link android.app.Service#onStartCommand onStartCommand()}, kadang-kadang perlu
+mengimplementasikan keduanya. Misalnya, sebuah pemutar musik bisa merasakan manfaatnya karena layanannya boleh berjalan
+terus-menerus dan juga menyediakan pengikatan. Dengan cara ini, sebuah aktivitas bisa memulai layanan untuk memutar beberapa
+lagu dan musik terus dimainkan sekalipun pengguna meninggalkan aplikasi. Lalu, bila pengguna
+kembali ke aplikasi, aktivitas bisa mengikat ke layanan untuk mendapatkan kembali kontrol atas pemutaran.</p>
+
+<p>Pastikan membaca bagian tentang <a href="#Lifecycle">Mengelola Daur Hidup Layanan
+Terikat</a>, untuk informasi selengkapnya tentang daur hidup layanan saat menambahkan pengikatan ke
+layanan yang sudah dimulai.</p>
+</div>
+</div>
+
+<p>Klien bisa mengikat ke layanan dengan memanggil {@link android.content.Context#bindService
+bindService()}. Bila itu dilakukan, klien harus menyediakan implementasi {@link
+android.content.ServiceConnection}, yang memantau koneksi dengan layanan. Metode {@link
+android.content.Context#bindService bindService()} kembali dengan serta-merta tanpa sebuah nilai, namun
+bila sistem Android membuat koneksi antara klien
+dan layanan, sistem akan memanggil {@link
+android.content.ServiceConnection#onServiceConnected onServiceConnected()} pada {@link
+android.content.ServiceConnection} untuk mengirim {@link android.os.IBinder} yang
+bisa digunakan klien untuk berkomunikasi dengan layanan.</p>
+
+<p>Beberapa klien bisa terhubung ke layanan dengan serentak. Akan tetapi, sistem akan memanggil metode
+{@link android.app.Service#onBind onBind()} layanan Anda untuk mengambil {@link android.os.IBinder} hanya
+bila klien pertama mengikat. Sistem lalu memberikan {@link android.os.IBinder} yang sama ke setiap
+klien tambahan yang mengikat, tanpa memanggil {@link android.app.Service#onBind onBind()} lagi.</p>
+
+<p>Bila klien terakhir melepas ikatan dari layanan, sistem akan menghapus layanan (kecuali jika
+layanan juga dimulai oleh {@link android.content.Context#startService startService()}).</p>
+
+<p>Bila Anda mengimplementasikan layanan terikat, yang terpenting adalah mendefinisikan antarmuka
+yang dihasilkan metode callback {@link android.app.Service#onBind onBind()} Anda. Ada sedikit
+cara mendefinisikan antarmuka {@link android.os.IBinder} layanan Anda dan bagian berikut
+akan membahas masing-masing teknik.</p>
+
+
+
+<h2 id="Creating">Membuat Layanan Terikat</h2>
+
+<p>Saat membuat layanan yang menyediakan pengikatan, Anda harus menyediakan {@link android.os.IBinder}
+yang menyediakan antarmuka pemrograman yang bisa digunakan klien untuk berinteraksi dengan layanan. Ada
+tiga cara untuk mendefinisikan antarmuka:</p>
+
+<dl>
+  <dt><a href="#Binder">Memperluas kelas Binder</a></dt>
+  <dd>Jika layanan Anda bersifat privat untuk aplikasi Anda sendiri dan berjalan dalam proses yang sama dengan klien
+(biasanya), Anda harus membuat antarmuka dengan memperluas kelas {@link android.os.Binder}
+dan menghasilkan instance dari
+{@link android.app.Service#onBind onBind()}. Klien akan menerima {@link android.os.Binder} dan
+bisa menggunakannya untuk mengakses langsung metode publik yang tersedia dalam implementasi {@link android.os.Binder}
+atau bahkan {@link android.app.Service}.
+  <p>Inilah teknik yang lebih disukai bila layanan Anda sekadar pekerja latar belakang untuk aplikasi Anda
+sendiri. Satu-satunya alasan tidak membuat antarmuka dengan cara ini adalah karena
+layanan Anda akan digunakan oleh aplikasi lain atau pada proses-proses terpisah.</dd>
+
+  <dt><a href="#Messenger">Menggunakan Messenger</a></dt>
+  <dd>Jika antarmuka Anda perlu bekerja lintas proses, Anda bisa membuat
+antarmuka untuk layanan dengan {@link android.os.Messenger}. Dengan cara ini, layanan
+mendefinisikan {@link android.os.Handler} yang akan merespons aneka tipe objek {@link
+android.os.Message}. {@link android.os.Handler}
+ini adalah dasar bagi {@link android.os.Messenger} yang nanti bisa berbagi {@link android.os.IBinder}
+dengan klien, sehingga memungkinkan klien mengirim perintah ke layanan dengan menggunakan objek {@link
+android.os.Message}. Selain itu, klien bisa mendefinisikan sendiri {@link android.os.Messenger}
+sehingga layanan bisa mengirim balik pesan.
+  <p>Inilah cara termudah melakukan komunikasi antarproses (IPC), karena {@link
+android.os.Messenger} akan mengantre semua permintaan ke dalam satu thread sehingga Anda tidak perlu mendesain
+layanan agar thread-safe.</p>
+  </dd>
+
+  <dt>Menggunakan AIDL</dt>
+  <dd>AIDL (Android Interface Definition Language) melakukan semua pekerjaan untuk mengurai objek menjadi
+primitif yang bisa dipahami dan diarahkan oleh sistem operasi ke berbagai proses untuk melakukan
+IPC. Teknik sebelumnya, dengan menggunakan {@link android.os.Messenger}, sebenarnya berdasarkan AIDL sebagai
+struktur yang mendasarinya. Seperti disebutkan di atas, {@link android.os.Messenger} membuat antrean
+semua permintaan klien dalam satu thread, sehingga layanan akan menerima permintaan satu per satu. Akan tetapi,
+jika ingin layanan Anda menangani beberapa permintaan sekaligus, Anda bisa menggunakan AIDL
+secara langsung. Dalam hal ini, layanan Anda harus mampu multi-thread dan dibuat thread-safe.
+  <p>Untuk menggunakan AIDL secara langsung, Anda harus
+membuat file {@code .aidl} yang mendefinisikan antarmuka pemrograman. Alat Android SDK menggunakan
+file ini untuk menghasilkan kelas abstrak yang mengimplementasikan antarmuka dan menangani IPC, yang nanti
+bisa Anda perluas dalam layanan.</p>
+  </dd>
+</dl>
+
+  <p class="note"><strong>Catatan:</strong> Umumnya aplikasi <strong>tidak boleh</strong> menggunakan AIDL untuk
+membuat layanan terikat, karena hal itu mungkin memerlukan kemampuan multi-thread dan
+bisa mengakibatkan implementasi yang lebih rumit. Dengan demikian, AIDL tidak cocok untuk sebagian besar aplikasi
+dan dokumen ini tidak membahas cara menggunakannya untuk layanan Anda. Jika Anda yakin perlu
+menggunakan AIDL secara langsung, lihat dokumen <a href="{@docRoot}guide/components/aidl.html">AIDL</a>
+.</p>
+
+
+
+
+<h3 id="Binder">Memperluas kelas Binder</h3>
+
+<p>Jika layanan Anda hanya digunakan oleh aplikasi lokal dan tidak perlu bekerja lintas proses,
+maka Anda bisa mengimplementasikan kelas {@link android.os.Binder} Anda sendiri yang memberi klien Anda
+akses langsung ke metode publik dalam layanan.</p>
+
+<p class="note"><strong>Catatan:</strong> Hal ini hanya berhasil jika klien dan layanan berada dalam
+aplikasi dan proses yang sama, suatu kondisi yang paling umum. Misalnya, cara ini sangat cocok untuk sebuah aplikasi musik
+yang perlu mengikat aktivitas ke layanannya sendiri, yakni memutar musik di
+latar belakang.</p>
+
+<p>Berikut cara menyiapkannya:</p>
+<ol>
+  <li>Dalam layanan Anda, buat sebuah instance {@link android.os.Binder} yang:
+    <ul>
+      <li>berisi metode publik yang bisa dipanggil klien</li>
+      <li>menghasilkan instance {@link android.app.Service} saat ini, yang memiliki metode publik yang
+bisa dipanggil klien</li>
+      <li>atau, menghasilkan instance kelas lain yang host-nya di layanan dengan metode publik yang
+bisa dipanggil klien</li>
+    </ul>
+  <li>Hasilkan instance {@link android.os.Binder} ini dari metode callback {@link
+android.app.Service#onBind onBind()}.</li>
+  <li>Di klien, terima {@link android.os.Binder} dari metode callback {@link
+android.content.ServiceConnection#onServiceConnected onServiceConnected()} dan
+buat panggilan ke layanan terikat dengan menggunakan metode yang disediakan.</li>
+</ol>
+
+<p class="note"><strong>Catatan:</strong> Alasan layanan dan klien harus berada dalam aplikasi yang sama
+adalah agar klien bisa mengkonversi objek yang dihasilkan dan memanggil API-nya dengan benar. Layanan
+dan klien juga harus berada dalam proses yang sama, karena teknik ini tidak melakukan
+pengarahan (marshalling) apa pun untuk lintas proses.</p>
+
+<p>Misalnya, berikut ini adalah layanan yang memberi klien akses ke metode-metode dalam layanan melalui
+implementasi {@link android.os.Binder}:</p>
+
+<pre>
+public class LocalService extends Service {
+    // Binder given to clients
+    private final IBinder mBinder = new LocalBinder();
+    // Random number generator
+    private final Random mGenerator = new Random();
+
+    /**
+     * Class used for the client Binder.  Because we know this service always
+     * runs in the same process as its clients, we don't need to deal with IPC.
+     */
+    public class LocalBinder extends Binder {
+        LocalService getService() {
+            // Return this instance of LocalService so clients can call public methods
+            return LocalService.this;
+        }
+    }
+
+    &#64;Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+
+    /** method for clients */
+    public int getRandomNumber() {
+      return mGenerator.nextInt(100);
+    }
+}
+</pre>
+
+<p>{@code LocalBinder} menyediakan {@code getService()} metode bagi klien untuk mengambil
+instance {@code LocalService} saat ini. Cara ini memungkinkan klien memanggil metode publik dalam
+layanan. Misalnya, klien bisa memanggil {@code getRandomNumber()} dari layanan.</p>
+
+<p>Berikut ini adalah aktivitas yang mengikat ke {@code LocalService} dan memanggil {@code getRandomNumber()}
+bila tombol diklik:</p>
+
+<pre>
+public class BindingActivity extends Activity {
+    LocalService mService;
+    boolean mBound = false;
+
+    &#64;Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+    }
+
+    &#64;Override
+    protected void onStart() {
+        super.onStart();
+        // Bind to LocalService
+        Intent intent = new Intent(this, LocalService.class);
+        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+    }
+
+    &#64;Override
+    protected void onStop() {
+        super.onStop();
+        // Unbind from the service
+        if (mBound) {
+            unbindService(mConnection);
+            mBound = false;
+        }
+    }
+
+    /** Called when a button is clicked (the button in the layout file attaches to
+      * this method with the android:onClick attribute) */
+    public void onButtonClick(View v) {
+        if (mBound) {
+            // Call a method from the LocalService.
+            // However, if this call were something that might hang, then this request should
+            // occur in a separate thread to avoid slowing down the activity performance.
+            int num = mService.getRandomNumber();
+            Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
+        }
+    }
+
+    /** Defines callbacks for service binding, passed to bindService() */
+    private ServiceConnection mConnection = new ServiceConnection() {
+
+        &#64;Override
+        public void onServiceConnected(ComponentName className,
+                IBinder service) {
+            // We've bound to LocalService, cast the IBinder and get LocalService instance
+            LocalBinder binder = (LocalBinder) service;
+            mService = binder.getService();
+            mBound = true;
+        }
+
+        &#64;Override
+        public void onServiceDisconnected(ComponentName arg0) {
+            mBound = false;
+        }
+    };
+}
+</pre>
+
+<p>Contoh di atas menampilkan cara klien mengikat ke layanan dengan menggunakan implementasi
+{@link android.content.ServiceConnection} dan callback {@link
+android.content.ServiceConnection#onServiceConnected onServiceConnected()}. Bagian
+berikut menyediakan informasi selengkapnya tentang proses pengikatan ke layanan.</p>
+
+<p class="note"><strong>Catatan:</strong> Contoh di atas tidak secara eksplisit melepas ikatan dari layanan,
+namun semua klien harus melepas ikatan pada waktu yang tepat (seperti saat aktivitas sedang jeda).</p>
+
+<p>Untuk contoh kode selengkapnya, lihat kelas <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
+LocalService.java}</a> dan kelas <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.html">{@code
+LocalServiceActivities.java}</a> dalam <a href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
+
+
+
+
+
+<h3 id="Messenger">Menggunakan Messenger</h3>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+  <h4>Dibandingkan dengan AIDL</h4>
+  <p>Bila Anda perlu melakukan IPC, menggunakan {@link android.os.Messenger} untuk antarmuka
+lebih sederhana daripada mengimplementasikannya dengan AIDL, karena {@link android.os.Messenger} mengantre
+semua panggilan ke layanan, sementara antarmuka AIDL murni mengirim permintaan serentak ke
+layanan, yang nanti harus menangani multi-threading.</p>
+  <p>Untuk sebagian besar aplikasi, layanan tidak perlu melakukan multi-threading, jadi dengan menggunakan {@link
+android.os.Messenger} memungkinkan layanan menangani panggilan satu per satu. Jika
+layanan harus multi-thread, Anda harus menggunakan <a href="{@docRoot}guide/components/aidl.html">AIDL</a> untuk mendefinisikan antarmuka.</p>
+</div>
+</div>
+
+<p>Jika layanan perlu berkomunikasi dengan proses jauh, Anda bisa menggunakan
+{@link android.os.Messenger} untuk menyediakan antarmuka bagi layanan Anda. Teknik ini memungkinkan
+Anda melakukan komunikasi antarproses (IPC) tanpa harus menggunakan AIDL.</p>
+
+<p>Berikut ini rangkuman cara menggunakan {@link android.os.Messenger}:</p>
+
+<ul>
+  <li>Layanan mengimplementasikan {@link android.os.Handler} yang menerima callback untuk tiap
+panggilan dari klien.</li>
+  <li>{@link android.os.Handler} digunakan untuk membuat objek {@link android.os.Messenger}
+(yang merupakan acuan ke {@link android.os.Handler}).</li>
+  <li>{@link android.os.Messenger} membuat {@link android.os.IBinder} yang
+dikembalikan layanan ke klien dari {@link android.app.Service#onBind onBind()}.</li>
+  <li>Klien menggunakan {@link android.os.IBinder} untuk membuat instance {@link android.os.Messenger}
+(yang mengacu {@link android.os.Handler} layanan), yang digunakan klien untuk mengirim
+objek {@link android.os.Message} ke layanan.</li>
+  <li>Layanan menerima setiap {@link android.os.Message} dalam {@link
+android.os.Handler}&mdash;secara spesifik, dalam metode {@link android.os.Handler#handleMessage
+handleMessage()}.</li>
+</ul>
+
+
+<p>Dengan cara ini, tidak ada "metode" untuk dipanggil klien pada layanan. Sebagai gantinya,
+klien mengirim "pesan" (objek-objek {@link android.os.Message}) yang diterima layanan dalam
+{@link android.os.Handler}-nya.</p>
+
+<p>Berikut ini contoh layanan sederhana yang menggunakan antarmuka {@link android.os.Messenger}:</p>
+
+<pre>
+public class MessengerService extends Service {
+    /** Command to the service to display a message */
+    static final int MSG_SAY_HELLO = 1;
+
+    /**
+     * Handler of incoming messages from clients.
+     */
+    class IncomingHandler extends Handler {
+        &#64;Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_SAY_HELLO:
+                    Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
+                    break;
+                default:
+                    super.handleMessage(msg);
+            }
+        }
+    }
+
+    /**
+     * Target we publish for clients to send messages to IncomingHandler.
+     */
+    final Messenger mMessenger = new Messenger(new IncomingHandler());
+
+    /**
+     * When binding to the service, we return an interface to our messenger
+     * for sending messages to the service.
+     */
+    &#64;Override
+    public IBinder onBind(Intent intent) {
+        Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
+        return mMessenger.getBinder();
+    }
+}
+</pre>
+
+<p>Perhatikan bahwa metode {@link android.os.Handler#handleMessage handleMessage()} dalam
+{@link android.os.Handler} adalah tempat layanan menerima {@link android.os.Message}
+yang masuk dan memutuskan aksi yang harus dilakukan, berdasarkan anggota {@link android.os.Message#what}.</p>
+
+<p>Klien tinggal membuat {@link android.os.Messenger} berdasarkan {@link
+android.os.IBinder} yang dihasilkan layanan dan mengirim pesan menggunakan {@link
+android.os.Messenger#send send()}. Misalnya, berikut ini adalah aktivitas sederhana yang mengikat ke
+layanan dan mengirim pesan {@code MSG_SAY_HELLO} ke layanan:</p>
+
+<pre>
+public class ActivityMessenger extends Activity {
+    /** Messenger for communicating with the service. */
+    Messenger mService = null;
+
+    /** Flag indicating whether we have called bind on the service. */
+    boolean mBound;
+
+    /**
+     * Class for interacting with the main interface of the service.
+     */
+    private ServiceConnection mConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            // This is called when the connection with the service has been
+            // established, giving us the object we can use to
+            // interact with the service.  We are communicating with the
+            // service using a Messenger, so here we get a client-side
+            // representation of that from the raw IBinder object.
+            mService = new Messenger(service);
+            mBound = true;
+        }
+
+        public void onServiceDisconnected(ComponentName className) {
+            // This is called when the connection with the service has been
+            // unexpectedly disconnected -- that is, its process crashed.
+            mService = null;
+            mBound = false;
+        }
+    };
+
+    public void sayHello(View v) {
+        if (!mBound) return;
+        // Create and send a message to the service, using a supported 'what' value
+        Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
+        try {
+            mService.send(msg);
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+    }
+
+    &#64;Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+    }
+
+    &#64;Override
+    protected void onStart() {
+        super.onStart();
+        // Bind to the service
+        bindService(new Intent(this, MessengerService.class), mConnection,
+            Context.BIND_AUTO_CREATE);
+    }
+
+    &#64;Override
+    protected void onStop() {
+        super.onStop();
+        // Unbind from the service
+        if (mBound) {
+            unbindService(mConnection);
+            mBound = false;
+        }
+    }
+}
+</pre>
+
+<p>Perhatikan bahwa contoh ini tidak menampilkan cara layanan merespons klien. Jika ingin
+layanan merespons, Anda juga perlu membuat {@link android.os.Messenger} di klien. Lalu
+saat menerima callback {@link android.content.ServiceConnection#onServiceConnected
+onServiceConnected()}, klien akan mengirim {@link android.os.Message} ke layanan yang berisi
+{@link android.os.Messenger} klien dalam parameter {@link android.os.Message#replyTo}
+metode {@link android.os.Messenger#send send()}.</p>
+
+<p>Anda bisa melihat contoh cara menyediakan pertukaran pesan dua arah dalam contoh <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.html">{@code
+MessengerService.java}</a> (layanan) dan <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.html">{@code
+MessengerServiceActivities.java}</a> (klien).</p>
+
+
+
+
+
+<h2 id="Binding">Mengikat ke Layanan</h2>
+
+<p>Komponen-komponen aplikasi (klien) bisa mengikat ke layanan dengan memanggil
+{@link android.content.Context#bindService bindService()}. Sistem Android
+lalu memanggil metode {@link android.app.Service#onBind
+onBind()} layanan, yang menghasilkan {@link android.os.IBinder} untuk berinteraksi dengan layanan.</p>
+
+<p>Pengikatan ini bersifat asinkron. {@link android.content.Context#bindService
+bindService()} segera kembali dan <em>tidak</em> mengembalikan {@link android.os.IBinder} ke
+klien. Untuk menerima {@link android.os.IBinder}, klien harus membuat instance {@link
+android.content.ServiceConnection} dan meneruskannya ke {@link android.content.Context#bindService
+bindService()}. {@link android.content.ServiceConnection} berisi metode callback yang
+dipanggil sistem untuk mengirim {@link android.os.IBinder}.</p>
+
+<p class="note"><strong>Catatan:</strong> Hanya aktivitas, layanan, dan penyedia konten yang bisa mengikat
+ke layanan yang&mdash;Anda <strong>tidak bisa</strong> ikat ke layanan dari penerima siaran.</p>
+
+<p>Jadi, untuk mengikat ke layanan dari klien, Anda harus: </p>
+<ol>
+  <li>Mengimplementasikan {@link android.content.ServiceConnection}.
+    <p>Implementasi Anda harus mengesampingkan dua metode callback:</p>
+    <dl>
+      <dt>{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}</dt>
+        <dd>Sistem memanggil ini untuk mengirim {@link android.os.IBinder} yang dihasilkan oleh
+metode {@link android.app.Service#onBind onBind()} layanan.</dd>
+      <dt>{@link android.content.ServiceConnection#onServiceDisconnected
+onServiceDisconnected()}</dt>
+        <dd>Sistem Android memanggil ini bila koneksi ke layanan putus
+tanpa terduga, seperti ketika layanan mengalami crash atau dimatikan. Ini <em>tidak</em> dipanggil ketika
+klien melepas ikatan.</dd>
+    </dl>
+  </li>
+  <li>Panggil {@link
+android.content.Context#bindService bindService()}, dengan meneruskan implementasi {@link
+android.content.ServiceConnection}. </li>
+  <li>Bila sistem memanggil metode callback {@link android.content.ServiceConnection#onServiceConnected
+onServiceConnected()}, Anda bisa mulai membuat panggilan ke layanan, dengan menggunakan
+metode yang didefinisikan oleh antarmuka.</li>
+  <li>Untuk memutus koneksi dari layanan, panggil {@link
+android.content.Context#unbindService unbindService()}.
+    <p>Bila telah dimusnahkan (destroyed), klien Anda akan melepas ikatan dari layanan, namun Anda harus selalu melepas ikatan
+bila sudah selesai berinteraksi dengan layanan atau bila aktivitas Anda sedang jeda sehingga layanan bisa
+dimatikan saat tidak sedang digunakan. (Waktu yang tepat untuk mengikat dan melepas ikatan dibahas
+selengkapnya di bawah ini.)</p>
+  </li>
+</ol>
+
+<p>Misalnya, cuplikan berikut menghubungkan klien ke layanan yang dibuat di atas dengan
+<a href="#Binder">memperluas kelas Binder</a>, sehingga tinggal mengkonversi
+{@link android.os.IBinder} yang dihasilkan ke kelas {@code LocalService} dan meminta instance {@code
+LocalService}:</p>
+
+<pre>
+LocalService mService;
+private ServiceConnection mConnection = new ServiceConnection() {
+    // Called when the connection with the service is established
+    public void onServiceConnected(ComponentName className, IBinder service) {
+        // Because we have bound to an explicit
+        // service that is running in our own process, we can
+        // cast its IBinder to a concrete class and directly access it.
+        LocalBinder binder = (LocalBinder) service;
+        mService = binder.getService();
+        mBound = true;
+    }
+
+    // Called when the connection with the service disconnects unexpectedly
+    public void onServiceDisconnected(ComponentName className) {
+        Log.e(TAG, "onServiceDisconnected");
+        mBound = false;
+    }
+};
+</pre>
+
+<p>Dengan {@link android.content.ServiceConnection} ini, klien bisa mengikat ke layanan dengan meneruskannya
+ke {@link android.content.Context#bindService bindService()}. Misalnya:</p>
+
+<pre>
+Intent intent = new Intent(this, LocalService.class);
+bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+</pre>
+
+<ul>
+  <li>Parameter pertama {@link android.content.Context#bindService bindService()} adalah sebuah
+{@link android.content.Intent} yang secara eksplisit menyebutkan layanan yang akan diikat (walaupun intent
+boleh implisit).</li>
+<li>Parameter kedua adalah objek {@link android.content.ServiceConnection}.</li>
+<li>Parameter ketiga adalah tanda (flag) yang menunjukkan opsi pengikatan. Tanda ini biasanya harus {@link
+android.content.Context#BIND_AUTO_CREATE} agar dapat membuat layanan jika belum hidup.
+Nilai-nilai lain yang memungkinkan adalah {@link android.content.Context#BIND_DEBUG_UNBIND}
+dan {@link android.content.Context#BIND_NOT_FOREGROUND}, atau {@code 0} untuk tidak satu pun.</li>
+</ul>
+
+
+<h3>Catatan tambahan</h3>
+
+<p>Berikut ini beberapa catatan penting tentang mengikat ke layanan:</p>
+<ul>
+  <li>Anda harus selalu menjebak eksepsi {@link android.os.DeadObjectException}, yang dilontarkan
+bila koneksi terputus. Inilah satu-satunya eksepsi yang dilontarkan oleh metode jauh.</li>
+  <li>Objek adalah acuan yang dihitung lintas proses. </li>
+  <li>Anda biasanya harus memasangkan pengikatan dan pelepasan ikatan selama
+memasangkan momen membuat dan menghapus daur hidup klien. Misalnya:
+    <ul>
+      <li>Jika Anda hanya perlu berinteraksi dengan layanan saat aktivitas terlihat, Anda
+harus mengikat selama {@link android.app.Activity#onStart onStart()} dan melepas ikatan selama {@link
+android.app.Activity#onStop onStop()}.</li>
+      <li>Jika Anda ingin aktivitas menerima tanggapan bahkan saat dihentikan di
+latar belakang, Anda bisa mengikat selama {@link android.app.Activity#onCreate onCreate()} dan melepas ikatan
+selama {@link android.app.Activity#onDestroy onDestroy()}. Berhati-hatilah karena hal ini menyiratkan aktivitas
+Anda perlu menggunakan layanan selama dijalankan (sekalipun di latar belakang), jadi jika
+layanan berada dalam proses lain, Anda meningkatkan bobot proses dan semakin besar
+kemungkinan sistem akan mematikannya.</li>
+    </ul>
+    <p class="note"><strong>Catatan:</strong> Anda biasanya <strong>tidak</strong> boleh mengikat dan melepas ikatan
+selama {@link android.app.Activity#onResume onResume()} aktivitas Anda dan {@link
+android.app.Activity#onPause onPause()}, karena callback ini terjadi pada setiap transisi daur hidup
+dan Anda harus menjaga pemrosesan yang terjadi pada transisi ini tetap minim. Juga, jika
+banyak aktivitas dalam aplikasi Anda mengikat ke layanan yang sama dan ada transisi antara
+dua aktivitas, layanan bisa dimusnahkan dan dibuat lagi sambil aktivitas saat ini melepas ikatan
+(selama jeda) sebelum aktivitas berikutnya mengikat (selama lanjutkan). (Transisi aktivitas ini untuk cara
+aktivitas mengoordinasikan daur hidupnya dijelaskan dalam dokumen <a href="{@docRoot}guide/components/activities.html#CoordinatingActivities">Aktivitas</a>
+.)</p>
+</ul>
+
+<p>Untuk contoh kode selengkapnya, yang menampilkan cara mengikat ke layanan, lihat kelas <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
+RemoteService.java}</a> dalam <a href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
+
+
+
+
+
+<h2 id="Lifecycle">Mengelola Daur Hidup Layanan Terikat</h2>
+
+<p>Bila layanan dilepas ikatannya dari semua klien, sistem Android akan menghapusnya (kecuali jika layanan juga
+dimulai dengan {@link android.app.Service#onStartCommand onStartCommand()}). Dengan demikian, Anda tidak harus
+mengelola daur hidup layanan jika layanan itu murni sebuah layanan
+terikat&mdash;yang dikelola sistem Android untuk Anda berdasarkan apakah layanan terikat ke klien atau tidak.</p>
+
+<p>Akan tetapi, Jika Anda memilih untuk mengimplementasikan metode callback {@link android.app.Service#onStartCommand
+onStartCommand()}, maka Anda harus menghentikan layanan secara eksplisit, karena layanan
+sekarang dianggap telah <em>dimulai</em>. Dalam hal ini, layanan akan berjalan hingga layanan
+menghentikan dirinya sendiri dengan {@link android.app.Service#stopSelf()} atau panggilan komponen lain {@link
+android.content.Context#stopService stopService()}, terlepas dari apakah layanan terikat ke
+klien atau tidak.</p>
+
+<p>Selain itu, jika layanan Anda telah dimulai dan menerima pengikatan, maka saat sistem memanggil
+metode {@link android.app.Service#onUnbind onUnbind()}, Anda bisa memilih untuk mengembalikan
+{@code true} jika ingin menerima panggilan ke {@link android.app.Service#onRebind
+onRebind()} bila nanti klien mengikat ke layanan (sebagai ganti menerima panggilan ke {@link
+android.app.Service#onBind onBind()}). {@link android.app.Service#onRebind
+onRebind()} akan menghasilkan void, namun klien tetap menerima {@link android.os.IBinder} dalam callback
+{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}.
+Di bawah ini adalah gambar 1 yang mengilustrasikan logika untuk jenis daur hidup ini.</p>
+
+
+<img src="{@docRoot}images/fundamentals/service_binding_tree_lifecycle.png" alt="" />
+<p class="img-caption"><strong>Gambar 1.</strong> Daur hidup untuk layanan yang dimulai
+dan juga memungkinkan pengikatan.</p>
+
+
+<p>Untuk informasi selengkapnya tentang daur hidup layanan yang telah dimulai, lihat dokumen <a href="{@docRoot}guide/components/services.html#Lifecycle">Layanan</a>.</p>
+
+
+
+
diff --git a/docs/html-intl/intl/id/guide/components/fragments.jd b/docs/html-intl/intl/id/guide/components/fragments.jd
new file mode 100644
index 0000000..9f7199c
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/components/fragments.jd
@@ -0,0 +1,812 @@
+page.title=Fragmen
+parent.title=Aktivitas
+parent.link=activities.html
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>Dalam dokumen ini</h2>
+  <ol>
+    <li><a href="#Design">Filosofi Desain</a></li>
+    <li><a href="#Creating">Membuat Fragmen</a>
+      <ol>
+        <li><a href="#UI">Menambahkan antarmuka pengguna</a></li>
+        <li><a href="#Adding">Menambahkan fragmen ke aktivitas</a></li>
+      </ol>
+    </li>
+    <li><a href="#Managing">Mengelola Fragmen</a></li>
+    <li><a href="#Transactions">Melakukan Transaksi Fragmen</a></li>
+    <li><a href="#CommunicatingWithActivity">Berkomunikasi dengan Aktivitas</a>
+      <ol>
+        <li><a href="#EventCallbacks">Membuat callback kejadian pada aktivitas</a></li>
+        <li><a href="#ActionBar">Menambahkan item ke Action-Bar</a></li>
+      </ol>
+    </li>
+    <li><a href="#Lifecycle">Menangani Daur Hidup Fragmen</a>
+      <ol>
+        <li><a href="#CoordinatingWithActivity">Mengoordinasi dengan daur hidup aktivitas</a></li>
+      </ol>
+    </li>
+    <li><a href="#Example">Contoh</a></li>
+  </ol>
+
+  <h2>Kelas-kelas utama</h2>
+  <ol>
+    <li>{@link android.app.Fragment}</li>
+    <li>{@link android.app.FragmentManager}</li>
+    <li>{@link android.app.FragmentTransaction}</li>
+  </ol>
+
+  <h2>Lihat juga</h2>
+  <ol>
+    <li><a href="{@docRoot}training/basics/fragments/index.html">Membangun UI Dinamis dengan Fragmen</a></li>
+    <li><a href="{@docRoot}guide/practices/tablets-and-handsets.html">Mendukung Tablet
+dan Handset</a></li>
+  </ol>
+</div>
+</div>
+
+<p>{@link android.app.Fragment} mewakili perilaku atau bagian dari antarmuka pengguna dalam
+{@link android.app.Activity}. Anda bisa mengombinasikan beberapa fragmen dalam satu aktivitas untuk membangun UI
+multipanel dan menggunakan kembali sebuah fragmen dalam beberapa aktivitas. Anda bisa menganggap fragmen sebagai bagian
+modular dari aktivitas, yang memiliki daur hidup sendiri, menerima kejadian input sendiri, dan
+yang bisa Anda tambahkan atau hapus saat aktivitas berjalan (semacam "sub aktivitas" yang
+bisa digunakan kembali dalam aktivitas berbeda).</p>
+
+<p>Fragmen harus selalu tertanam dalam aktivitas dan daur hidup fragmen secara langsung
+dipengaruhi oleh daur hidup aktivitas host-nya. Misalnya, saat aktivitas dihentikan sementara,
+semua fragmen di dalamnya juga dihentikan sementara, dan bila aktivitas dimusnahkan, semua fragmen juga demikian. Akan tetapi, saat
+aktivitas berjalan (dalam <a href="{@docRoot}guide/components/activities.html#Lifecycle">status daur hidup</a> <em>dilanjutkan</em>, Anda bisa
+memanipulasi setiap fragmen secara terpisah, seperti menambah atau menghapusnya. Saat melakukan transaksi
+fragmen, Anda juga bisa menambahkannya ke back-stack yang dikelola oleh aktivitas
+&mdash;setiap entri back-stack merupakan record transaksi fragmen yang
+terjadi. Dengan back-stack pengguna dapat membalikkan transaksi fragmen (mengarah mundur),
+dengan menekan tombol <em>Back</em>.</p>
+
+<p>Bila Anda menambahkan fragmen sebagai bagian dari layout aktivitas, fragmen itu berada dalam {@link
+android.view.ViewGroup} di hierarki tampilan aktivitas tersebut dan fragmen mendefinisikan
+layout
+tampilannya sendiri. Anda bisa menyisipkan fragmen ke dalam layout aktivitas dengan mendeklarasikan fragmen dalam file layout aktivitas
+, sebagai elemen {@code &lt;fragment&gt;}, atau dari kode aplikasi dengan menambahkannya ke
+ {@link android.view.ViewGroup} yang ada. Akan tetapi, fragmen tidak harus menjadi bagian dari
+layout aktivitas; Anda juga bisa menggunakan fragmen tanpa UI-nya sendiri sebagai pekerja tak terlihat untuk
+aktivitas tersebut.</p>
+
+<p>Dokumen ini menjelaskan cara membangun aplikasi menggunakan fragmen, termasuk
+cara fragmen mempertahankan statusnya bila ditambahkan ke back-stack aktivitas, berbagi
+kejadian dengan aktivitas, dan fragmen lain dalam aktivitas, berkontribusi pada action-bar
+aktivitas, dan lainnya.</p>
+
+
+<h2 id="Design">Filosofi Desain</h2>
+
+<p>Android memperkenalkan fragmen di Android 3.0 (API level 11), terutama untuk mendukung desain UI yang lebih
+dinamis dan fleksibel pada layar besar, seperti tablet. Karena
+layar tablet jauh lebih besar daripada layar handset, maka lebih banyak ruang untuk mengombinasikan dan
+bertukar komponen UI. Fragmen memungkinkan desain seperti itu tanpa perlu mengelola perubahan
+kompleks pada hierarki tampilan. Dengan membagi layout aktivitas menjadi beberapa fragmen, Anda bisa
+mengubah penampilan aktivitas saat runtime dan mempertahankan perubahan itu di back-stack
+yang dikelola oleh aktivitas.</p>
+
+<p>Misalnya, aplikasi berita bisa menggunakan satu fragmen untuk menampilkan daftar artikel di
+sebelah kiri dan fragmen lainnya untuk menampilkan artikel di sebelah kanan&mdash;kedua fragmen ini muncul di satu
+aktivitas, berdampingan, dan masing-masing fragmen memiliki serangkaian metode callback daur hidup dan menangani kejadian input
+penggunanya sendiri. Sehingga, sebagai ganti menggunakan satu aktivitas untuk memilih
+artikel dan aktivitas lainnya untuk membaca artikel, pengguna bisa memilih artikel dan membaca semuanya dalam
+aktivitas yang sama, sebagaimana diilustrasikan dalam layout tablet pada gambar 1.</p>
+
+<p>Anda harus mendesain masing-masing fragmen sebagai komponen aktivitas modular dan bisa digunakan kembali. Yakni, karena
+setiap fragmen mendefinisikan layoutnya dan perilakunya dengan callback daur hidupnya sendiri, Anda bisa memasukkan
+satu fragmen dalam banyak aktivitas, sehingga Anda harus mendesainnya untuk digunakan kembali dan mencegah
+memanipulasi satu fragmen dari fragmen lain secara langsung. Ini terutama penting karena dengan
+fragmen modular Anda bisa mengubah kombinasi fragmen untuk ukuran layar berbeda. Saat mendesain aplikasi
+untuk mendukung tablet maupun handset, Anda bisa menggunakan kembali fragmen dalam
+konfigurasi layout berbeda untuk mengoptimalkan pengalaman pengguna berdasarkan ruang layar yang tersedia. Misalnya
+, pada handset, fragmen mungkin perlu dipisahkan untuk menyediakan UI panel tunggal
+bila lebih dari satu yang tidak cocok dalam aktivitas yang sama.</p>
+
+<img src="{@docRoot}images/fundamentals/fragments.png" alt="" />
+<p class="img-caption"><strong>Gambar 1.</strong> Contoh cara dua modul UI yang didefinisikan oleh
+ fragmen bisa digabungkan ke dalam satu aktivitas untuk desain tablet, namun dipisahkan untuk
+desain handset.</p>
+
+<p>Misalnya&mdash;untuk melanjutkan contoh aplikasi berita&mdash; aplikasi bisa menanamkan
+dua fragmen dalam <em>Aktivitas A</em>, saat berjalan pada perangkat berukuran tablet. Akan tetapi, pada
+layar berukuran handset, ruang untuk kedua fragmen tidak cukup, sehingga <em>Aktivitas A</em> hanya
+menyertakan fragmen untuk daftar artikel, dan saat pengguna memilih artikel,
+<em>Aktivitas B</em> akan dimulai, termasuk fragmen kedua untuk membaca artikel. Sehingga, aplikasi mendukung
+tablet dan handset dengan menggunakan kembali fragmen dalam kombinasi berbeda, seperti diilustrasikan dalam
+gambar 1.</p>
+
+<p>Untuk informasi selengkapnya tentang mendesain aplikasi menggunakan kombinasi fragmen berbeda
+untuk konfigurasi layar berbeda, lihat panduan untuk <a href="{@docRoot}guide/practices/tablets-and-handsets.html">Mendukung Tablet dan Handset</a>.</p>
+
+
+
+<h2 id="Creating">Membuat Fragmen</h2>
+
+<div class="figure" style="width:327px">
+<img src="{@docRoot}images/fragment_lifecycle.png" alt="" />
+<p class="img-caption"><strong>Gambar 2.</strong> Daur hidup fragmen (saat
+ aktivitasnya berjalan).</p>
+</div>
+
+<p>Untuk membuat fragmen, Anda harus membuat subkelas {@link android.app.Fragment} (atau
+subkelasnya yang ada). Kelas {@link android.app.Fragment} memiliki kode yang mirip seperti
+{@link android.app.Activity}. Kelas ini memiliki metode callback yang serupa dengan aktivitas, seperti
+ {@link android.app.Fragment#onCreate onCreate()}, {@link android.app.Fragment#onStart onStart()},
+{@link android.app.Fragment#onPause onPause()}, dan {@link android.app.Fragment#onStop onStop()}. Sebenarnya
+, jika Anda mengkonversi aplikasi Android saat ini untuk menggunakan fragmen, Anda mungkin cukup memindahkan
+kode dari metode callback aktivitas ke masing-masing metode callback
+fragmen.</p>
+
+<p>Biasanya, Anda harus mengimplementasikan setidaknya metode daur hidup berikut ini:</p>
+
+<dl>
+  <dt>{@link android.app.Fragment#onCreate onCreate()}</dt>
+  <dd>Sistem akan memanggilnya saat membuat fragmen. Dalam implementasi, Anda harus
+menginisialisasi komponen penting dari fragmen yang ingin dipertahankan saat fragmen
+dihentikan sementara atau dihentikan, kemudian dilanjutkan.</dd>
+  <dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt>
+  <dd>Sistem akan memanggilnya saat fragmen menggambar antarmuka penggunanya
+untuk yang pertama kali. Untuk menggambar UI fragmen, Anda harus mengembalikan {@link android.view.View} dari metode
+ini yang menjadi akar layout fragmen. Hasil yang dikembalikan bisa berupa null jika
+fragmen tidak menyediakan UI.</dd>
+  <dt>{@link android.app.Activity#onPause onPause()}</dt>
+  <dd>Sistem akan memanggil metode ini sebagai indikasi pertama bahwa pengguna sedang meninggalkan
+fragmen Anda (walau itu tidak selalu berarti fragmen sedang dimusnahkan). Inilah biasanya tempat Anda
+harus mengikat setiap perubahan yang harus dipertahankan selepas sesi pengguna saat ini (karena
+pengguna mungkin tidak kembali).</dd>
+</dl>
+
+<p>Kebanyakan aplikasi harus mengimplementasikan setidaknya tiga metode ini untuk setiap fragmen, namun ada
+beberapa metode callback lain yang juga harus Anda gunakan untuk menangani berbagai tahap
+daur hidup fragmen. Semua metode callback daur hidup akan dibahas secara lebih detail, di bagian
+tentang <a href="#Lifecycle">Menangani Daur Hidup Fragmen</a>.</p>
+
+
+<p>Ada juga beberapa subkelas yang mungkin ingin diperpanjang, sebagai ganti kelas basis {@link
+android.app.Fragment}:</p>
+
+<dl>
+  <dt>{@link android.app.DialogFragment}</dt>
+  <dd>Menampilkan dialog mengambang. Penggunaan kelas ini untuk membuat dialog merupakan alternatif yang baik dari
+penggunaan metode helper dialog di kelas {@link android.app.Activity}, karena Anda bisa
+menyatukan dialog fragmen ke dalam back-stack fragmen yang dikelola oleh aktivitas,
+sehingga pengguna bisa kembali ke fragmen yang ditinggalkan.</dd>
+
+  <dt>{@link android.app.ListFragment}</dt>
+  <dd>Menampilkan daftar item yang dikelola oleh adaptor (seperti {@link
+android.widget.SimpleCursorAdapter}), serupa dengan {@link android.app.ListActivity}. Menampilkan
+beberapa metode pengelolaan daftar tampilan seperti callback {@link
+android.app.ListFragment#onListItemClick(ListView,View,int,long) onListItemClick()} untuk
+menangani kejadian klik.</dd>
+
+  <dt>{@link android.preference.PreferenceFragment}</dt>
+  <dd>Menampilkan hierarki objek {@link android.preference.Preference} sebagai daftar, serupa dengan
+{@link android.preference.PreferenceActivity}. Hal ini berguna saat membuat aktivitas
+"pengaturan" untuk aplikasi Anda.</dd>
+</dl>
+
+
+<h3 id="UI">Menambahkan antarmuka pengguna</h3>
+
+<p>Fragmen biasanya digunakan sebagai bagian dari antarmuka pengguna aktivitas dan menyumbangkan
+layoutnya sendiri ke aktivitas.</p>
+
+<p>Untuk menyediakan layout fragmen, Anda harus mengimplementasikan metode callback {@link
+android.app.Fragment#onCreateView onCreateView()}, yang dipanggil sistem Android
+bila tiba saatnya fragmen menggambar layoutnya. Implementasi Anda atas metode ini harus mengembalikan
+{@link android.view.View} yang menjadi akar layout fragmen.</p>
+
+<p class="note"><strong>Catatan:</strong> Jika fragmen adalah subkelas {@link
+android.app.ListFragment}, implementasi default akan mengembalikan {@link android.widget.ListView} dari
+{@link android.app.Fragment#onCreateView onCreateView()}, sehingga Anda tidak perlu mengimplementasikannya.</p>
+
+<p>Untuk mengembalikan layout dari {@link
+android.app.Fragment#onCreateView onCreateView()}, Anda bisa memekarkannya dari <a href="{@docRoot}guide/topics/resources/layout-resource.html">sumber daya layout</a> yang didefinisikan di XML. Untuk
+membantu melakukannya, {@link android.app.Fragment#onCreateView onCreateView()} menyediakan objek
+{@link android.view.LayoutInflater}.</p>
+
+<p>Misalnya, ini adalah subkelas {@link android.app.Fragment} yang memuat layout dari file
+{@code example_fragment.xml}:</p>
+
+<pre>
+public static class ExampleFragment extends Fragment {
+    &#64;Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        // Inflate the layout for this fragment
+        return inflater.inflate(R.layout.example_fragment, container, false);
+    }
+}
+</pre>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+  <h3>Membuat layout</h3>
+  <p>Dalam contoh di atas, {@code R.layout.example_fragment} merupakan acuan ke sumber daya layout
+bernama {@code example_fragment.xml} yang tersimpan dalam sumber daya aplikasi. Untuk informasi tentang cara
+membuat layout di XML, lihat dokumentasi
+<a href="{@docRoot}guide/topics/ui/index.html">Antarmuka Pengguna</a>.</p>
+</div>
+</div>
+
+<p>Parameter {@code container} yang diteruskan ke {@link android.app.Fragment#onCreateView
+onCreateView()} adalah induk {@link android.view.ViewGroup} (dari layout aktivitas) tempat
+layout fragmen
+akan disisipkan. Parameter {@code savedInstanceState} adalah {@link android.os.Bundle} yang
+menyediakan data tentang instance fragmen sebelumnya, jika fragmen dilanjutkan
+(status pemulihan dibahas selengkapnya di bagian tentang <a href="#Lifecycle">Menangani
+Daur Hidup Fragmen</a>).</p>
+
+<p>Metode {@link android.view.LayoutInflater#inflate(int,ViewGroup,boolean) inflate()} membutuhkan
+tiga argumen:</p>
+<ul>
+  <li>ID sumber daya layout yang ingin dimekarkan.</li>
+  <li>{@link android.view.ViewGroup} akan menjadi induk dari layout yang dimekarkan. {@code
+container} perlu diteruskan agar sistem menerapkan parameter layout ke tampilan akar layout
+yang dimekarkan, yang ditetapkan dalam tampilan induk yang akan dituju.</li>
+  <li>Boolean yang menunjukkan apakah layout akan dimekarkan harus ditempelkan pada {@link
+android.view.ViewGroup} (parameter kedua) selama pemekaran. (Dalam hal ini, ini
+salah karena sistem sudah memasukkan layout yang dimekarkan ke dalam {@code
+container}&mdash;meneruskan benar akan membuat tampilan grup yang berlebihan dalam layout akhir.)</li>
+</ul>
+
+<p>Anda kini telah melihat cara membuat fragmen yang menyediakan layout. Berikutnya, Anda perlu menambahkan
+fragmen ke aktivitas.</p>
+
+
+
+<h3 id="Adding">Menambahkan fragmen ke aktivitas</h3>
+
+<p>Biasanya, fragmen berkontribusi pada sebagian UI ke aktivitas host, yang ditanamkan sebagai
+bagian dari hierarki tampilan keseluruhan aktivitas. Ada dua cara untuk menambahkan fragmen ke layout
+aktivitas:</p>
+
+<ul>
+  <li><b>Deklarasikan fragmen dalam file layout aktivitas.</b>
+<p>Dalam hal ini, Anda bisa
+menetapkan properti layout fragmen seakan-akan sebuah tampilan. Misalnya, berikut ini adalah file
+layout untuk aktivitas dengan dua fragmen:</p>
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"&gt;
+    &lt;fragment android:name="com.example.news.ArticleListFragment"
+            android:id="@+id/list"
+            android:layout_weight="1"
+            android:layout_width="0dp"
+            android:layout_height="match_parent" /&gt;
+    &lt;fragment android:name="com.example.news.ArticleReaderFragment"
+            android:id="@+id/viewer"
+            android:layout_weight="2"
+            android:layout_width="0dp"
+            android:layout_height="match_parent" /&gt;
+&lt;/LinearLayout&gt;
+</pre>
+  <p>Atribut {@code android:name} dalam {@code &lt;fragment&gt;} menetapkan kelas {@link
+android.app.Fragment} untuk dibuat instance-nya dalam layout.</p>
+
+<p>Saat sistem membuat layout aktivitas, sistem membuat instance setiap fragmen sebagaimana yang ditetapkan dalam layout
+dan memanggil metode {@link android.app.Fragment#onCreateView onCreateView()} masing-masing,
+untuk mengambil setiap fragmen. Sistem akan menyisipkan {@link android.view.View} yang dikembalikan langsung oleh fragmen,
+ menggantikan elemen {@code &lt;fragment&gt;}.</p>
+
+<div class="note">
+  <p><strong>Catatan:</strong> Setiap fragmen memerlukan identifier
+unik yang bisa digunakan sistem untuk memulihkan fragmen jika aktivitas dimulai kembali (dan identifier yang bisa digunakan menangkap
+fragmen untuk melakukan transaksi, seperti menghapusnya). Ada tiga cara untuk memberikan
+ID bagi fragmen:</p>
+  <ul>
+    <li>Memberikan atribut {@code android:id} bersama ID unik.</li>
+    <li>Memberikan atribut {@code android:tag} bersama string unik.</li>
+    <li>Jika Anda tidak memberikan dua hal tersebut, sistem akan menggunakan ID
+tampilan kontainer.</li>
+  </ul>
+</div>
+  </li>
+
+  <li><b>Atau, secara programatis tambahkan fragmen ke {@link android.view.ViewGroup} yang ada.</b>
+<p>Kapan saja saat aktivitas berjalan, Anda bisa menambahkan fragmen ke layout aktivitas. Anda
+cukup menetapkan {@link
+android.view.ViewGroup} di tempat memasukkan fragmen.</p>
+  <p>Untuk membuat transaksi fragmen dalam aktivitas (seperti menambah, menghapus, atau mengganti
+fragmen), Anda harus menggunakan API dari {@link android.app.FragmentTransaction}. Anda bisa mengambil instance
+ {@link android.app.FragmentTransaction} dari {@link android.app.Activity} seperti ini:</p>
+
+<pre>
+FragmentManager fragmentManager = {@link android.app.Activity#getFragmentManager()}
+FragmentTransaction fragmentTransaction = fragmentManager.{@link android.app.FragmentManager#beginTransaction()};
+</pre>
+
+<p>Selanjutnya Anda bisa menambahkan fragmen menggunakan metode {@link
+android.app.FragmentTransaction#add(int,Fragment) add()}, dengan menetapkan fragmen yang akan ditambahkan dan
+tampilan tempat menyisipkannya. Misalnya:</p>
+
+<pre>
+ExampleFragment fragment = new ExampleFragment();
+fragmentTransaction.add(R.id.fragment_container, fragment);
+fragmentTransaction.commit();
+</pre>
+
+  <p>Argumen pertama yang diteruskan ke {@link android.app.FragmentTransaction#add(int,Fragment) add()}
+ adalah {@link android.view.ViewGroup} tempat fragmen harus dimasukkan, yang ditetapkan oleh
+ID sumber daya, dan parameter kedua merupakan fragmen yang akan ditambahkan.</p>
+  <p>Setelah membuat perubahan dengan
+{@link android.app.FragmentTransaction}, Anda harus
+ memanggil {@link android.app.FragmentTransaction#commit} untuk menerapkan perubahan.</p>
+  </li>
+</ul>
+
+
+<h4 id="AddingWithoutUI">Menambahkan fragmen tanpa UI</h4>
+
+<p>Contoh di atas menampilkan cara menambahkan fragmen ke aktivitas untuk menyediakan UI. Akan tetapi,
+Anda juga bisa menggunakan fragmen untuk menyediakan perilaku latar belakang bagi aktivitas tanpa menampilkan UI
+tambahan.</p>
+
+<p>Untuk menambahkan fragmen tanpa UI, tambahkan fragmen dari aktivitas menggunakan {@link
+android.app.FragmentTransaction#add(Fragment,String)} (dengan menyediakan string unik "tag" untuk fragmen
+, bukan ID tampilan). Ini akan menambahkan fragmen, namun, karena tidak dikaitkan dengan tampilan
+dalam layout aktivitas, ini tidak akan menerima panggilan ke {@link
+android.app.Fragment#onCreateView onCreateView()}. Jadi Anda tidak perlu mengimplementasikan metode itu.</p>
+
+<p>Menyediakan tag string untuk fragmen tidak hanya untuk fragmen non-UI&mdash;Anda juga bisa
+menyediakan tag string untuk fragmen yang memiliki UI&mdash;namun jika fragmen tidak memiliki UI
+, maka tag string adalah satu-satunya cara untuk mengidentifikasinya. Jika Anda ingin mendapatkan fragmen dari
+aktivitas nantinya, Anda perlu menggunakan {@link android.app.FragmentManager#findFragmentByTag
+findFragmentByTag()}.</p>
+
+<p>Untuk contoh aktivitas yang menggunakan fragmen sebagai pekerja latar belakang, tanpa UI, lihat sampel {@code
+FragmentRetainInstance.java}, yang disertakan dalam sampel SDK (tersedia melalui
+Android SDK Manager) dan terletak di sistem Anda sebagai
+<code>&lt;sdk_root&gt;/APIDemos/app/src/main/java/com/example/android/apis/app/FragmentRetainInstance.java</code>.</p>
+
+
+
+<h2 id="Managing">Mengelola Fragmen</h2>
+
+<p>Untuk mengelola fragmen dalam aktivitas, Anda perlu menggunakan {@link android.app.FragmentManager}. Untuk
+mendapatkannya, panggil {@link android.app.Activity#getFragmentManager()} dari aktivitas Anda.</p>
+
+<p>Beberapa hal yang dapat Anda lakukan dengan {@link android.app.FragmentManager} antara lain:</p>
+
+<ul>
+  <li>Dapatkan fragmen yang ada di aktivitas dengan {@link
+android.app.FragmentManager#findFragmentById findFragmentById()} (untuk fragmen yang menyediakan UI dalam
+layout aktivitas) atau {@link android.app.FragmentManager#findFragmentByTag
+findFragmentByTag()} (untuk fragmen yang menyediakan atau tidak menyediakan UI).</li>
+  <li>Tarik fragmen dari back-stack, dengan {@link
+android.app.FragmentManager#popBackStack()} (mensimulasikan perintah <em>Back</em> oleh pengguna).</li>
+  <li>Daftarkan listener untuk perubahan pada back-stack, dengan {@link
+android.app.FragmentManager#addOnBackStackChangedListener addOnBackStackChangedListener()}.</li>
+</ul>
+
+<p>Untuk informasi selengkapnya tentang metode ini dan hal lainnya, lihat dokumentasi kelas {@link
+android.app.FragmentManager}.</p>
+
+<p>Seperti yang ditunjukkan di bagian sebelumnya, Anda juga bisa menggunakan {@link android.app.FragmentManager}
+untuk membuka {@link android.app.FragmentTransaction}, sehingga Anda bisa melakukan transaksi, seperti
+menambah dan menghapus fragmen.</p>
+
+
+<h2 id="Transactions">Melakukan Transaksi Fragmen</h2>
+
+<p>Fitur menarik terkait penggunaan fragmen di aktivitas adalah kemampuan menambah, menghapus, mengganti,
+dan melakukan tindakan lain dengannya, sebagai respons atas interaksi pengguna. Setiap set perubahan
+yang Anda lakukan untuk aktivitas disebut transaksi dan Anda bisa melakukan transaksi menggunakan API di {@link
+android.app.FragmentTransaction}. Anda juga bisa menyimpan setiap transaksi ke back-stack yang dikelola
+aktivitas, sehingga pengguna bisa mengarah mundur melalui perubahan fragmen (mirip mengarah
+mundur melalui aktivitas).</p>
+
+<p>Anda bisa mengambil instance {@link android.app.FragmentTransaction} dari {@link
+android.app.FragmentManager} seperti ini:</p>
+
+<pre>
+FragmentManager fragmentManager = {@link android.app.Activity#getFragmentManager()};
+FragmentTransaction fragmentTransaction = fragmentManager.{@link android.app.FragmentManager#beginTransaction()};
+</pre>
+
+<p>Setiap transaksi merupakan serangkaian perubahan yang ingin dilakukan pada waktu yang sama. Anda bisa
+mengatur semua perubahan yang ingin dilakukan untuk transaksi mana saja menggunakan metode seperti {@link
+android.app.FragmentTransaction#add add()}, {@link android.app.FragmentTransaction#remove remove()},
+dan {@link android.app.FragmentTransaction#replace replace()}. Kemudian, untuk menerapkan transaksi
+pada aktivitas, Anda harus memanggil {@link android.app.FragmentTransaction#commit()}.</p>
+</dl>
+
+<p>Akan tetapi, sebelum memanggil {@link
+android.app.FragmentTransaction#commit()}, Anda mungkin perlu memanggil {@link
+android.app.FragmentTransaction#addToBackStack addToBackStack()}, untuk menambahkan transaksi
+ke back-stack dari transaksi fragmen. Back-stack ini dikelola oleh aktivitas dan memungkinkan
+pengguna kembali ke status fragmen sebelumnya, dengan menekan tombol <em>Back</em>.</p>
+
+<p>Misalnya, berikut ini cara mengganti satu fragmen dengan yang fragmen yang lain, dan mempertahankan
+status sebelumnya di back-stack:</p>
+
+<pre>
+// Create new fragment and transaction
+Fragment newFragment = new ExampleFragment();
+FragmentTransaction transaction = getFragmentManager().beginTransaction();
+
+// Replace whatever is in the fragment_container view with this fragment,
+// and add the transaction to the back stack
+transaction.replace(R.id.fragment_container, newFragment);
+transaction.addToBackStack(null);
+
+// Commit the transaction
+transaction.commit();
+</pre>
+
+<p>Dalam contoh ini, {@code newFragment} menggantikan fragmen apa saja (jika ada) yang saat ini berada dalam
+kontainer layout yang diidentifikasi oleh ID {@code R.id.fragment_container}. Dengan memanggil @link
+android.app.FragmentTransaction#addToBackStack addToBackStack()}, transaksi yang diganti
+disimpan ke back-stack sehingga pengguna bisa membalikkan transaksi dan mengembalikan fragmen
+sebelumnya dengan menekan tombol <em>Back</em>.</p>
+
+<p>Jika Anda menambahkan beberapa perubahan pada transaksi (seperti {@link
+android.app.FragmentTransaction#add add()} atau {@link android.app.FragmentTransaction#remove
+remove()}) dan panggil {@link
+android.app.FragmentTransaction#addToBackStack addToBackStack()}, maka semua perubahan akan diterapkan
+sebelum Anda memanggil {@link android.app.FragmentTransaction#commit commit()} akan ditambahkan ke
+back-stack sebagai satu transaksi dan tombol <em>Back</em> akan membalikannya semua.</p>
+
+<p>Urutan menambahkan perubahan pada {@link android.app.FragmentTransaction} tidak berpengaruh,
+kecuali:</p>
+<ul>
+  <li>Anda harus memanggil {@link android.app.FragmentTransaction#commit()} paling akhir</li>
+  <li>Jika Anda menambahkan beberapa fragmen ke kontainer yang sama, maka
+urutan penambahannya akan menentukan urutan munculnya dalam hierarki tampilan</li>
+</ul>
+
+<p>Jika Anda tidak memanggil {@link android.app.FragmentTransaction#addToBackStack(String)
+addToBackStack()} saat melakukan transaksi yang menghapus fragmen, maka fragmen itu
+akan dimusnahkan bila transaksi diikat dan pengguna tidak bisa mengarah kembali ke sana. Sedangkan, jika
+Anda memanggil {@link android.app.FragmentTransaction#addToBackStack(String) addToBackStack()} saat
+menghapus fragmen, maka fragmen itu akan <em>dihentikan</em> dan akan dilanjutkan jika pengguna mengarah
+kembali.</p>
+
+<p class="note"><strong>Tip:</strong> Untuk setiap transaksi fragmen, Anda bisa menerapkan animasi
+transisi, dengan memanggil {@link android.app.FragmentTransaction#setTransition setTransition()} sebelum
+mengikatnya.</p>
+
+<p>Memanggil {@link android.app.FragmentTransaction#commit()} tidak akan langsung menjalankan
+transaksi. Namun sebuah jadwal akan dibuat untuk dijalankan pada thread UI aktivitas (thread "utama")
+begitu thread bisa melakukannya. Akan tetapi, jika perlu Anda bisa memanggil {@link
+android.app.FragmentManager#executePendingTransactions()} dari thread UI untuk segera
+mengeksekusi transaksi yang diserahkan oleh {@link android.app.FragmentTransaction#commit()}. Hal itu
+biasanya tidak perlu kecuali jika transaksi merupakan dependensi bagi pekerjaan dalam thread lain.</p>
+
+<p class="caution"><strong>Perhatian:</strong> Anda bisa mengikat transaksi menggunakan {@link
+android.app.FragmentTransaction#commit commit()} hanya sebelum aktivitas <a href="{@docRoot}guide/components/activities.html#SavingActivityState">menyimpan
+statusnya</a> (saat pengguna meninggalkan aktivitas). Jika Anda mencoba mengikatnya setelah itu,
+eksepsi akan dilontarkan. Ini karena status setelah pengikatan bisa hilang jika aktivitas
+perlu dipulihkan. Untuk situasi yang memperbolehkan Anda meniadakan pengikatan (commit), gunakan {@link
+android.app.FragmentTransaction#commitAllowingStateLoss()}.</p>
+
+
+
+
+<h2 id="CommunicatingWithActivity">Berkomunikasi dengan Aktivitas</h2>
+
+<p>Meskipun {@link android.app.Fragment} diimplementasikan sebagai objek yang tidak bergantung pada
+{@link android.app.Activity} dan bisa digunakan dalam banyak aktivitas, instance tertentu
+dari fragmen secara langsung terkait dengan aktivitas yang dimuatnya.</p>
+
+<p>Khususnya, fragmen bisa mengakses instance {@link android.app.Activity} dengan {@link
+android.app.Fragment#getActivity()} dan dengan mudah melakukan tugas-tugas seperti mencari tampilan dalam
+ layout aktivitas:</p>
+
+<pre>
+View listView = {@link android.app.Fragment#getActivity()}.{@link android.app.Activity#findViewById findViewById}(R.id.list);
+</pre>
+
+<p>Demikian pula, aktivitas Anda bisa memanggil metode di fragmen dengan meminta acuan ke
+{@link android.app.Fragment} dari {@link android.app.FragmentManager}, menggunakan {@link
+android.app.FragmentManager#findFragmentById findFragmentById()} atau {@link
+android.app.FragmentManager#findFragmentByTag findFragmentByTag()}. Misalnya:</p>
+
+<pre>
+ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);
+</pre>
+
+
+<h3 id="EventCallbacks">Membuat callback kejadian pada aktivitas</h3>
+
+<p>Dalam beberapa kasus, Anda mungkin perlu fragmen untuk berbagi kejadian dengan aktivitas. Cara yang baik untuk melakukannya
+adalah mendefinisikan antarmuka callback di dalam fragmen dan mengharuskan aktivitas host
+mengimplementasikannya. Saat aktivitas menerima callback melalui antarmuka, aktivitas akan bisa berbagi informasi itu
+dengan fragmen lain dalam layout jika perlu.</p>
+
+<p>Misalnya, jika sebuah aplikasi berita memiliki dua fragmen dalam aktivitas&mdash;satu untuk menampilkan daftar
+artikel (fragmen A) dan satu lagi untuk menampilkan artikel (fragmen B)&mdash;maka fragmen A harus
+memberi tahu aktivitas bila item daftar dipilih sehingga aktivitas bisa memberi tahu fragmen B untuk menampilkan artikel. Dalam
+hal ini, antarmuka {@code OnArticleSelectedListener} dideklarasikan di dalam fragmen A:</p>
+
+<pre>
+public static class FragmentA extends ListFragment {
+    ...
+    // Container Activity must implement this interface
+    public interface OnArticleSelectedListener {
+        public void onArticleSelected(Uri articleUri);
+    }
+    ...
+}
+</pre>
+
+<p>Selanjutnya aktivitas yang menjadi host fragmen akan mengimplementasikan antarmuka {@code OnArticleSelectedListener}
+ dan
+mengesampingkan {@code onArticleSelected()} untuk memberi tahu fragmen B mengenai kejadian dari fragmen A. Untuk memastikan
+bahwa aktivitas host mengimplementasikan antarmuka ini, metode callback fragmen A {@link
+android.app.Fragment#onAttach onAttach()} (yang dipanggil sistem saat menambahkan
+fragmen ke aktivitas) membuat instance {@code OnArticleSelectedListener} dengan
+membuat {@link android.app.Activity} yang diteruskan ke {@link android.app.Fragment#onAttach
+onAttach()}:</p>
+
+<pre>
+public static class FragmentA extends ListFragment {
+    OnArticleSelectedListener mListener;
+    ...
+    &#64;Override
+    public void onAttach(Activity activity) {
+        super.onAttach(activity);
+        try {
+            mListener = (OnArticleSelectedListener) activity;
+        } catch (ClassCastException e) {
+            throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
+        }
+    }
+    ...
+}
+</pre>
+
+<p>Jika aktivitas belum mengimplementasikan antarmuka, maka fragmen akan melontarkan
+{@link java.lang.ClassCastException}.
+Jika berhasil, anggota {@code mListener} yang menyimpan acuan ke implementasi aktivitas
+{@code OnArticleSelectedListener}, sehingga fragmen A bisa berbagi kejadian dengan aktivitas, dengan memanggil metode
+yang didefinisikan oleh antarmuka {@code OnArticleSelectedListener}. Misalnya, jika fragmen A adalah
+ekstensi dari {@link android.app.ListFragment}, maka setiap kali
+pengguna mengklik item daftar, sistem akan memanggil {@link android.app.ListFragment#onListItemClick
+onListItemClick()} di fragmen, yang selanjutnya memanggil {@code onArticleSelected()} untuk berbagi
+kejadian dengan aktivitas:</p>
+
+<pre>
+public static class FragmentA extends ListFragment {
+    OnArticleSelectedListener mListener;
+    ...
+    &#64;Override
+    public void onListItemClick(ListView l, View v, int position, long id) {
+        // Append the clicked item's row ID with the content provider Uri
+        Uri noteUri = ContentUris.{@link android.content.ContentUris#withAppendedId withAppendedId}(ArticleColumns.CONTENT_URI, id);
+        // Send the event and Uri to the host activity
+        mListener.onArticleSelected(noteUri);
+    }
+    ...
+}
+</pre>
+
+<p>Parameter {@code id} yang diteruskan ke {@link
+android.app.ListFragment#onListItemClick onListItemClick()} merupakan ID baris dari item yang diklik,
+yang digunakan aktivitas (atau fragmen lain) untuk mengambil artikel dari {@link
+android.content.ContentProvider} aplikasi.</p>
+
+<p><!--To see a complete implementation of this kind of callback interface, see the <a
+href="{@docRoot}resources/samples/NotePad/index.html">NotePad sample</a>. -->Informasi selengkapnya tentang
+menggunakan penyedia konten tersedia dalam dokumen <a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Konten</a>.</p>
+
+
+
+<h3 id="ActionBar">Menambahkan item ke Action-Bar</h3>
+
+<p>Fragmen Anda bisa menyumbangkan item menu ke <a href="{@docRoot}guide/topics/ui/menus.html#options-menu">Menu Opsi</a> aktivitas (dan, konsekuensinya, <a href="{@docRoot}guide/topics/ui/actionbar.html">Action-Bar</a>) dengan mengimplementasikan
+{@link android.app.Fragment#onCreateOptionsMenu(Menu,MenuInflater) onCreateOptionsMenu()}. Agar
+metode ini bisa menerima panggilan, Anda harus memanggil {@link
+android.app.Fragment#setHasOptionsMenu(boolean) setHasOptionsMenu()} selama {@link
+android.app.Fragment#onCreate(Bundle) onCreate()}, untuk menunjukkan bahwa fragmen
+ingin menambahkan item ke Menu Opsi (jika tidak, fragmen tidak akan menerima panggilan ke
+{@link android.app.Fragment#onCreateOptionsMenu onCreateOptionsMenu()}).</p>
+
+<p>Setiap item yang selanjutnya Anda tambahkan ke Menu Opsi dari fragmen akan ditambahkan ke item menu
+yang ada. Fragmen juga menerima callback ke {@link
+android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} bila item menu
+dipilih.</p>
+
+<p>Anda juga bisa mendaftarkan tampilan dalam layout fragmen untuk menyediakan menu konteks dengan memanggil {@link
+android.app.Fragment#registerForContextMenu(View) registerForContextMenu()}. Bila pengguna
+membuka menu konteks, fragmen akan menerima panggilan ke {@link
+android.app.Fragment#onCreateContextMenu(ContextMenu,View,ContextMenu.ContextMenuInfo)
+onCreateContextMenu()}. Bila pengguna memilih item, fragmen akan menerima panggilan ke @link
+android.app.Fragment#onContextItemSelected(MenuItem) onContextItemSelected()}.</p>
+
+<p class="note"><strong>Catatan:</strong> Walaupun fragmen menerima callback pada item yang dipilih
+untuk setiap item menu yang ditambahkannya, aktivitaslah yang pertama kali menerima masing-masing callback saat pengguna
+memilih item menu. Jika implementasi aktivitas dari callback bila-item-dipilih,
+tidak menangani item yang dipilih, maka kejadian akan diteruskan ke callback fragmen. Ini berlaku
+untuk Menu Opsi dan menu konteks.</p>
+
+<p>Untuk informasi selengkapnya tentang menu, lihat panduan pengembang <a href="{@docRoot}guide/topics/ui/menus.html">Menu</a> dan <a href="{@docRoot}guide/topics/ui/actionbar.html">Action-Bar</a>.</p>
+
+
+
+
+<h2 id="Lifecycle">Menangani Daur Hidup Fragmen</h2>
+
+<div class="figure" style="width:350px">
+<img src="{@docRoot}images/activity_fragment_lifecycle.png" alt="" />
+<p class="img-caption"><strong>Gambar 3.</strong> Efek daur hidup aktivitas pada daur hidup
+fragmen.</p>
+</div>
+
+<p>Mengelola daur hidup fragmen mirip sekali dengan mengelola daur hidup aktivitas. Seperti
+aktivitas, fragmen bisa berada dalam tiga status:</p>
+
+<dl>
+  <dt><i>Dilanjutkan</i></dt>
+    <dd>Fragmen terlihat dalam aktivitas yang berjalan.</dd>
+
+  <dt><i>Dihentikan sementara</i></dt>
+    <dd>Aktivitas lain berada di latar depan dan memiliki fokus, namun aktivitas tempat fragmen berada
+masih terlihat (aktivitas latar depan sebagian terlihat atau tidak menutupi
+seluruh layar).</dd>
+
+  <dt><i>Dihentikan</i></dt>
+    <dd>Fragmen tidak terlihat. Aktivitas host telah dihentikan atau
+fragmen telah dihapus dari aktivitas namun ditambahkan ke back-stack. Fragmen yang dihentikan
+masih hidup (semua status dan informasi anggota masih disimpan oleh sistem). Akan tetapi, fragmen
+tidak terlihat lagi oleh pengguna dan akan dimatikan jika aktivitas dimatikan.</dd>
+</dl>
+
+<p>Seperti halnya aktivitas, Anda bisa mempertahankan status fragmen menggunakan {@link
+android.os.Bundle}, jika proses aktivitas dimatikan dan Anda harus memulihkan status
+fragmen bila aktivitas dibuat kembali. Anda bisa menyimpan status selama callback {@link
+android.app.Fragment#onSaveInstanceState onSaveInstanceState()} fragmen dan memulihkannya selama
+{@link android.app.Fragment#onCreate onCreate()}, {@link
+android.app.Fragment#onCreateView onCreateView()}, atau {@link
+android.app.Fragment#onActivityCreated onActivityCreated()}. Untuk informasi selengkapnya tentang menyimpan
+status, lihat dokumen <a href="{@docRoot}guide/components/activities.html#SavingActivityState">Aktivitas</a>
+.</p>
+
+<p>Perbedaan paling signifikan dalam daur hidup antara aktivitas dan fragmen ada
+pada cara penyimpanannya dalam back-stack masing-masing. Aktivitas ditempatkan ke back-stack aktivitas
+yang dikelola oleh sistem saat dihentikan, secara default (sehingga pengguna bisa mengarah kembali
+ke aktivitas dengan tombol <em>Back</em>, seperti yang dibahas dalam <a href="{@docRoot}guide/components/tasks-and-back-stack.html">Tugas dan Back-Stack</a>).
+Akan tetapi, fragmen yang ditempatkan ke back-stack dikelola oleh aktivitas host hanya saat
+Anda secara eksplisit meminta agar instance disimpan dengan memanggil {@link
+android.app.FragmentTransaction#addToBackStack(String) addToBackStack()} selama transaksi yang
+menghapus fragmen.</p>
+
+<p>Jika tidak, pengelolaan daur hidup fragmen mirip sekali dengan mengelola daur hidup
+aktivitas. Jadi, praktik yang sama untuk <a href="{@docRoot}guide/components/activities.html#Lifecycle">mengelola daur hidup
+aktivitas</a> juga berlaku untuk fragmen. Namun yang perlu juga Anda pahami adalah bagaimana hidup
+aktivitas memengaruhi hidup fragmen.</p>
+
+<p class="caution"><strong>Perhatian:</strong> Jika Anda memerlukan objek {@link android.content.Context}
+ dalam {@link android.app.Fragment}, Anda bisa memanggil {@link android.app.Fragment#getActivity()}.
+Akan tetapi, berhati-hatilah memanggil {@link android.app.Fragment#getActivity()} hanya bila fragmen
+terkait dengan aktivitas. Bila fragmen belum terkait, atau terlepas selama akhir daur
+hidupnya, {@link android.app.Fragment#getActivity()} akan kembali nol.</p>
+
+
+<h3 id="CoordinatingWithActivity">Mengoordinasi dengan daur hidup aktivitas</h3>
+
+<p>Daur hidup aktivitas tempat fragmen berada akan memengaruhi langsung siklus hidup
+fragmen sedemikian rupa sehingga setiap callback daur hidup aktivitas menghasilkan callback yang sama untuk masing-masing
+fragmen. Misalnya, bila aktivitas menerima {@link android.app.Activity#onPause}, masing-masing
+fragmen dalam aktivitas akan menerima {@link android.app.Fragment#onPause}.</p>
+
+<p>Namun fragmen memiliki beberapa callback daur hidup ekstra, yang menangani interaksi
+unik dengan aktivitas untuk melakukan tindakan seperti membangun dan memusnahkan UI fragmen. Metode callback
+tambahan ini adalah:</p>
+
+<dl>
+  <dt>{@link android.app.Fragment#onAttach onAttach()}</dt>
+    <dd>Dipanggil bila fragmen telah dikaitkan dengan aktivitas ({@link
+android.app.Activity} diteruskan di sini).</dd>
+  <dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt>
+    <dd>Dipanggil untuk membuat hierarki tampilan yang dikaitkan dengan fragmen.</dd>
+  <dt>{@link android.app.Fragment#onActivityCreated onActivityCreated()}</dt>
+    <dd>Dipanggil bila metode {@link android.app.Activity#onCreate
+onCreate()} aktivitas telah dikembalikan.</dd>
+  <dt>{@link android.app.Fragment#onDestroyView onDestroyView()}</dt>
+    <dd>Dipanggil bila hierarki tampilan yang terkait dengan fragmen dihapus.</dd>
+  <dt>{@link android.app.Fragment#onDetach onDetach()}</dt>
+    <dd>Dipanggil bila fragmen diputuskan dari aktivitas.</dd>
+</dl>
+
+<p>Aliran daur hidup fragmen, karena dipengaruhi oleh aktivitas host-nya, diilustrasikan oleh
+gambar 3. Dalam gambar ini, Anda bisa melihat bagaimana setiap status aktivitas menentukan
+metode callback mana yang mungkin diterima fragmen. Misalnya, saat aktivitas menerima call back {@link
+android.app.Activity#onCreate onCreate()}, fragmen dalam aktivitas akan menerima tidak lebih
+dari callback {@link android.app.Fragment#onActivityCreated onActivityCreated()}.</p>
+
+<p>Setelah status aktivitas diteruskan kembali, Anda bisa bebas menambah dan menghapus fragmen untuk
+aktivitas tersebut. Sehingga, hanya saat aktivitas berada dalam status dilanjutkan, daur hidup fragmen bisa
+berubah secara independen.</p>
+
+<p>Akan tetapi, saat aktivitas meninggalkan status dilanjutkan, fragmen akan kembali didorong
+melalui daur hidupnya oleh aktivitas.</p>
+
+
+
+
+<h2 id="Example">Contoh</h2>
+
+<p>Untuk merangkum semua yang telah dibahas dalam dokumen ini, berikut ini contoh aktivitas
+yang menggunakan dua fragmen untuk membuat layout dua panel. Aktivitas di bawah ini menyertakan satu fragmen untuk
+menampilkan daftar putar Shakespeare dan fragmen lainnya menampilkan rangkuman pemutaran bila dipilih dari
+daftar. Aktivitas ini juga menunjukkan cara menyediakan konfigurasi fragmen berbeda,
+berdasarkan konfigurasi layar.</p>
+
+<p class="note"><strong>Catatan:</strong> Kode sumber lengkap untuk aktivitas ini tersedia di
+<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.html">{@code
+FragmentLayout.java}</a>.</p>
+
+<p>Aktivitas utama akan menerapkan layout seperti biasa, selama {@link
+android.app.Activity#onCreate onCreate()}:</p>
+
+{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java main}
+
+<p>Layout yang diterapkan adalah {@code fragment_layout.xml}:</p>
+
+{@sample development/samples/ApiDemos/res/layout-land/fragment_layout.xml layout}
+
+<p>Dengan layout ini, sistem akan membuat instance {@code TitlesFragment} (yang mencantumkan
+judul) segera setelah aktivitas memuat layout, sementara {@link android.widget.FrameLayout}
+ (lokasi penempatan fragmen untuk menampilkan rangkuman pemutaran) menempati ruang di sisi kanan
+layar, namun pada awalnya masih kosong. Seperti yang akan Anda lihat di bawah ini, sampai pengguna memilih item
+dari daftar maka fragmen baru akan ditempatkan ke dalam {@link android.widget.FrameLayout}.</p>
+
+<p>Akan tetapi, tidak semua konfigurasi layar cukup lebar untuk menampilkan
+daftar putar dan rangkuman secara berdampingan. Sehingga, layout di atas hanya digunakan untuk konfigurasi
+layar mendatar, dengan menyimpannya di {@code res/layout-land/fragment_layout.xml}.</p>
+
+<p>Sehingga, bila layar berada dalam orientasi tegak, sistem akan menerapkan layout berikut, yang
+tersimpan di {@code res/layout/fragment_layout.xml}:</p>
+
+{@sample development/samples/ApiDemos/res/layout/fragment_layout.xml layout}
+
+<p>Layout ini hanya menyertakan {@code TitlesFragment}. Ini artinya saat perangkat berada dalam
+orientasi tegak, hanya judul daftar putar yang terlihat. Jadi, saat pengguna mengklik item
+daftar dalam konfigurasi ini, aplikasi akan memulai aktivitas baru untuk menampilkan rangkuman,
+sebagai ganti pemuatan fragmen kedua.</p>
+
+<p>Berikutnya, Anda bisa melihat bagaimana hal ini dilakukan dalam kelas fragmen. Pertama adalah {@code
+TitlesFragment}, yang menampilkan judul daftar putar Shakespeare. Fragmen ini membuat ekstensi {@link
+android.app.ListFragment} dan mengandalkannya itu untuk menangani sebagian besar pekerjaan tampilan daftar.</p>
+
+<p>Saat Anda memeriksa kode ini, perhatikan bahwa ada dua kemungkinan perilaku saat pengguna mengklik
+item daftar: bergantung pada layout mana yang aktif, bisa membuat dan menampilkan fragmen
+baru untuk menampilkan detail dalam aktivitas yang sama (menambahkan fragmen ke {@link
+android.widget.FrameLayout}), atau memulai aktivitas baru (tempat fragmen ditampilkan).</p>
+
+{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java titles}
+
+<p>Fragmen kedua, {@code DetailsFragment} menampilkan rangkuman pemutaran untuk item yang dipilih dari
+daftar dari {@code TitlesFragment}:</p>
+
+{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details}
+
+<p>Ingatlah dari kelas {@code TitlesFragment}, bahwa, jika pengguna mengklik item daftar dan
+layout saat ini <em>tidak</em> menyertakan tampilan {@code R.id.details} (yaitu tempat
+{@code DetailsFragment} berada), maka aplikasi memulai aktivitas {@code DetailsActivity}
+untuk menampilkan konten item.</p>
+
+<p>Berikut ini adalah {@code DetailsActivity}, yang hanya menanamkan {@code DetailsFragment} untuk menampilkan rangkuman pemutaran
+yang dipilih saat layar dalam orientasi tegak:</p>
+
+{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java
+details_activity}
+
+<p>Perhatikan bahwa aktivitas ini selesai sendiri jika konfigurasi mendatar, sehingga aktivitas utama
+bisa mengambil alih dan menampilkan {@code DetailsFragment} bersama {@code TitlesFragment}.
+Ini bisa terjadi jika pengguna memulai {@code DetailsActivity} saat dalam orientasi tegak, namun kemudian
+memutarnya menjadi mendatar (yang akan memulai lagi aktivitas saat ini).</p>
+
+
+<p>Untuk contoh lainnya mengenai penggunaan fragmen (dan file sumber lengkap untuk contoh ini),
+lihat aplikasi contoh Demo API yang tersedia di <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/index.html#Fragment">
+ApiDemos</a> (bisa diunduh dari <a href="{@docRoot}resources/samples/get.html">Komponen contoh SDK</a>).</p>
+
+
diff --git a/docs/html-intl/intl/id/guide/components/fundamentals.jd b/docs/html-intl/intl/id/guide/components/fundamentals.jd
new file mode 100644
index 0000000..2c925e9
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/components/fundamentals.jd
@@ -0,0 +1,480 @@
+page.title=Dasar-Dasar Aplikasi
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>Dalam dokumen ini</h2>
+<ol>
+<li><a href="#Components">Komponen Aplikasi</a>
+  <ol>
+    <li><a href="#ActivatingComponents">Mengaktifkan komponen</a></li>
+  </ol>
+</li>
+<li><a href="#Manifest">File Manifes</a>
+  <ol>
+    <li><a href="#DeclaringComponents">Mendeklarasikan komponen</a></li>
+    <li><a href="#DeclaringRequirements">Mendeklarasikan kebutuhan aplikasi</a></li>
+  </ol>
+</li>
+<li><a href="#Resources">Sumber Daya Aplikasi</a></li>
+</ol>
+</div>
+</div>
+
+<p>Aplikasi Android ditulis dalam bahasa pemrograman Java. Android SDK Tools mengkompilasi
+kode Anda&mdash;bersama data dan file sumber daya &mdash;ke dalam APK: <i>Paket Android</i>,
+yaitu file arsip berekstensi {@code .apk}. Satu file APK berisi semua konten
+aplikasi Android dan merupakan file yang digunakan perangkat berbasis Android untuk menginstal aplikasi.</p>
+
+<p>Setelah diinstal di perangkat, setiap aplikasi Android tinggal di sandbox keamanannya sendiri: </p>
+
+<ul>
+ <li>Sistem operasi Android merupakan sistem Linux multi-pengguna yang di dalamnya setiap
+aplikasi adalah pengguna berbeda.</li>
+
+<li>Secara default, sistem menetapkan ID pengguna Linux unik kepada setiap aplikasi (ID ini hanya
+ digunakan oleh sistem dan tidak diketahui aplikasi). Sistem menetapkan izin
+bagi semua file dalam aplikasi sehingga hanya ID pengguna yang diizinkan yang bisa mengaksesnya. </li>
+
+<li>Setiap proses memiliki mesin virtual (VM) sendiri, sehingga kode aplikasi yang berjalan secara terisolasi dari
+aplikasi lainnya.</li>
+
+<li>Secara default, setiap aplikasi berjalan dalam proses Linux-nya sendiri. Android memulai proses
+bila ada komponen aplikasi yang perlu dijalankan, kemudian mematikan proses bila tidak lagi diperlukan
+atau bila sistem harus memulihkan memori untuk digunakan aplikasi lain.</li>
+</ul>
+
+<p>Dengan cara ini, sistem Android mengimplementasikan <em>prinsip privilese minim</em>. Ini berarti,
+secara default aplikasi hanya memiliki akses ke komponen yang diperlukannya untuk melakukan pekerjaannya dan
+tidak lebih dari itu. Hal ini menghasilkan lingkungan yang sangat aman sehingga aplikasi tidak bisa mengakses bagian
+sistem bila tidak diberi izin.</p>
+
+<p>Akan tetapi, ada beberapa cara bagi aplikasi untuk berbagi data dengan aplikasi lain dan bagi aplikasi
+untuk mengakses layanan sistem:</p>
+
+<ul>
+  <li>Dua aplikasi bisa diatur untuk menggunakan ID pengguna Linux yang sama,
+dalam hal ini keduanya bisa saling mengakses file masing-masing.  Untuk menghemat sumber daya sistem, aplikasi dengan ID
+pengguna yang sama juga bisa diatur agar berjalan dalam proses Linux yang sama dan menggunakan VM yang sama (
+aplikasi juga harus ditandatangani dengan sertifikat yang sama).</li>
+  <li>Aplikasi bisa meminta izin akses ke data perangkat seperti kontak
+pengguna, pesan SMS, penyimpanan lepas-pasang (kartu SD), kamera, Bluetooth, dan lainnya. Semua
+izin aplikasi harus diberikan oleh pengguna saat menginstal.</li>
+</ul>
+
+<p>Hal tersebut mencakup dasar-dasar tentang cara aplikasi Android berada di dalam sistem. Bagian dokumen
+selanjutnya memperkenalkan Anda pada:</p>
+<ul>
+  <li>Komponen kerangka kerja inti yang mendefinisikan aplikasi.</li>
+  <li>File manifes tempat Anda mendeklarasikan komponen dan fitur yang diperlukan perangkat
+untuk aplikasi.</li>
+  <li>Sumber daya yang terpisah dari kode aplikasi dan memungkinkan
+aplikasi mengoptimalkan perilakunya untuk beragam konfigurasi perangkat.</li>
+</ul>
+
+
+
+<h2 id="Components">Komponen Aplikasi</h2>
+
+<p>Komponen aplikasi adalah blok pembangun penting dari aplikasi Android.
+Setiap komponen merupakan titik berbeda yang digunakan sistem untuk memasuki aplikasi. Tidak semua komponen
+merupakan titik masuk sebenarnya bagi pengguna dan sebagian saling bergantung, namun masing-masing komponen tersedia
+sebagai kesatuan sendiri dan memainkan peran tertentu&mdash;masing-masing merupakan
+blok pembangun unik yang mendefinisikan perilaku aplikasi secara keseluruhan.</p>
+
+<p>Ada empat macam tipe komponen aplikasi. Setiap tipe memiliki kegunaan tersendiri
+dan daur hidupnya sendiri yang mendefinisikan cara komponen dibuat dan dimusnahkan.</p>
+
+<p>Berikut ini empat tipe komponen aplikasi:</p>
+
+<dl>
+
+<dt><b>Aktivitas</b></dt>
+
+<dd>Sebuah <i>aktivitas</i> mewakili satu layar dengan antarmuka pengguna. Misalnya,
+aplikasi email mungkin memiliki satu aktivitas yang menampilkan daftar email
+baru, aktivitas lain untuk menulis email, dan aktivitas satunya lagi untuk membaca email. Walaupun
+semua aktivitas bekerja sama untuk membentuk pengalaman pengguna yang kohesif dalam aplikasi email,
+masing-masing tidak saling bergantung. Karenanya, aplikasi berbeda bisa memulai
+salah satu aktivitas ini (jika aplikasi email mengizinkannya). Misalnya, aplikasi kamera bisa memulai
+aktivitas dalam aplikasi email yang membuat email baru agar pengguna bisa berbagi gambar.
+
+<p>Aktivitas diimplementasikan sebagai subkelas {@link android.app.Activity} dan Anda bisa mengetahui selengkapnya
+tentang hal ini dalam panduan pengembang <a href="{@docRoot}guide/components/activities.html">Aktivitas</a>
+.</p>
+</dd>
+
+
+<dt><b>Layanan</b></dt>
+
+<dd>Sebuah <i>layanan</i> adalah komponen yang berjalan di latar belakang untuk melakukan
+operasi yang berjalan lama atau untuk melakukan pekerjaan bagi proses jarak jauh. Layanan
+tidak menyediakan antarmuka pengguna. Misalnya, sebuah layanan bisa memutar musik di latar belakang sementara
+pengguna berada dalam aplikasi lain, atau layanan bisa menarik data lewat jaringan tanpa
+memblokir interaksi pengguna dengan aktivitas. Komponen lain, seperti aktivitas, bisa memulai
+layanan dan membiarkannya berjalan atau mengikat layanan untuk berinteraksi dengannya.
+
+<p>Layanan diimplementasikan sebagai subkelas {@link android.app.Service} dan Anda bisa mengetahui selengkapnya
+tentang hal ini dalam panduan
+pengembang <a href="{@docRoot}guide/components/services.html">Layanan</a>.</p>
+</dd>
+
+
+<dt><b>Penyedia konten</b></dt>
+
+<dd>Sebuah <i>penyedia konten</i> mengelola seperangkat data-bersama aplikasi. Anda bisa menyimpan data
+dalam sistem file, database SQLite, di web, atau lokasi penyimpanan permanen lainnya
+yang bisa diakses aplikasi. Melalui penyedia konten, aplikasi lain bisa melakukan query atau bahkan
+memodifikasi data (jika penyedia konten mengizinkannya). Misalnya, sistem Android menyediakan penyedia
+konten yang mengelola informasi kontak pengguna. Karenanya, setiap aplikasi
+dengan izin yang sesuai bisa melakukan query mengenai bagian dari penyedia konten (seperti {@link
+android.provider.ContactsContract.Data}) untuk membaca dan menulis informasi tentang orang tertentu.
+
+<p>Penyedia konten juga berguna untuk membaca dan menulis data privat ke aplikasi Anda
+dan tidak dibagikan. Misalnya, aplikasi contoh <a href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> menggunakan
+penyedia konten untuk menyimpan catatan.</p>
+
+<p>Penyedia konten diimplementasikan sebagai subkelas {@link android.content.ContentProvider}
+dan harus mengimplementasikan seperangkat standar API yang memungkinkan aplikasi
+lain melakukan transaksi. Untuk informasi selengkapnya, lihat panduan pengembang
+<a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Konten</a>.</p>
+</dd>
+
+
+<dt><b>Penerima siaran</b></dt>
+
+<dd>Sebuah <i>penerima siaran</i> adalah komponen yang merespons pengumuman siaran dalam lingkup
+sistem.  Banyak siaran yang berasal dari sistem&mdash;misalnya, siaran yang mengumumkan bahwa
+layar telah dimatikan, baterai lemah, atau gambar telah direkam.
+Aplikasi juga bisa memulai siaran&mdash;misalnya untuk menginformasikan ke
+aplikasi lain bahwa sebagian data telah diunduh ke perangkat dan bisa digunakan aplikasi lain tersebut. Walaupun penerima
+siaran tidak menampilkan antarmuka pengguna, penerima bisa <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">membuat pemberitahuan baris status</a>
+untuk memberi tahu pengguna kapan kejadian siaran dilakukan. Meskipun penerima siaran umumnya cuma menjadi
+"gerbang" untuk komponen lain dan dimaksudkan untuk melakukan pekerjaan dalam jumlah sangat minim. Misalnya
+, penerima siaran bisa menjalankan layanan untuk melakukan beberapa pekerjaan berdasarkan kejadian.
+
+<p>Penerima siaran diimplementasikan sebagai subkelas {@link android.content.BroadcastReceiver}
+dan setiap siaran dikirim sebagai objek {@link android.content.Intent}. Untuk informasi selengkapnya,
+lihat kelas {@link android.content.BroadcastReceiver}.</p>
+</dd>
+
+</dl>
+
+
+
+<p>Aspek unik dari desain sistem Android adalah aplikasi mana pun bisa memulai
+komponen aplikasi lain. Misalnya, jika Anda menginginkan pengguna mengambil
+foto dengan kamera perangkat, bisa saja aplikasi lain yang melakukannya dan aplikasi
+Anda bisa menggunakannya, sebagai ganti mengembangkan aktivitas sendiri untuk mengambil foto. Anda tidak
+harus menyatukan atau bahkan menautkan ke kode dari aplikasi kamera.
+Sebagai gantinya, Anda tinggal memulai aktivitas di aplikasi kamera yang akan mengambil
+foto. Bila selesai, foto akan dikembalikan ke aplikasi sehingga Anda bisa menggunakannya. Bagi pengguna,
+kamera seakan menjadi bagian dari aplikasi Anda.</p>
+
+<p>Saat sistem memulai komponen, sistem akan memulai proses untuk aplikasi itu (jika
+belum berjalan) dan membuat instance kelas yang diperlukan untuk komponen. Misalnya, jika aplikasi Anda
+memulai aktivitas dalam aplikasi kamera yang mengambil foto, aktivitas itu akan
+berjalan dalam proses yang dimiliki oleh aplikasi kamera, bukan dalam proses aplikasi Anda.
+Karenanya, tidak seperti aplikasi di sebagian besar sistem lain, aplikasi Android tidak memiliki titik
+masuk tunggal (misalnya tidak ada fungsi {@code main()}).</p>
+
+<p>Karena sistem menjalankan setiap aplikasi dalam proses terpisah dengan izin file yang
+membatasi akses ke aplikasi lain, aplikasi Anda tidak bisa langsung mengaktifkan komponen dari aplikasi lain. Akan tetapi, sistem
+Android bisa melakukannya. Jadi, untuk mengaktifkan
+komponen dalam aplikasi lain, Anda harus mengirim pesan ke sistem yang menetapkan <em>intent</em> Anda untuk memulai
+komponen tertentu. Selanjutnya sistem akan mengaktifkan komponen untuk Anda.</p>
+
+
+<h3 id="ActivatingComponents">Mengaktifkan Komponen</h3>
+
+<p>Tiga dari empat tipe komponen&mdash;aktivitas, layanan, dan
+penerima siaran&mdash;diaktifkan oleh pesan asinkron yang disebut <em>intent</em>.
+Intent saling mengikat setiap komponen saat runtime (Anda bisa menganggapnya
+sebagai pembawa pesan yang meminta tindakan dari komponen lain), baik komponen itu milik aplikasi Anda
+atau milik aplikasi lain.</p>
+
+<p>Intent dibuat dengan objek {@link android.content.Intent}, yang mendefinisikan pesan untuk
+mengaktifkan komponen tertentu atau komponen <em>tipe</em> komponen tertentu&mdash;masing-masing intent
+bisa eksplisit atau implisit.</p>
+
+<p>Untuk aktivitas dan layanan, intent mendefinisikan tindakan yang akan dilakukan (misalnya, untuk "melihat" atau
+"mengirim" sesuatu) dan mungkin menetapkan URI data untuk ditindaklanjuti (salah satu hal yang mungkin perlu diketahui
+oleh komponen yang akan dimulai). Misalnya, intent mungkin menyampaikan permintaan suatu
+aktivitas untuk menampilkan gambar atau membuka halaman web. Dalam beberapa kasus, Anda bisa memulai
+aktivitas untuk menerima hasil, dalam hal ini, aktivitas juga akan mengembalikan hasil
+dalam {@link android.content.Intent} (misalnya Anda bisa mengeluarkan intent agar
+pengguna bisa memilih kontak pribadi dan memintanya dikembalikan kepada Anda&mdash;intent yang dikembalikan menyertakan URI yang
+menunjuk ke kontak yang dipilih).</p>
+
+<p>Untuk penerima siaran, intent hanya mendefinisikan
+pengumuman yang sedang disiarkan (misalnya, siaran untuk menunjukkan baterai perangkat hampir habis
+hanya menyertakan string tindakan yang menunjukkan "baterai hampir habis").</p>
+
+<p>Tipe komponen lainnya dan penyedia konten, tidak diaktifkan oleh intent. Melainkan
+diaktifkan saat ditargetkan oleh permintaan dari {@link android.content.ContentResolver}. Resolver
+konten menangani semua transaksi langsung dengan penyedia konten sehingga komponen yang melakukan
+transaksi dengan penyedia tidak perlu dan sebagai gantinya memanggil metode pada objek {@link
+android.content.ContentResolver}. Ini membuat lapisan abstraksi antara penyedia
+konten dan komponen yang meminta informasi (demi keamanan).</p>
+
+<p>Ada beberapa metode terpisah untuk mengaktifkan masing-masing tipe komponen:</p>
+<ul>
+  <li>Anda bisa memulai aktivitas (atau memberinya pekerjaan baru) dengan
+meneruskan {@link android.content.Intent} ke {@link android.content.Context#startActivity
+startActivity()} atau {@link android.app.Activity#startActivityForResult startActivityForResult()}
+(bila Anda ingin aktivitas mengembalikan hasil).</li>
+  <li>Anda bisa memulai layanan (atau memberikan instruksi baru ke layanan yang sedang berlangsung) dengan
+meneruskan {@link android.content.Intent} ke {@link android.content.Context#startService
+startService()}. Atau Anda bisa mengikat ke layanan dengan meneruskan {@link android.content.Intent} ke
+{@link android.content.Context#bindService bindService()}.</li>
+  <li>Anda bisa memulai siaran dengan meneruskan {@link android.content.Intent} ke metode seperti
+{@link android.content.Context#sendBroadcast(Intent) sendBroadcast()}, {@link
+android.content.Context#sendOrderedBroadcast(Intent, String) sendOrderedBroadcast()}, atau {@link
+android.content.Context#sendStickyBroadcast sendStickyBroadcast()}.</li>
+  <li>Anda bisa melakukan query ke penyedia konten dengan memanggil {@link
+android.content.ContentProvider#query query()} pada {@link android.content.ContentResolver}.</li>
+</ul>
+
+<p>Untuk informasi selengkapnya tentang menggunakan intent, lihat dokumen <a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter
+ Intent</a>. Informasi selengkapnya tentang mengaktifkan komponen
+tertentu juga tersedia dalam dokumen berikut: <a href="{@docRoot}guide/components/activities.html">Aktivitas</a>, <a href="{@docRoot}guide/components/services.html">Layanan</a>, {@link
+android.content.BroadcastReceiver} dan <a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Konten</a>.</p>
+
+
+<h2 id="Manifest">File Manifes</h2>
+
+<p>Sebelum sistem Android bisa memulai komponen aplikasi, sistem harus mengetahui
+keberadaan komponen dengan membaca file {@code AndroidManifest.xml} aplikasi (file
+"manifes"). Aplikasi Anda harus mendeklarasikan semua komponennya dalam file ini, yang harus menjadi akar
+dari direktori proyek aplikasi.</p>
+
+<p>Manifes melakukan banyak hal selain mendeklarasikan komponen aplikasi,
+seperti:</p>
+<ul>
+  <li>Mengidentifikasi izin pengguna yang diperlukan aplikasi, seperti akses Internet atau
+akses-baca ke kontak pengguna.</li>
+  <li>Mendeklarasikan <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Level</a>
+ minimum yang diperlukan aplikasi, berdasarkan API yang digunakan aplikasi.</li>
+  <li>Mendeklarasikan fitur perangkat keras dan perangkat lunak yang diperlukan aplikasi, seperti kamera,
+layanan Bluetooth, atau layar multisentuh.</li>
+  <li>Pustaka API aplikasi perlu ditautkan (selain
+API kerangka kerja Android), seperti pustaka
+<a href="http://code.google.com/android/add-ons/google-apis/maps-overview.html">Google Maps.</a></li>
+  <li>Dan lainnya</li>
+</ul>
+
+
+<h3 id="DeclaringComponents">Mendeklarasikan komponen</h3>
+
+<p>Tugas utama manifes adalah menginformasikan komponen aplikasi pada sistem. Misalnya,
+file manifes bisa mendeklarasikan aktivitas sebagai berikut: </p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;manifest ... &gt;
+    &lt;application android:icon="@drawable/app_icon.png" ... &gt;
+        &lt;activity android:name="com.example.project.ExampleActivity"
+                  android:label="@string/example_label" ... &gt;
+        &lt;/activity&gt;
+        ...
+    &lt;/application&gt;
+&lt;/manifest&gt;</pre>
+
+<p>Dalam elemen <code><a
+href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
+, atribut {@code android:icon} menunjuk ke sumber daya untuk ikon yang mengidentifikasi
+aplikasi.</p>
+
+<p>Dalam elemen <code><a
+href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>,
+atribut {@code android:name} menetapkan nama kelas yang sepenuhnya memenuhi syarat subkelas {@link
+android.app.Activity} dan atribut {@code android:label} menetapkan string yang akan
+digunakan sebagai label yang terlihat oleh pengguna untuk aktivitas tersebut.</p>
+
+<p>Anda harus mendeklarasikan semua komponen aplikasi dengan cara ini:</p>
+<ul>
+  <li>Elemen <code><a
+href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code> untuk
+aktivitas</li>
+  <li>Elemen <code><a
+href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code> untuk
+layanan</li>
+  <li>Elemen <code><a
+href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code> untuk
+penerima siaran</li>
+  <li>Elemen <code><a
+href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code> untuk
+penyedia konten</li>
+</ul>
+
+<p>Aktivitas, layanan, dan penyedia konten yang Anda sertakan dalam kode sumber, namun tidak
+dideklarasikan dalam manifes, tidak akan terlihat pada sistem dan, akibatnya, tidak pernah bisa berjalan.  Akan tetapi,
+penerima siaran
+bisa dideklarasikan dalam manifes atau dibuat secara dinamis dalam kode (sebagai objek
+{@link android.content.BroadcastReceiver}) dan didaftarkan pada sistem dengan memanggil
+{@link android.content.Context#registerReceiver registerReceiver()}.</p>
+
+<p>Untuk informasi selengkapnya tentang cara menstrukturkan file manifes untuk aplikasi Anda,
+lihat dokumentasi <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">File AndroidManifest.xml</a>. </p>
+
+
+
+<h3 id="DeclaringComponentCapabilities">Mendeklarasikan kemampuan komponen</h3>
+
+<p>Seperti telah dibahas di atas, dalam <a href="#ActivatingComponents">Mengaktifkan Komponen</a>, Anda bisa menggunakan
+{@link android.content.Intent} untuk memulai aktivitas, layanan, dan penerima siaran. Anda bisa
+melakukannya dengan menamai komponen sasaran secara eksplisit (menggunakan nama kelas komponen) dalam intent. Akan tetapi,
+kemampuan intent sebenarnya ada pada konsep <em>intent implisit</em>. Intent implisit
+cuma menjelaskan tipe tindakan yang akan dilakukan (dan, secara opsional, data tempat Anda ingin
+melakukan tindakan) dan memungkinkan sistem untuk menemukan komponen pada perangkat yang bisa melakukan
+tindakan tersebut dan memulainya. Jika ada banyak komponen yang bisa melakukan tindakan yang dijelaskan oleh intent,
+maka pengguna bisa memilih komponen yang akan digunakan.</p>
+
+<p>Cara sistem mengidentifikasi komponen yang bisa merespons intent adalah dengan membandingkan
+intent yang diterima dengan <i>filter intent</i> yang disediakan dalam file manifes aplikasi lainnya pada
+perangkat.</p>
+
+<p>Bila mendeklarasikan aktivitas dalam manifes aplikasi, secara opsional Anda bisa menyertakan
+filter intent yang mendeklarasikan kemampuan aktivitas agar bisa merespons intent dari
+aplikasi lain. Anda bisa mendeklarasikan filter intent untuk komponen dengan
+menambahkan elemen <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code
+&lt;intent-filter&gt;}</a> sebagai anak elemen deklarasi komponen.</p>
+
+<p>Misalnya, jika Anda telah membangun aplikasi email dengan aktivitas untuk menulis email baru, Anda bisa
+mendeklarasikan filter intent untuk merespons intent "kirim" (untuk mengirim email baru) seperti ini:</p>
+<pre>
+&lt;manifest ... >
+    ...
+    &lt;application ... &gt;
+        &lt;activity android:name="com.example.project.ComposeEmailActivity">
+            &lt;intent-filter>
+                &lt;action android:name="android.intent.action.SEND" />
+                &lt;data android:type="*/*" />
+                &lt;category android:name="android.intent.category.DEFAULT" />
+            &lt;/intent-filter>
+        &lt;/activity>
+    &lt;/application&gt;
+&lt;/manifest>
+</pre>
+
+<p>Kemudian, jika aplikasi lain membuat intent dengan tindakan {@link
+android.content.Intent#ACTION_SEND} dan meneruskannya ke {@link android.app.Activity#startActivity
+startActivity()}, sistem bisa memulai aktivitas Anda agar pengguna bisa menulis draf dan mengirim
+email.</p>
+
+<p>Untuk informasi selengkapnya tentang membuat filter intent, lihat dokumen <a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter Intent</a>.
+</p>
+
+
+
+<h3 id="DeclaringRequirements">Mendeklarasikan kebutuhan aplikasi</h3>
+
+<p>Ada berbagai macam perangkat yang didukung oleh Android dan tidak
+semuanya menyediakan fitur dan kemampuan yang sama. Agar aplikasi Anda tidak dihapus pada perangkat yang tidak memiliki
+fitur yang diperlukan aplikasi, Anda harus jelas mendefinisikan profil mengenai
+tipe perangkat yang didukung aplikasi dengan mendeklarasikan kebutuhan perangkat dan perangkat lunak dalam file
+manifes. Kebanyakan deklarasi ini hanya bersifat informasi dan sistem tidak
+membacanya, namun layanan eksternal seperti Google Play akan membacanya untuk menyediakan
+penyaringan bagi pengguna saat mereka mencari aplikasi dari perangkat.</p>
+
+<p>Misalnya, jika aplikasi memerlukan kamera dan menggunakan API yang disediakan dalam Android 2.1 (<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Level</a> 7)
+, Anda harus mendeklarasikannya sebagai kebutuhan dalam file manifes seperti ini:</p>
+
+<pre>
+&lt;manifest ... >
+    &lt;uses-feature android:name="android.hardware.camera.any"
+                  android:required="true" />
+    &lt;uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" />
+    ...
+&lt;/manifest>
+</pre>
+
+<p>Sekarang, perangkat yang <em>tidak</em> memiliki kamera dan menggunakan
+Android versi <em>lebih rendah</em> dari 2.1 tidak bisa menginstal aplikasi Anda dari Google Play.</p>
+
+<p>Akan tetapi, bisa juga mendeklarasikan bahwa aplikasi Anda menggunakan kamera, namun tidak
+<em>mengharuskannya</em>. Dalam hal itu, aplikasi Anda harus mengatur atribut <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#required">{@code required}</a>
+ ke {@code "false"} dan memeriksa saat runtime apakah
+perangkat memiliki kamera dan menonaktifkan setiap fitur kamera yang sesuai.</p>
+
+<p>Informasi selengkapnya tentang cara mengelola kompatibilitas aplikasi dengan
+perangkat yang berbeda disediakan dalam dokumen
+<a href="{@docRoot}guide/practices/compatibility.html">Kompatibilitas Perangkat</a>.</p>
+
+
+
+<h2 id="Resources">Sumber Daya Aplikasi</h2>
+
+<p>Aplikasi Android tidak hanya terdiri dari kode&mdash;Aplikasi memerlukan sumber daya yang
+terpisah dari kode sumber, seperti gambar, file audio, dan apa saja yang berkaitan dengan
+presentasi visual dari aplikasi. Misalnya, Anda harus mendefinisikan animasi, menu, gaya, warna,
+dan layout antarmuka pengguna aktivitas dengan file XML. Penggunaan sumber daya aplikasi
+mempermudah pembaruan berbagai karakteristik aplikasi Anda tanpa memodifikasi kode dan&mdash;dengan menyediakan
+seperangkat sumber daya alternatif&mdash;memungkinkan Anda mengoptimalkan aplikasi untuk berbagai konfigurasi
+perangkat berbeda (seperti bahasa dan ukuran layar yang berbeda).</p>
+
+<p>Untuk setiap sumber daya yang Anda sertakan dalam proyek Android, alat bawaan SDK akan mendefinisikan ID integer
+unik, yang bisa Anda gunakan untuk mengacu sumber daya dari kode aplikasi atau dari sumber daya lainnya yang
+didefinisikan dalam XML. Misalnya, jika aplikasi berisi file gambar bernama {@code
+logo.png} (disimpan dalam direktori {@code res/drawable/}), alat SDK akan menghasilkan ID sumber daya
+bernama {@code R.drawable.logo}, yang bisa Anda gunakan untuk mengacu gambar dan memasukkannya dalam
+antarmuka pengguna.</p>
+
+<p>Salah satu aspek paling penting dari penyediaan sumber daya yang terpisah dari
+kode sumber adalah kemampuan Anda menyediakan sumber daya alternatif untuk konfigurasi perangkat
+yang berbeda. Misalnya, dengan mendefinisikan string UI dalam XML, Anda bisa menerjemahkan string ke dalam
+bahasa lain dan menyimpan string itu dalam file terpisah. Kemudian, berdasarkan <em>qualifier</em>
+bahasa yang ditambahkan ke nama direktori sumber daya (seperti {@code res/values-fr/} untuk nilai
+string Prancis) dan pengaturan bahasa pengguna, sistem Android akan menerapkan string bahasa yang sesuai
+untuk UI Anda.</p>
+
+<p>Android mendukung banyak <em>qualifier</em> berbeda untuk sumber daya alternatif Anda. Qualifier
+adalah string pendek yang Anda sertakan dalam nama direktori sumber
+daya untuk mendefinisikan konfigurasi perangkat yang harus digunakan sumber daya tersebut. Contoh lainnya,
+Anda harus sering membuat layout berbeda untuk aktivitas, bergantung pada
+orientasi layar dan ukuran perangkat. Misalnya, saat layar perangkat dalam orientasi
+tegak, Anda mungkin ingin layout tombolnya vertikal, tetapi saat layar dalam orientasi
+mendatar, tombolnya harus sejajar horizontal. Untuk mengubah layout
+sesuai orientasi, Anda bisa mendefinisikan dua layout berbeda dan menerapkan qualifier yang
+tepat untuk setiap nama direktori layout. Kemudian, sistem secara otomatis menerapkan
+layout yang tepat sesuai dengan orientasi perangkat saat ini.</p>
+
+<p>Untuk informasi selengkapnya tentang berbagai jenis sumber daya yang bisa disertakan dalam aplikasi dan cara
+membuat sumber daya alternatif untuk konfigurasi perangkat berbeda, bacalah <a href="{@docRoot}guide/topics/resources/providing-resources.html">Menyediakan Sumber Daya</a>.</p>
+
+
+
+<div class="next-docs">
+<div class="col-6">
+  <h2 class="norule">Teruskan membaca tentang:</h2>
+  <dl>
+    <dt><a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter Intent</a>
+    </dt>
+    <dd>Informasi tentang cara menggunakan API {@link android.content.Intent} untuk
+ mengaktifkan komponen aplikasi, seperti aktivitas dan layanan, dan cara menyediakan komponen aplikasi
+ untuk digunakan oleh aplikasi lain.</dd>
+    <dt><a href="{@docRoot}guide/components/activities.html">Aktivitas</a></dt>
+    <dd>Informasi tentang cara membuat instance kelas {@link android.app.Activity},
+yang menyediakan layar tersendiri dalam aplikasi bersama antarmuka pengguna.</dd>
+    <dt><a href="{@docRoot}guide/topics/resources/providing-resources.html">Menyediakan Sumber Daya</a></dt>
+    <dd>Informasi tentang cara aplikasi Android disusun untuk memisahkan sumber daya aplikasi dari
+kode aplikasi, termasuk cara Anda bisa menyediakan sumber daya alternatif untuk
+konfigurasi perangkat tertentu.
+    </dd>
+  </dl>
+</div>
+<div class="col-6">
+  <h2 class="norule">Anda juga mungkin tertarik dengan:</h2>
+  <dl>
+    <dt><a href="{@docRoot}guide/practices/compatibility.html">Kompatibilitas Perangkat</a></dt>
+    <dd>Informasi tentang cara kerja Android pada berbagai tipe perangkat dan
+pengenalan mengenai cara mengoptimalkan aplikasi untuk setiap perangkat atau membatasi ketersediaan aplikasi Anda untuk
+perangkat berbeda.</dd>
+    <dt><a href="{@docRoot}guide/topics/security/permissions.html">Izin Sistem</a></dt>
+    <dd>Informasi tentang cara Android membatasi akses aplikasi pada API tertentu dengan sistem izin
+yang mengharuskan persetujuan pengguna agar aplikasi dapat menggunakan API tersebut.</dd>
+  </dl>
+</div>
+</div>
+
diff --git a/docs/html-intl/intl/id/guide/components/index.jd b/docs/html-intl/intl/id/guide/components/index.jd
new file mode 100644
index 0000000..de40b22
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/components/index.jd
@@ -0,0 +1,57 @@
+page.title=Komponen Aplikasi
+page.landing=true
+page.landing.intro=Kerangka kerja aplikasi Android memungkinkan Anda membuat aplikasi yang kaya dan inovatif menggunakan seperangkat komponen yang dapat digunakan kembali. Bagian ini menjelaskan cara membangun komponen yang mendefinisikan blok pembangun aplikasi Anda dan cara menghubungkannya bersama menggunakan intent.
+page.metaDescription=Kerangka kerja aplikasi Android memungkinkan Anda membuat aplikasi yang kaya dan inovatif menggunakan seperangkat komponen yang dapat digunakan kembali. Bagian ini menjelaskan cara membangun komponen yang mendefinisikan blok pembangun aplikasi Anda dan cara menghubungkannya bersama menggunakan intent.
+page.landing.image=images/develop/app_components.png
+page.image=images/develop/app_components.png
+
+@jd:body
+
+<div class="landing-docs">
+
+  <div class="col-6">
+    <h3>Artikel Blog</h3>
+
+    <a href="http://android-developers.blogspot.com/2012/05/using-dialogfragments.html">
+      <h4>Menggunakan DialogFragments</h4>
+      <p>Dalam posting ini, saya akan menunjukkan cara menggunakan DialogFragments dengan pustaka dukungan v4 (untuk kompatibilitas mundur pada perangkat sebelum Honeycomb) untuk menunjukkan dialog edit sederhana dan mengembalikan hasil ke Aktivitas pemanggil menggunakan antarmuka.</p>
+    </a>
+
+    <a href="http://android-developers.blogspot.com/2011/03/fragments-for-all.html">
+      <h4>Fragmen Untuk Semua</h4>
+      <p>Hari ini kami telah merilis pustaka statis yang memperlihatkan API Fragment yang sama (serta LoaderManager baru dan beberapa kelas lain) agar aplikasi yang kompatibel dengan Android 1.6 atau yang lebih baru bisa menggunakan fragmen untuk membuat antarmuka pengguna yang kompatibel dengan tablet. </p>
+    </a>
+
+    <a href="http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html">
+      <h4>Multithreading untuk Kinerja</h4>
+      <p>Praktik yang baik dalam membuat aplikasi yang responsif adalah memastikan thread UI utama Anda
+melakukan pekerjaan minimum. Setiap tugas yang berpotensi lama dan dapat membuat aplikasi mogok harus
+ditangani di thread berbeda.</p>
+    </a>
+  </div>
+
+  <div class="col-6">
+    <h3>Pelatihan</h3>
+
+    <a href="http://developer.android.com/training/basics/activity-lifecycle/index.html">
+      <h4>Mengelola Daur Hidup Aktivitas</h4>
+      <p>Bagian ini menjelaskan pentingnya metode callback daur hidup yang diterima setiap instance Aktivitas
+dan cara menggunakannya sehingga aktivitas Anda melakukan yang diharapkan pengguna dan tidak menghabiskan sumber daya sistem
+saat aktivitas tidak membutuhkannya.</p>
+    </a>
+
+    <a href="http://developer.android.com/training/basics/fragments/index.html">
+      <h4>Membangun UI Dinamis dengan Fragmen</h4>
+      <p>Bagian ini menunjukkan kepada Anda cara membuat pengalaman pengguna yang dinamis dengan fragmen dan mengoptimalkan
+pengalaman pengguna aplikasi Anda dengan berbagai ukuran layar, sekaligus terus mendukung
+perangkat yang menjalankan versi sebelumnya, sesudah versi Android 1.6.</p>
+    </a>
+
+    <a href="http://developer.android.com/training/sharing/index.html">
+      <h4>Berbagi Konten</h4>
+      <p>Bagian ini membahas beberapa cara umum untuk mengirim dan menerima konten antar
+aplikasi menggunakan API Intent dan objek ActionProvider.</p>
+    </a>
+  </div>
+
+</div>
diff --git a/docs/html-intl/intl/id/guide/components/intents-filters.jd b/docs/html-intl/intl/id/guide/components/intents-filters.jd
new file mode 100644
index 0000000..8e89b5d
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/components/intents-filters.jd
@@ -0,0 +1,899 @@
+page.title=Intent dan Filter Intent
+page.tags="IntentFilter"
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>Dalam dokumen ini</h2>
+<ol>
+  <li><a href="#Types">Tipe Intent</a></li>
+  <li><a href="#Building">Membangun Intent</a>
+    <ol>
+      <li><a href="#ExampleExplicit">Contoh intent eksplisit</a></li>
+      <li><a href="#ExampleSend">Contoh intent implisit</a></li>
+      <li><a href="#ForceChooser">Memaksakan pemilih aplikasi</a></li>
+    </ol>
+  </li>
+  <li><a href="#Receiving">Menerima Intent Implisit</a>
+    <ol>
+      <li><a href="#ExampleFilters">Contoh filter</a></li>
+    </ol>
+  </li>
+  <li><a href="#PendingIntent">Menggunakan Intent Tertunda</a></li>
+  <li><a href="#Resolution">Resolusi Intent</a>
+    <ol>
+      <li><a href="#ActionTest">Pengujian tindakan</a></li>
+      <li><a href="#CategoryTest">Pengujian kategori</a></li>
+      <li><a href="#DataTest">Pengujian data</a></li>
+      <li><a href="#imatch">Pencocokan intent</a></li>
+    </ol>
+  </li>
+</ol>
+
+<h2>Lihat juga</h2>
+<ol>
+<li><a href="{@docRoot}training/basics/intents/index.html">Berinteraksi dengan Aplikasi Lain</a></li>
+<li><a href="{@docRoot}training/sharing/index.html">Berbagi Konten</a></li>
+</ol>
+
+</div>
+</div>
+
+
+
+
+<p>{@link android.content.Intent} merupakan objek pertukaran pesan yang bisa Anda gunakan untuk meminta tindakan
+dari <a href="{@docRoot}guide/components/fundamentals.html#Components">komponen aplikasi</a> lain.
+Walaupun intent memudahkan komunikasi antarkomponen dalam beberapa cara, ada tiga
+kasus-penggunaan dasar:</p>
+
+<ul>
+<li><b>Untuk memulai aktivitas:</b>
+<p>{@link android.app.Activity} menyatakan satu layar dalam aplikasi. Anda bisa memulai instance
+baru {@link android.app.Activity} dengan meneruskan {@link android.content.Intent}
+ke {@link android.content.Context#startActivity startActivity()}. {@link android.content.Intent}
+menjelaskan aktivitas yang akan dimulai dan membawa data yang diperlukan.</p>
+
+<p>Jika Anda ingin menerima hasil dari aktivitas bila selesai,
+panggil {@link android.app.Activity#startActivityForResult
+startActivityForResult()}. Aktivitas Anda menerima hasil
+sebagai objek {@link android.content.Intent} terpisah dalam callback {@link
+android.app.Activity#onActivityResult onActivityResult()} aktivitas Anda.
+Untuk informasi selengkapnya, lihat panduan <a href="{@docRoot}guide/components/activities.html">Aktivitas</a>.</p></li>
+
+<li><b>Untuk memulai layanan:</b>
+<p>{@link android.app.Service} adalah komponen yang melakukan operasi di latar belakang
+tanpa antarmuka pengguna. Anda bisa memulai layanan untuk melakukan operasi satu-kali
+(misalnya mengunduh file) dengan meneruskan {@link android.content.Intent}
+ke {@link android.content.Context#startService startService()}. {@link android.content.Intent}
+menjelaskan layanan yang akan dimulai dan membawa data yang diperlukan.</p>
+
+<p>Jika layanan didesain dengan antarmuka pengguna klien-server, Anda bisa mengikat ke layanan
+dari komponen lain dengan meneruskan {@link android.content.Intent} ke {@link
+android.content.Context#bindService bindService()}</code>. Untuk informasi selengkapnya, lihat panduan <a href="{@docRoot}guide/components/services.html">Layanan</a>.</p></li>
+
+<li><b>Untuk mengirim siaran:</b>
+<p>Siaran adalah pesan yang bisa diterima aplikasi apa saja. Sistem menyampaikan beragam siaran
+untuk kejadian sistem, misalnya saat sistem booting atau saat perangkat mulai mengisi daya.
+Anda bisa mengirim siaran ke aplikasi lain dengan meneruskan {@link android.content.Intent}
+ke {@link android.content.Context#sendBroadcast(Intent) sendBroadcast()},
+{@link android.content.Context#sendOrderedBroadcast(Intent, String)
+sendOrderedBroadcast()}, atau {@link
+android.content.Context#sendStickyBroadcast sendStickyBroadcast()}.</p>
+</li>
+</ul>
+
+
+
+
+<h2 id="Types">Tipe Intent</h2>
+
+<p>Ada dua tipe intent:</p>
+
+<ul>
+<li><b>Intent eksplisit</b> menetapkan komponen untuk memulai dengan nama (
+nama kelas yang sepenuhnya memenuhi syarat). Anda biasanya akan menggunakan intent eksplisit untuk memulai sebuah komponen
+dalam aplikasi sendiri, karena Anda mengetahui nama kelas dari aktivitas atau layanan yang ingin dimulai.
+Misalnya, mulai aktivitas baru sebagai respons terhadap tindakan pengguna atau mulai layanan untuk mengunduh
+file di latar belakang.</li>
+
+<li><b>Intent implisit</b> tidak menetapkan komponen tertentu, melainkan mendeklarasikan tindakan umum
+yang dilakukan, yang memungkinkan komponen aplikasi lain untuk menanganinya. Misalnya, jika Anda ingin
+menampilkan sebuah lokasi di peta pada pengguna, Anda bisa menggunakan intent implisit untuk meminta aplikasi lain
+yang mampu untuk menunjukkan lokasi yang telah ditetapkan di peta tersebut.</li>
+</ul>
+
+<p>Saat Anda membuat intent eksplisit untuk memulai aktivitas atau layanan, sistem akan segera
+memulai komponen aplikasi yang telah ditetapkan dalam objek {@link android.content.Intent}.</p>
+
+<div class="figure" style="width:446px">
+<img src="{@docRoot}images/components/intent-filters@2x.png" width="446" alt="" />
+<p class="img-caption"><strong>Gambar 1.</strong> Ilustrasi yang menggambarkan cara intent implisit
+disampaikan melalui sistem untuk memulai aktivitas lain: <b>[1]</b> <em>Aktivitas A</em> membuat sebuah
+{@link android.content.Intent} dengan keterangan tindakan dan meneruskannya ke {@link
+android.content.Context#startActivity startActivity()}. <b>[2]</b> Sistem Android akan mencari semua
+aplikasi untuk filter intent yang cocok dengan intent tersebut. Bila cocok, <b>[3]</b> sistem akan
+memulai aktivitas mencocokkan (<em>Aktivitas B</em>) dengan memanggil metode {@link
+android.app.Activity#onCreate onCreate()} dan meneruskannya ke {@link android.content.Intent}.
+</p>
+</div>
+
+<p>Bila Anda membuat intent implisit, sistem Android akan menemukan komponen yang sesuai untuk memulai
+dengan membandingkan konten intent dengan <em>filter intent</em> yang dideklarasikan dalam <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">file manifes</a> aplikasi lain di
+perangkat. Jika intent cocok dengan filter intent, sistem akan memulai komponen tersebut dan mengiriminya
+objek {@link android.content.Intent}. Jika banyak filter intent yang kompatibel, sistem
+menampilkan dialog sehingga pengguna bisa memilih aplikasi yang akan digunakan.</p>
+
+<p>Filter intent adalah ekspresi dalam file manifes aplikasi yang
+menetapkan tipe intent yang akan diterima
+komponen. Misalnya, dengan mendeklarasikan intent filter untuk aktivitas,
+Anda akan memungkinkan aplikasi lain untuk langsung memulai aktivitas Anda dengan intent tertentu.
+Demikian pula, jika Anda <em>tidak</em> mendeklarasikan filter intent untuk suatu aktivitas, maka aktivitas tersebut hanya bisa dimulai
+dengan intent eksplisit.</p>
+
+<p class="caution"><strong>Perhatian:</strong> Untuk memastikan aplikasi Anda aman, selalu gunakan intent
+eksplisit saat memulai {@link android.app.Service} dan jangan
+mendeklarasikan filter intent untuk layanan. Menggunakan intent implisit untuk memulai layanan akan menimbulkan
+bahaya keamanan karena Anda tidak bisa memastikan layanan apa yang akan merespons intent,
+dan pengguna tidak bisa melihat layanan mana yang dimulai. Mulai dari Android 5.0 (API level 21), sistem
+melontarkan eksepsi jika Anda memanggil {@link android.content.Context#bindService bindService()}
+dengan intent implisit.</p>
+
+
+
+
+
+<h2 id="Building">Membangun Intent</h2>
+
+<p>Objek {@link android.content.Intent} membawa informasi yang digunakan sistem Android
+untuk menentukan komponen mana yang akan dimulai (misalnya nama persis dari suatu komponen atau kategori
+komponen yang seharusnya menerima intent), ditambah informasi yang digunakan komponen penerima untuk
+melakukan tindakan dengan benar (misalnya tindakan yang harus dilakukan dan data yang harus diolah).</p>
+
+
+<p>Informasi utama yang dimuat dalam {@link android.content.Intent} adalah sebagai berikut:</p>
+
+<dl>
+
+<dt><b>Nama komponen</b></dt>
+<dd>Nama komponen yang akan dimulai.
+
+<p>Ini opsional, namun merupakan bagian informasi penting yang membuat intent
+menjadi <b>eksplisit</b>, yaitu intent harus dikirim hanya ke komponen aplikasi
+yang didefinisikan oleh nama komponen. Tanpa nama komponen, intent menjadi <b>implisit</b> dan
+sistem akan memutuskan komponen mana yang harus menerima intent berdasarkan informasi intent lain
+(misalnya tindakan, data, dan kategori&mdash;yang dijelaskan di bawah ini). Jadi jika Anda ingin memulai komponen
+tertentu dalam aplikasi, Anda harus menetapkan nama komponen tersebut.</p>
+
+<p class="note"><strong>Catatan:</strong> Saat memulai {@link android.app.Service}, Anda harus
+<strong>selalu menetapkan nama komponen</strong>. Jika tidak, maka Anda tidak bisa memastikan layanan apa
+yang akan merespons intent tersebut, dan pengguna tidak bisa melihat layanan mana yang dimulai.</p>
+
+<p>Bidang {@link android.content.Intent} ini adalah objek
+{@link android.content.ComponentName}, yang bisa Anda tetapkan menggunakan
+nama kelas yang sepenuhnya memenuhi syarat dari komponen target, termasuk nama paket aplikasi. Misalnya,
+{@code com.example.ExampleActivity}. Anda bisa mengatur nama komponen dengan {@link
+android.content.Intent#setComponent setComponent()}, {@link android.content.Intent#setClass
+setClass()}, {@link android.content.Intent#setClassName(String, String) setClassName()}, atau dengan konstruktor
+{@link android.content.Intent}.</p>
+
+</dd>
+
+<p><dt><b>Tindakan</b></dt>
+<dd>String yang menetapkan tindakan generik untuk dilakukan (misalnya <em>lihat</em> atau <em>pilih</em>).
+
+<p>Dalam hal intent siaran, ini adalah tindakan yang terjadi dan dilaporkan.
+Tindakan ini sangat menentukan bagaimana keseluruhan intent disusun&mdash;terutama
+apa yang dimuat dalam data dan ekstra.
+
+<p>Anda bisa menetapkan tindakan sendiri yang akan digunakan oleh intent dalam aplikasi Anda (atau digunakan oleh aplikasi
+lain untuk memanggil komponen dalam aplikasi Anda), namun Anda harus menggunakan konstanta tindakan
+yang didefinisikan oleh kelas {@link android.content.Intent} atau kelas kerangka kerja lain. Berikut ini adalah beberapa
+tindakan umum untuk memulai sebuah aktivitas:</p>
+
+<dl>
+<dt>{@link android.content.Intent#ACTION_VIEW}</dt>
+   <dd>Gunakan tindakan ini dalam intent dengan {@link
+   android.content.Context#startActivity startActivity()} saat Anda memiliki beberapa informasi yang
+ bisa ditampilkan aktivitas kepada pengguna, misalnya foto yang bisa dilihat dalam aplikasi galeri, atau alamat
+ yang bisa dilihat dalam aplikasi peta.</dd>
+
+<dt>{@link android.content.Intent#ACTION_SEND}</dt>
+   <dd>Juga dikenal dengan intent "berbagi", Anda harus menggunakannya dalam intent dengan {@link
+   android.content.Context#startActivity startActivity()} bila Anda memiliki data yang bisa digunakan pengguna untuk
+ berbagi melalui aplikasi lain, misalnya aplikasi email atau aplikasi jaringan sosial.</dd>
+</dl>
+
+<p>Lihat referensi kelas {@link android.content.Intent} untuk konstanta
+selengkapnya yang mendefinisikan tindakan generik.  Tindakan lain yang didefinisikan
+di tempat lain dalam kerangka kerja Android, misalnya dalam {@link android.provider.Settings} untuk tindakan
+yang membuka layar tertentu dalam aplikasi Settings di sistem.</p>
+
+<p>Anda bisa menetapkan tindakan untuk sebuah intent dengan {@link android.content.Intent#setAction
+setAction()} atau dengan konstruktor {@link android.content.Intent}.</p>
+
+<p>Jika mendefinisikan tindakan Anda sendiri, pastikan untuk memasukkan nama paket aplikasi Anda
+sebagai awalan. Misalnya:</p>
+<pre>static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";</pre>
+</dd>
+
+<dt><b>Data</b></dt>
+<dd>URI (objek {@link android.net.Uri}) yang mengacu data untuk diolah dan/atau
+tipe MIME dari data tersebut. Tipe data yang disediakan umumnya didikte oleh tindakan intent.
+Misalnya, jika tindakan merupakan {@link android.content.Intent#ACTION_EDIT}, data harus berisi
+URI dari dokumen untuk diedit.
+
+<p>Saat membuat intent,
+seringkali tipe data (tipe MIME-nya) selain URI perlu ditetapkan.
+Misalnya, aktivitas yang mampu menampilkan gambar mungkin tidak mampu
+memutar file audio, walaupun format URI mungkin serupa.
+Jadi menetapkan tipe MIME data Anda akan membantu sistem
+Android menemukan komponen terbaik untuk diterima intent.
+Akan tetapi, tipe MIME seringkali bisa diambil dari URI&mdash;terutama saat datanya merupakan URI
+{@code content:}, yang menunjukkan data tersebut berada di perangkat dan dikontrol oleh
+{@link android.content.ContentProvider}, yang membuat data tipe MIME terlihat di sistem.</p>
+
+<p>Untuk mengatur data URI saja, panggil {@link android.content.Intent#setData setData()}.
+Untuk mengatur tipe MIME saja, panggil {@link android.content.Intent#setType setType()}. Jika perlu, Anda
+bisa mengatur keduanya secara eksplisit dengan {@link
+android.content.Intent#setDataAndType setDataAndType()}.</p>
+
+<p class="caution"><strong>Perhatian:</strong> Jika ingin mengatur tipe URI dan MIME,
+<strong>jangan</strong> panggil {@link android.content.Intent#setData setData()} dan
+{@link android.content.Intent#setType setType()} karena mereka saling menghapuskan nilai satu sama lain.
+Selalu gunakan {@link android.content.Intent#setDataAndType setDataAndType()} untuk mengatur
+tipe URI maupun MIME.</p>
+</dd>
+
+<p><dt><b>Kategori</b></dt>
+<dd>String yang berisi informasi tambahan tentang jenis komponen
+yang harus menangani intent.  Keterangan kategori dalam jumlah berapa pun bisa
+dimasukkan dalam intent, namun sebagian besar intent tidak memerlukan kategori.
+Berikut ini adalah beberapa kategori umum:
+
+<dl>
+<dt>{@link android.content.Intent#CATEGORY_BROWSABLE}</dt>
+  <dd>Aktivitas target memungkinkannya dimulai oleh browser web untuk menampilkan data
+yang diacu oleh tautan&mdash;misalnya gambar atau pesan e-mail.
+  </dd>
+<dt>{@link android.content.Intent#CATEGORY_LAUNCHER}</dt>
+  <dd>Aktivitas tersebut adalah aktivitas awal dari sebuah tugas dan dicantumkan dalam
+       launcher aplikasi sistem.
+  </dd>
+</dl>
+
+<p>Lihat keterangan kelas {@link android.content.Intent} untuk mengetahui daftar lengkap
+kategori.</p>
+
+<p>Anda bisa menetapkan kategori dengan {@link android.content.Intent#addCategory addCategory()}.</p>
+</dd>
+</dl>
+
+
+<p>Properti yang tercantum di atas (nama komponen, tindakan, data, dan kategori) menyatakan
+karakteristik yang mendefinisikan intent. Dengan membaca properti ini, sistem Android
+mampu memutuskan komponen aplikasi yang harus dimulainya.</p>
+
+<p>Akan tetapi, intent bisa membawa informasi tambahan yang tidak memengaruhi
+cara intent ditetapkan pada komponen aplikasi. Intent juga bisa menyediakan:</p>
+
+<dl>
+<dt><b>Ekstra</b></dt>
+<dd>Pasangan nilai-kunci yang membawa informasi yang diperlukan untuk menghasilkan tindakan yang diminta.
+Seperti halnya beberapa tindakan menggunakan jenis tertentu URI data, beberapa tindakan juga menggunakan ekstra tertentu.
+
+<p>Anda bisa menambahkan data ekstra dengan beragam metode {@link android.content.Intent#putExtra putExtra()},
+masing-masing menerima dua parameter: nama kunci dan nilainya.
+Anda juga bisa membuat objek {@link android.os.Bundle} dengan semua data ekstra, kemudian memasukkan
+{@link android.os.Bundle} dalam {@link android.content.Intent} dengan {@link
+android.content.Intent#putExtras putExtras()}.</p>
+
+<p>Misalnya, saat membuat intent yang akan dikirimkan bersama email
+{@link android.content.Intent#ACTION_SEND}, Anda bisa menetapkan penerima "kepada" dengan kunci
+{@link android.content.Intent#EXTRA_EMAIL}, dan menetapkan "subjek" dengan kunci
+{@link android.content.Intent#EXTRA_SUBJECT}.</p>
+
+<p>Kelas {@link android.content.Intent} menetapkan beberapa konstanta {@code EXTRA_*}
+untuk tipe data standar. Jika Anda ingin mendeklarasikan kunci ekstra sendiri (untuk intent yang
+diterima aplikasi Anda), pastikan untuk memasukkan nama paket aplikasi
+sebagai awalan. Misalnya:</p>
+<pre>static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";</pre>
+</dd>
+
+<dt><b>Flag</b></dt>
+<dd>Flag didefinisikan dalam kelas {@link android.content.Intent} yang berfungsi sebagai metadata untuk
+intent. Flag menginstruksikan cara meluncurkan aktivitas (misalnya,
+<a href="{@docRoot}guide/components/tasks-and-back-stack.html">tugas</a> mana yang harus dimiliki suatu aktivitas
+) dan cara memperlakukannya setelah diluncurkan (misalnya, apakah aktivitas tersebut masuk ke dalam daftar aktivitas
+terbaru) pada sistem Android.
+
+<p>Untuk informasi selengkapnya, lihat metode {@link android.content.Intent#setFlags setFlags()} .</p>
+</dd>
+
+</dl>
+
+
+
+
+<h3 id="ExampleExplicit">Contoh intent eksplisit</h3>
+
+<p>Intent eksplisit adalah intent yang Anda gunakan untuk meluncurkan komponen aplikasi tertentu, seperti
+aktivitas tertentu atau layanan dalam aplikasi Anda. Untuk membuat intent eksplisit, definisikan
+nama komponen untuk objek {@link android.content.Intent} &mdash;semua
+properti intent lain bersifat opsional.</p>
+
+<p>Misalnya, jika Anda ingin membangun layanan dalam aplikasi Anda, bernama {@code DownloadService},
+yang didesain untuk mengunduh file dari web, Anda bisa memulainya dengan kode berikut ini:</p>
+
+<pre>
+// Executed in an Activity, so 'this' is the {@link android.content.Context}
+// The fileUrl is a string URL, such as "http://www.example.com/image.png"
+Intent downloadIntent = new Intent(this, DownloadService.class);
+downloadIntent.setData({@link android.net.Uri#parse Uri.parse}(fileUrl));
+startService(downloadIntent);
+</pre>
+
+<p>Konstruktor {@link android.content.Intent#Intent(Context,Class)}
+ menyediakan {@link android.content.Context} aplikasi dan
+objek {@link java.lang.Class} pada komponen. Dengan demikian,
+intent ini memulai secara eksplisit kelas {@code DownloadService} dalam aplikasi.</p>
+
+<p>Untuk informasi selengkapnya tentang membangun dan memulai layanan, lihat panduan
+<a href="{@docRoot}guide/components/services.html">Layanan</a>.</p>
+
+
+
+
+<h3 id="ExampleSend">Contoh intent implisit</h3>
+
+<p>Intent implisit menetapkan tindakan yang bisa memanggil aplikasi pada perangkat yang mampu
+melakukan tindakan. Menggunakan intent implisit berguna bila aplikasi Anda tidak bisa melakukan
+tindakan, namun aplikasi lain mungkin bisa melakukannya dan Anda ingin pengguna untuk memilih aplikasi mana yang ingin digunakan.</p>
+
+<p>Misalnya, jika memiliki konten yang Anda ingin agar pengguna berbagi konten itu dengan orang lain, buatlah intent
+dengan tindakan {@link android.content.Intent#ACTION_SEND}
+dan tambahkan ekstra yang menetapkan konten yang akan dibagikan. Bila Anda memanggil
+{@link android.content.Context#startActivity startActivity()} dengan intent tersebut, pengguna bisa
+memilih aplikasi yang akan digunakan untuk berbagi konten.</p>
+
+<p class="caution"><strong>Perhatian:</strong> Ada kemungkinan pengguna tidak memiliki <em>suatu</em>
+aplikasi yang menangani intent implisit yang Anda kirimkan ke {@link android.content.Context#startActivity
+startActivity()}. Jika itu terjadi, panggilan akan gagal dan aplikasi Anda akan crash. Untuk memeriksa
+apakah aktivitas bisa menerima intent, panggil {@link android.content.Intent#resolveActivity
+resolveActivity()} pada objek {@link android.content.Intent} Anda. Jika hasilnya bukan nol,
+berarti setidaknya ada satu aplikasi yang bisa menangani intent tersebut dan aman untuk memanggil
+{@link android.content.Context#startActivity startActivity()}. Jika hasilnya nol,
+Anda tidak boleh menggunakan intent tersebut dan, jika memungkinkan, Anda harus menonaktifkan fitur yang mengeluarkan
+intent tersebut.</p>
+
+
+<pre>
+// Create the text message with a string
+Intent sendIntent = new Intent();
+sendIntent.setAction(Intent.ACTION_SEND);
+sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
+sendIntent.setType("text/plain");
+
+// Verify that the intent will resolve to an activity
+if (sendIntent.resolveActivity(getPackageManager()) != null) {
+    startActivity(sendIntent);
+}
+</pre>
+
+<p class="note"><strong>Catatan:</strong> Dalam hal ini, URI tidak digunakan, namun tipe data intent
+dideklarasikan untuk menetapkan konten yang dibawa oleh ekstra.</p>
+
+
+<p>Saat {@link android.content.Context#startActivity startActivity()} dipanggil, sistem akan
+memeriksa semua aplikasi yang terinstal untuk menentukan aplikasi mana yang bisa menangani intent jenis ini (
+intent dengan tindakan {@link android.content.Intent#ACTION_SEND} dan yang membawa data
+"teks/polos"). Jika hanya ada satu aplikasi yang bisa menanganinya, aplikasi tersebut akan langsung terbuka dan diberi
+intent tersebut. Jika banyak aktivitas menerima intent, sistem akan
+menampilkan dialog sehingga pengguna bisa memilih aplikasi mana yang digunakan.</p>
+
+
+<div class="figure" style="width:200px">
+  <img src="{@docRoot}images/training/basics/intent-chooser.png" alt="">
+  <p class="img-caption"><strong>Gambar 2.</strong> Dialog pemilih.</p>
+</div>
+
+<h3 id="ForceChooser">Memaksakan pemilih aplikasi</h3>
+
+<p>Bila ada lebih dari satu aplikasi yang merespons intent implisit Anda,
+pengguna bisa memilih aplikasi mana yang digunakan dan membuat aplikasi tersebut pilihan default untuk
+tindakan tersebut. Ini sangat membantu saat melakukan tindakan di mana pengguna
+mungkin ingin menggunakan aplikasi yang sama untuk seterusnya, seperti saat membuka halaman web (pengguna
+biasanya memilih hanya satu browser web).</p>
+
+<p>Akan tetapi, jika ada banyak aplikasi yang bisa merespons intent tersebut dan pengguna mungkin ingin menggunakan aplikasi
+yang berbeda untuk setiap kalinya, Anda harus menampilkan dialog pemilih secara eksplisit. Dialog pemilih akan meminta
+pengguna memilih aplikasi yang akan digunakan untuk tindakan tertentu setiap kali (pengguna tidak bisa memilih aplikasi default untuk
+tindakan tersebut). Misalnya, saat aplikasi Anda melakukan "berbagi" dengan tindakan {@link
+android.content.Intent#ACTION_SEND}, pengguna mungkin ingin berbagi menggunakan aplikasi berbeda sesuai
+dengan situasi mereka saat itu, jadi Anda harus selalu menggunakan dialog pemilih, seperti yang ditampilkan dalam gambar 2.</p>
+
+
+
+
+<p>Untuk menampilkan pemilih, buatlah {@link android.content.Intent} menggunakan {@link
+android.content.Intent#createChooser createChooser()} dan teruskan ke {@link
+android.app.Activity#startActivity startActivity()}. Misalnya:</p>
+
+<pre>
+Intent sendIntent = new Intent(Intent.ACTION_SEND);
+...
+
+// Always use string resources for UI text.
+// This says something like "Share this photo with"
+String title = getResources().getString(R.string.chooser_title);
+// Create intent to show the chooser dialog
+Intent chooser = Intent.createChooser(sendIntent, title);
+
+// Verify the original intent will resolve to at least one activity
+if (sendIntent.resolveActivity(getPackageManager()) != null) {
+    startActivity(chooser);
+}
+</pre>
+
+<p>Ini menampilkan dialog dengan daftar aplikasi yang merespons intent yang diteruskan ke metode {@link
+android.content.Intent#createChooser createChooser()} dan menggunakan teks yang disediakan sebagai
+judul dialog.</p>
+
+
+
+
+
+
+
+
+
+<h2 id="Receiving">Menerima Intent Implisit</h2>
+
+<p>Untuk mengiklankan intent implisit yang bisa diterima aplikasi Anda, deklarasikan satu atau beberapa filter intent untuk
+tiap komponen aplikasi dengan elemen <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code &lt;intent-filter&gt;}</a>
+dalam <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">file manifes</a> Anda.
+Tiap filter intent menetapkan tipe intent yang diterimanya berdasarkan tindakan intent,
+data, dan kategori. Sistem akan mengirim intent implisit ke komponen aplikasi Anda hanya jika
+intent tersebut bisa diteruskan melalui salah satu filter intent.</p>
+
+<p class="note"><strong>Catatan:</strong> Intent eksplisit selalu dikirimkan ke targetnya,
+apa pun filter intent yang dideklarasikan komponen.</p>
+
+<p>Komponen aplikasi harus mendeklarasikan filter terpisah untuk setiap pekerjaan unik yang bisa dilakukannya.
+Misalnya, satu aktivitas dalam aplikasi galeri gambar bisa memiliki dua filter: satu filter
+untuk melihat gambar, dan filter lainnya untuk mengedit gambar. Bila aktivitas dimulai,
+aktivitas akan memeriksa {@link android.content.Intent} dan menentukan cara berperilaku berdasarkan informasi
+dalam {@link android.content.Intent} (misalnya menampilkan kontrol editor atau tidak).</p>
+
+<p>Tiap filter intent didefinisikan oleh elemen <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code &lt;intent-filter&gt;}</a>
+dalam file manifes aplikasi, yang tersarang dalam komponen aplikasi terkait (seperti
+elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
+). Di dalam <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code &lt;intent-filter&gt;}</a>,
+Anda bisa menetapkan tipe intent yang akan diterima dengan menggunakan salah satu atau beberapa
+dari tiga elemen ini:</p>
+
+<dl>
+<dt><a href="{@docRoot}guide/topics/manifest/action-element.html">{@code &lt;action&gt;}</a></dt>
+  <dd>Mendeklarasikan tindakan intent yang diterima, dalam atribut {@code name}. Nilai
+  haruslah nilai string literal dari tindakan, bukan konstanta kelas.</dd>
+<dt><a href="{@docRoot}guide/topics/manifest/data-element.html">{@code &lt;data&gt;}</a></dt>
+  <dd>Mendeklarasikan tipe data yang diterima, menggunakan salah satu atau beberapa atribut yang menetapkan beragam
+  aspek URI data (<code>scheme</code>, <code>host</code>, <code>port</code>,
+  <code>path</code>, dll.) dan tipe MIME.</dd>
+<dt><a href="{@docRoot}guide/topics/manifest/category-element.html">{@code &lt;category&gt;}</a></dt>
+  <dd>Mendeklarasikan kategori intent yang diterima, dalam atribut {@code name}. Nilai
+  haruslah nilai string literal dari tindakan, bukan konstanta kelas.
+
+  <p class="note"><strong>Catatan:</strong> Untuk menerima intent implisit, Anda
+  <strong>harus menyertakan</strong> kategori
+{@link android.content.Intent#CATEGORY_DEFAULT} dalam filter intent. Metode
+  {@link android.app.Activity#startActivity startActivity()}dan
+  {@link android.app.Activity#startActivityForResult startActivityForResult()} memperlakukan semua intent
+  seolah-olah mendeklarasikan kategori {@link android.content.Intent#CATEGORY_DEFAULT}.
+  Jika tidak mendeklarasikan kategori ini dalam filter intent Anda, tidak ada intent implisit yang ditetapkan untuk
+ aktivitas Anda.</p>
+  </dd>
+</dl>
+
+<p>Misalnya, ini adalah deklarasi aktivitas dengan filter intent yang diterima intent
+{@link android.content.Intent#ACTION_SEND} bila tipe data berupa teks:</p>
+
+<pre>
+&lt;activity android:name="ShareActivity">
+    &lt;intent-filter>
+        &lt;action android:name="android.intent.action.SEND"/>
+        &lt;category android:name="android.intent.category.DEFAULT"/>
+        &lt;data android:mimeType="text/plain"/>
+    &lt;/intent-filter>
+&lt;/activity>
+</pre>
+
+<p>Anda bisa membuat filter yang menyertakan lebih dari satu instance
+<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code &lt;action&gt;}</a>,
+<a href="{@docRoot}guide/topics/manifest/data-element.html">{@code &lt;data&gt;}</a>, atau
+<a href="{@docRoot}guide/topics/manifest/category-element.html">{@code &lt;category&gt;}</a>.
+Jika Anda melakukannya, Anda hanya perlu memastikan bahwa komponen bisa menangani semua kombinasi
+elemen filter tersebut.</p>
+
+<p>Bila ingin menangani beragam jenis intent, namun hanya dalam kombinasi
+tindakan, data, dan tipe kategori tertentu, maka Anda harus membuat banyak filter intent.</p>
+
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<h2>Membatasi akses ke komponen</h2>
+<p>Menggunakan filter intent bukanlah cara yang aman untuk mencegah aplikasi lain memulai
+komponen Anda. Walaupun filter intent membatasi komponen agar hanya merespons
+jenis intent implisit tertentu, aplikasi lain bisa saja memulai komponen aplikasi Anda
+dengan menggunakan intent eksplisit jika pengembangnya menentukan nama komponen Anda.
+Jika perlu <em>hanya aplikasi Anda sendiri</em> yang mampu memulai salah satu komponen,
+atur atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#exported">{@code
+exported}</a> ke {@code "false"} untuk komponen itu.
+</p>
+</div>
+</div>
+
+<p>Intent implisit diuji terhadap filter dengan membandingkan intent dengan masing-masing
+dari ketiga elemen. Agar dikirim ke komponen, intent harus lolos ketiga pengujian tersebut.
+Jika intent gagal dalam salah satu pengujian, sistem Android tidak akan mengirim intent ke
+komponen.  Akan tetapi, karena sebuah komponen dapat memiliki beberapa filter intent, intent yang tidak
+lolos melalui salah satu filter komponen mungkin akan lolos di filter lain.
+Informasi selengkapnya tentang cara sistem menetapkan intent disediakan dalam bagian di bawah ini
+tentang <a href="#Resolution">Resolusi Intent</a>.</p>
+
+<p class="caution"><strong>Perhatian:</strong> Untuk menghindari menjalankan
+{@link android.app.Service} aplikasi yang berbeda secara tidak sengaja, selalu gunakan intent eksplisit untuk memulai layanan Anda sendiri dan jangan
+deklarasikan filter intent untuk layanan Anda.</p>
+
+<p class="note"><strong>Catatan:</strong>
+Untuk semua aktivitas, Anda harus mendeklarasikan filter intent dalam file manifes.
+Akan tetapi, filter untuk penerima siaran bisa didaftarkan secara dinamis dengan memanggil
+{@link android.content.Context#registerReceiver(BroadcastReceiver, IntentFilter, String,
+Handler) registerReceiver()}. Anda nanti bisa mencabut pendaftaran penerima dengan {@link
+android.content.Context#unregisterReceiver unregisterReceiver()}. Dengan begitu aplikasi Anda
+bisa mendengarkan siaran tertentu hanya selama periode waktu yang telah ditetapkan saat aplikasi Anda
+berjalan.</p>
+
+
+
+
+
+
+
+<h3 id="ExampleFilters">Contoh filter</h3>
+
+<p>Untuk lebih memahami beberapa perilaku filter intent, lihatlah cuplikan berikut
+dari file manifes aplikasi berbagi di jaringan sosial.</p>
+
+<pre>
+&lt;activity android:name="MainActivity">
+    &lt;!-- This activity is the main entry, should appear in app launcher -->
+    &lt;intent-filter>
+        &lt;action android:name="android.intent.action.MAIN" />
+        &lt;category android:name="android.intent.category.LAUNCHER" />
+    &lt;/intent-filter>
+&lt;/activity>
+
+&lt;activity android:name="ShareActivity">
+    &lt;!-- This activity handles "SEND" actions with text data -->
+    &lt;intent-filter&gt;
+        &lt;action android:name="android.intent.action.SEND"/>
+        &lt;category android:name="android.intent.category.DEFAULT"/>
+        &lt;data android:mimeType="text/plain"/>
+    &lt;/intent-filter&gt;
+    &lt;!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->
+    &lt;intent-filter&gt;
+        &lt;action android:name="android.intent.action.SEND"/>
+        &lt;action android:name="android.intent.action.SEND_MULTIPLE"/>
+        &lt;category android:name="android.intent.category.DEFAULT"/>
+        &lt;data android:mimeType="application/vnd.google.panorama360+jpg"/>
+        &lt;data android:mimeType="image/*"/>
+        &lt;data android:mimeType="video/*"/>
+    &lt;/intent-filter&gt;
+&lt;/activity&gt;
+</pre>
+
+<p>Aktivitas pertama, {@code MainActivity}, merupakan titik masuk utama aplikasi&mdash;aplikasi yang
+terbuka saat pengguna meluncurkan aplikasi dengan ikon launcher:</p>
+<ul>
+  <li>Tindakan {@link android.content.Intent#ACTION_MAIN}
+  menunjukkan ini adalah titik masuk utama dan tidak mengharapkan data intent apa pun.</li>
+  <li>Kategori {@link android.content.Intent#CATEGORY_LAUNCHER} menunjukjkan bahwa ikon
+  aktivitas ini harus ditempatkan dalam launcher aplikasi sistem. Jika elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
+  tidak menetapkan ikon dengan{@code icon}, maka sistem akan menggunakan ikon dari elemen
+<a href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a>.</li>
+</ul>
+<p>Keduanya harus dipasangkan bersama agar aktivitas muncul dalam launcher aplikasi.</p>
+
+<p>Aktivitas kedua, {@code ShareActivity}, dimaksudkan untuk memudahkan berbagi teks dan konten
+media. Walaupun pengguna mungkin memasuki aktivitas ini dengan mengarah ke aktivitas dari {@code MainActivity},
+pengguna juga bisa memasukkan {@code ShareActivity} secara langsung dari aplikasi lain yang mengeluarkan intent
+implisit yang cocok dengan salah satu dari kedua filter intent.</p>
+
+<p class="note"><strong>Catatan:</strong> Tipe MIME,
+<a href="https://developers.google.com/panorama/android/">{@code
+application/vnd.google.panorama360+jpg}</a>, merupakan tipe data khusus yang menetapkan
+foto panorama, yang bisa Anda tangani dengan API <a href="{@docRoot}reference/com/google/android/gms/panorama/package-summary.html">panorama
+Google</a>.</p>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h2 id="PendingIntent">Menggunakan Intent Tertunda</h2>
+
+<p>Objek {@link android.app.PendingIntent} merupakan pembungkus objek {@link
+android.content.Intent}. Tujuan utama {@link android.app.PendingIntent}
+adalah memberikan izin pada aplikasi asing
+untuk menggunakan {@link android.content.Intent} yang termuat seolah-olah dieksekusi dari
+proses aplikasi Anda sendiri.</p>
+
+<p>Kasus penggunaan utama untuk intent tertunda antara lain:</p>
+<ul>
+  <li>Mendeklarasikan intent untuk dieksekusi saat pengguna melakukan tindakan dengan <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Pemberitahuan</a>
+  ({@link android.app.NotificationManager}
+  sistem Android akan mengeksekusi {@link android.content.Intent}) Anda.
+  <li>Mendeklarasikan intent untuk dieksekusi saat pengguna melakukan tindakan dengan
+<a href="{@docRoot}guide/topics/appwidgets/index.html">App Widget</a>
+  (aplikasi layar Home mengeksekusi {@link android.content.Intent}).
+  <li>Mendeklarasikan intent untuk dieksekusi di waktu yang telah ditetapkan di masa mendatang
+({@link android.app.AlarmManager}  sistem Android akan mengeksekusi {@link android.content.Intent}).
+</ul>
+
+<p>Karena setiap objek {@link android.content.Intent} didesain untuk ditangani oleh tipe
+tertentu dari komponen aplikasi (baik {@link android.app.Activity}, {@link android.app.Service}, maupun
+ {@link android.content.BroadcastReceiver}), jadi {@link android.app.PendingIntent} harus
+dibuat dengan pertimbangan yang sama. Saat menggunakan intent tertunda, aplikasi Anda tidak akan
+mengeksekusi intent dengan panggilan seperti {@link android.content.Context#startActivity
+startActivity()}. Anda harus mendeklarasikan tipe komponen yang dimaksud saat membuat
+{@link android.app.PendingIntent} dengan memanggil metode kreator masing-masing:</p>
+
+<ul>
+  <li>{@link android.app.PendingIntent#getActivity PendingIntent.getActivity()} untuk
+  {@link android.content.Intent} yang memulai {@link android.app.Activity}.</li>
+  <li>{@link android.app.PendingIntent#getService PendingIntent.getService()} untuk
+  {@link android.content.Intent} yang memulai {@link android.app.Service}.</li>
+  <li>{@link android.app.PendingIntent#getBroadcast PendingIntent.getBroadcast()} untuk
+  {@link android.content.Intent} yang memulai {@link android.content.BroadcastReceiver}.</li>
+</ul>
+
+<p>Kecuali jika aplikasi Anda <em>menerima</em> intent tertunda dari aplikasi lain,
+metode di atas untuk membuat {@link android.app.PendingIntent} menjadi satu-satunya metode
+{@link android.app.PendingIntent} yang mungkin Anda butuhkan.</p>
+
+<p>Tiap metode mengambil {@link android.content.Context} aplikasi saat itu,
+{@link android.content.Intent} yang ingin Anda bungkus, dan satu atau beberapa flag yang menetapkan
+cara penggunaan intent (misalnya apakah intent bisa digunakan lebih dari sekali).</p>
+
+<p>Informasi selengkapnya tentang intent tertunda disediakan pada dokumentasi untuk setiap
+kasus penggunaan yang bersangkutan, seperti dalam panduan API <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Notifications</a>
+dan <a href="{@docRoot}guide/topics/appwidgets/index.html">App Widgets</a>.</p>
+
+
+
+
+
+
+
+<h2 id="Resolution">Resolusi Intent</h2>
+
+
+<p>Saat sistem menerima intent implisit yang memulai suatu aktivitas, sistem tersebut akan mencari
+aktivitas terbaik untuk intent dengan membandingkan intent dengan filter intent berdasarkan tiga aspek:</p>
+
+<ul>
+  <li>Tindakan intent
+  <li>Data intent (baik URI maupun tipe data)
+  <li>Kategori intent
+</ul>
+
+<p>Bagian berikut menjelaskan cara pencocokan intent dengan komponen yang sesuai
+sehubungan dengan cara pendeklarasian filter intent dalam file manifes aplikasi.</p>
+
+
+<h3 id="ActionTest">Pengujian tindakan</h3>
+
+<p>Untuk menetapkan tindakan intent yang diterima, filter intent bisa mendeklarasikan nol atau beberapa elemen
+<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code
+&lt;action&gt;}</a>.  Misalnya:</p>
+
+<pre>
+&lt;intent-filter&gt;
+    &lt;action android:name="android.intent.action.EDIT" /&gt;
+    &lt;action android:name="android.intent.action.VIEW" /&gt;
+    ...
+&lt;/intent-filter&gt;
+</pre>
+
+<p>Untuk melewati filter ini, tindakan yang ditetapkan dalam {@link android.content.Intent}
+harus sesuai dengan salah satu tindakan yang tercantum dalam filter.</p>
+
+<p>Jika filter tidak mencantumkan tindakan apa pun, maka tidak ada intent
+yang dicocokkan, jadi semua intent gagal dalam pengujian. Akan tetapi, jika sebuah {@link android.content.Intent}
+tidak menetapkan suatu tindakan, maka akan lolos pengujian (asalkan filter
+berisi setidaknya satu tindakan).</p>
+
+
+
+<h3 id="CategoryTest">Pengujian kategori</h3>
+
+<p>Untuk menetapkan kategori intent yang diterima, filter intent bisa mendeklarasikan nol atau beberapa elemen
+<a href="{@docRoot}guide/topics/manifest/category-element.html">{@code
+&lt;category&gt;}</a>.  Misalnya:</p>
+
+<pre>
+&lt;intent-filter&gt;
+    &lt;category android:name="android.intent.category.DEFAULT" /&gt;
+    &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
+    ...
+&lt;/intent-filter&gt;
+</pre>
+
+<p>Agar intent bisa lolos pengujian kategori, setiap kategori dalam {@link android.content.Intent}
+harus sesuai dengan kategori dalam filter. Kebalikannya tidak diperlukan&mdash;filter intent bisa
+mendeklarasikan kategori lebih banyak daripada yang ditetapkan dalam {@link android.content.Intent} dan
+{@link android.content.Intent} tetap akan lolos. Oleh karena itu, intent tanpa kategori harus
+selalu lolos pengujian ini, kategori apa pun yang dideklarasikan dalam filter.</p>
+
+<p class="note"><strong>Catatan:</strong>
+Android secara otomatis menerapkan kategori {@link android.content.Intent#CATEGORY_DEFAULT}
+untuk semua intent implisit yang diteruskan ke {@link
+android.content.Context#startActivity startActivity()} dan {@link
+android.app.Activity#startActivityForResult startActivityForResult()}.
+Jadi jika ingin aktivitas Anda menerima intent implisit, aktivitas tersebut harus
+menyertakan kategori untuk{@code "android.intent.category.DEFAULT"} dalam filter intent (seperti
+yang ditampilkan dalam contoh{@code &lt;intent-filter&gt;} sebelumnya.</p>
+
+
+
+<h3 id="DataTest">Pengujian data</h3>
+
+<p>Untuk menetapkan data intent yang diterima, filter intent bisa mendeklarasikan nol atau beberapa elemen
+<a href="{@docRoot}guide/topics/manifest/data-element.html">{@code
+&lt;data&gt;}</a>.  Misalnya:</p>
+
+<pre>
+&lt;intent-filter&gt;
+    &lt;data android:mimeType="video/mpeg" android:scheme="http" ... /&gt;
+    &lt;data android:mimeType="audio/mpeg" android:scheme="http" ... /&gt;
+    ...
+&lt;/intent-filter&gt;
+</pre>
+
+<p>Tiap elemen <code><a href="{@docRoot}guide/topics/manifest/data-element.html">&lt;data&gt;</a></code>
+bisa menetapkan struktur URI dan tipe data (tipe media MIME).  Ada atribut
+terpisah &mdash; {@code scheme}, {@code host}, {@code port},
+dan {@code path} &mdash; untuk setiap bagian URI:
+</p>
+
+<p style="margin-left: 2em">{@code &lt;scheme&gt;://&lt;host&gt;:&lt;port&gt;/&lt;path&gt;}</p>
+
+<p>
+Misalnya:
+</p>
+
+<p style="margin-left: 2em">{@code content://com.example.project:200/folder/subfolder/etc}</p>
+
+<p>Dalam URI ini, skemanya adalah {@code content}, host-nya adalah {@code com.example.project},
+port-nya adalah {@code 200}, dan path-nya adalah {@code folder/subfolder/etc}.
+</p>
+
+<p>Tiap atribut bersifat opsional dalam elemen <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code &lt;data&gt;}</a>,
+namun ada dependensi linear:</p>
+<ul>
+  <li>Jika skema tidak ditetapkan, host akan diabaikan.</li>
+  <li>Jika host tidak ditetapkan, port akan diabaikan.</li>
+  <li>Jika skema dan host tidak ditetapkan, path akan diabaikan.</li>
+</ul>
+
+<p>Bila URI dalam intent dibandingkan dengan spesifikasi URI dalam filter,
+pembandingannya hanya dengan bagian URI yang disertakan dalam filter. Misalnya:</p>
+<ul>
+  <li>Jika sebuah filter menetapkan hanya satu skema, semua URI dengan skema tersebut akan cocok
+dengan filter.</li>
+  <li>Jika sebuah filter menetapkan satu skema dan satu otoritas namun tanpa path, semua URI
+dengan skema dan otoritas yang sama akan lolos dari filter, apa pun path-nya.</li>
+  <li>Jika sebuah filter menetapkan satu skema, otoritas dan path, hanya URI dengan skema,
+otoritas, dan path sama yang bisa lolos dari filter.</li>
+</ul>
+
+<p class="note"><strong>Catatan:</strong> Spesifikasi path bisa berisi
+wildcard bintang (*) untuk hanya mencocokkan nama path secara parsial.</p>
+
+<p>Pengujian data membandingkan URI maupun tipe MIME dalam intent dengan URI
+dan tipe MIME yang ditetapkan dalam filter.  Aturannya adalah sebagai berikut:
+</p>
+
+<ol type="a">
+<li>Intent yang tidak berisi URI maupun tipe MIME hanya akan lolos
+pengujian jika filter tersebut tidak menetapkan URI atau tipe MIME apa pun.</li>
+
+<li>Intent yang berisi URI namun tidak berisi tipe MIME (baik secara eksplisit maupun tidak langsung dari
+URI) hanya akan lolos pengujian jika URI-nya cocok dengan format URI filter
+dan filternya juga tidak menetapkan tipe MIME.</li>
+
+<li>Intent yang berisi tipe MIME namun tidak berisi URI hanya akan lolos pengujian
+jika filter mencantumkan tipe MIME yang sama dan tidak menetapkan format URI.</li>
+
+<li>Intent yang berisi URI maupun tipe MIME (baik secara eksplisit maupun tidak langsung dari
+URI) hanya akan lolos pengujian bagian tipe MIME jika
+tipe tersebut cocok dengan tipe yang dicantumkan dalam filter.  Ini akan lolos pengujian bagian URI
+jika URI-nya cocok dengan URI dalam filter atau memiliki {@code content:}
+atau URI {@code file:} dan filter tidak menetapkan URI. Dengan kata lain,
+komponen dianggap mendukung data {@code content:} dan {@code file:} jika
+filternya <em>hanya</em> mencantumkan tipe MIME.</p></li>
+</ol>
+
+<p>
+Aturan terakhir ini, aturan (d), mencerminkan harapan
+bahwa komponen mampu mendapatkan data lokal dari file atau penyedia konten.
+Oleh karena itu, filter mereka mencatumkan tipe data saja dan tidak secara eksplisit
+harus menamai skema {@code content:} dan {@code file:}.
+Ini adalah kasus umum.  Elemen <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code &lt;data&gt;}</a>
+seperti berikut ini, misalnya, memberi tahu Android bahwa komponen bisa mengambil data gambar dari penyedia
+konten dan menampilkannya:
+</p>
+
+<pre>
+&lt;intent-filter&gt;
+    &lt;data android:mimeType="image/*" /&gt;
+    ...
+&lt;/intent-filter&gt;</pre>
+
+<p>
+Karena sebagian besar data yang tersedia dikeluarkan oleh penyedia konten, filter yang
+menetapkan tipe data namun bukan URI mungkin adalah yang paling umum.
+</p>
+
+<p>
+Konfigurasi umum yang lain adalah filter dengan skema dan tipe data.  Misalnya
+, elemen <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code &lt;data&gt;}</a>
+ seperti berikut ini akan memberi tahu Android bahwa
+komponen bisa mengambil data video dari jaringan untuk melakukan tindakan:
+</p>
+
+<pre>
+&lt;intent-filter&gt;
+    &lt;data android:scheme="http" android:type="video/*" /&gt;
+    ...
+&lt;/intent-filter&gt;</pre>
+
+
+
+<h3 id="imatch">Pencocokan intent</h3>
+
+<p>Intent dicocokkan dengan filter intent selain untuk menemukan komponen
+target yang akan diaktifkan, juga untuk menemukan sesuatu tentang rangkaian
+komponen pada perangkat.  Misalnya, aplikasi Home akan menempatkan launcher aplikasi
+dengan mencari semua aktivitas dengan filter intent yang menetapkan tindakan
+{@link android.content.Intent#ACTION_MAIN} dan
+kategori {@link android.content.Intent#CATEGORY_LAUNCHER}.</p>
+
+<p>Aplikasi Anda bisa menggunakan pencocokan intent dengan cara serupa.
+{@link android.content.pm.PackageManager} memiliki seperangkat metode {@code query...()}
+yang mengembalikan semua komponen yang bisa menerima intent tertentu, dan
+serangkaian metode{@code resolve...()} serupa yang menentukan komponen
+terbaik untuk merespons intent.  Misalnya,
+{@link android.content.pm.PackageManager#queryIntentActivities
+queryIntentActivities()} akan mengembalikan daftar semua aktivitas yang bisa melakukan
+intent yang diteruskan sebagai argumen, dan {@link
+android.content.pm.PackageManager#queryIntentServices
+queryIntentServices()} akan mengembalikan daftar layanan serupa.
+Tidak ada metode yang akan mengaktifkan komponen; mereka hanya mencantumkan komponen yang
+bisa merespons.  Ada metode serupa,
+{@link android.content.pm.PackageManager#queryBroadcastReceivers
+queryBroadcastReceivers()}, untuk penerima siaran.
+</p>
+
+
+
+
diff --git a/docs/html-intl/intl/id/guide/components/loaders.jd b/docs/html-intl/intl/id/guide/components/loaders.jd
new file mode 100644
index 0000000..88093cc
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/components/loaders.jd
@@ -0,0 +1,494 @@
+page.title=Aktivitas
+parent.title=Loader
+parent.link=activities.html
+@jd:body
+<div id="qv-wrapper">
+<div id="qv">
+    <h2>Dalam dokumen ini</h2>
+    <ol>
+    <li><a href="#summary">Rangkuman Loader API</a></li>
+    <li><a href="#app">Menggunakan Loader dalam Aplikasi</a>
+      <ol>
+        <li><a href="#requirements"></a></li>
+        <li><a href="#starting">Memulai Loader</a></li>
+        <li><a href="#restarting">Me-restart Loader</a></li>
+        <li><a href="#callback">Menggunakan Callback LoaderManager</a></li>
+      </ol>
+    </li>
+    <li><a href="#example">Contoh</a>
+       <ol>
+         <li><a href="#more_examples">Contoh Selengkapnya</a></li>
+        </ol>
+    </li>
+  </ol>
+
+  <h2>Kelas-kelas utama</h2>
+    <ol>
+      <li>{@link android.app.LoaderManager}</li>
+      <li>{@link android.content.Loader}</li>
+
+    </ol>
+
+    <h2>Contoh-contoh terkait</h2>
+   <ol>
+     <li> <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderCursor.html">
+LoaderCursor</a></li>
+     <li> <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html">
+LoaderThrottle</a></li>
+   </ol>
+  </div>
+</div>
+
+<p>Diperkenalkan di Android 3.0, loader memudahkan pemuatan data asinkron
+dalam aktivitas atau fragmen. Loader memiliki karakteristik ini:</p>
+  <ul>
+    <li>Loader tersedia untuk setiap {@link android.app.Activity} dan {@link
+android.app.Fragment}.</li>
+    <li>Loader menyediakan pemuatan data asinkron.</li>
+    <li>Loader memantau sumber data mereka dan memberikan hasil baru bila
+konten berubah.</li>
+    <li>Loader secara otomatis menghubungkan kembali ke kursor loader lalu saat
+dibuat kembali setelah perubahan konfigurasi. Karena itu, loader tidak perlu melakukan query ulang
+datanya.</li>
+  </ul>
+
+<h2 id="summary">Rangkuman Loader API</h2>
+
+<p>Ada beberapa kelas dan antarmuka yang mungkin dilibatkan dalam menggunakan
+loader pada aplikasi. Semuanya dirangkum dalam tabel ini:</p>
+
+<table>
+  <tr>
+    <th>Kelas/Antarmuka</th>
+    <th>Keterangan</th>
+  </tr>
+  <tr>
+    <td>{@link android.app.LoaderManager}</td>
+    <td>Kelas abstrak yang dikaitkan dengan {@link android.app.Activity} atau
+{@link android.app.Fragment} untuk mengelola satu atau beberapa instance {@link
+android.content.Loader}. Ini membantu aplikasi mengelola
+operasi berjalan lebih lama bersamaan dengan daur hidup {@link android.app.Activity}
+atau {@link android.app.Fragment}; penggunaan paling umumnya adalah dengan
+{@link android.content.CursorLoader}, akan tetapi aplikasi bebas menulis loader-nya
+ sendiri untuk memuat tipe data lainnya.
+    <br />
+    <br />
+    Hanya ada satu {@link android.app.LoaderManager} per aktivitas atau fragmen. Namun {@link android.app.LoaderManager} bisa memiliki
+beberapa loader.</td>
+  </tr>
+  <tr>
+    <td>{@link android.app.LoaderManager.LoaderCallbacks}</td>
+    <td>Antarmuka callback untuk klien berinteraksi dengan {@link
+android.app.LoaderManager}. Misalnya, Anda menggunakan metode callback {@link
+android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}
+untuk membuat loader baru.</td>
+  </tr>
+  <tr>
+    <td>{@link android.content.Loader}</td>
+    <td>Kelas abstrak yang melakukan pemuatan data asinkron. Ini
+adalah kelas dasar untuk loader. Biasanya Anda akan menggunakan {@link
+android.content.CursorLoader}, namun Anda bisa menerapkan subkelas sendiri. Selagi
+loader aktif, loader harus memantau sumber datanya dan memberikan hasil
+baru bila konten berubah. </td>
+  </tr>
+  <tr>
+    <td>{@link android.content.AsyncTaskLoader}</td>
+    <td>Loader abstrak yang menyediakan {@link android.os.AsyncTask} untuk melakukan pekerjaan.</td>
+  </tr>
+  <tr>
+    <td>{@link android.content.CursorLoader}</td>
+    <td>Subkelas {@link android.content.AsyncTaskLoader} yang meng-query
+{@link android.content.ContentResolver} dan mengembalikan {@link
+android.database.Cursor}. Kelas ini mengimplementasikan protokol {@link
+android.content.Loader} dengan cara standar untuk query kursor,
+yang dibuat berdasarkan {@link android.content.AsyncTaskLoader} untuk melakukan query kursor
+pada thread latar belakang agar tidak memblokir UI aplikasi. Menggunakan loader
+ini merupakan cara terbaik untuk memuat data secara asinkron dari {@link
+android.content.ContentProvider}, sebagai ganti melakukan query terkelola melalui
+fragmen atau API aktivitas.</td>
+  </tr>
+</table>
+
+<p>Kelas dan antarmuka dalam tabel di atas merupakan komponen
+esensial yang akan Anda gunakan untuk mengimplementasikan loader dalam aplikasi Anda. Anda tidak memerlukan semuanya
+untuk setiap loader yang dibuat, namun Anda akan selalu memerlukan acuan ke {@link
+android.app.LoaderManager} untuk memulai loader dan implementasi
+kelas {@link android.content.Loader} seperti {@link
+android.content.CursorLoader}. Bagian berikut ini menunjukkan kepada Anda cara menggunakan
+kelas dan antarmuka ini dalam aplikasi.</p>
+
+<h2 id ="app">Menggunakan Loader dalam Aplikasi</h2>
+<p>Bagian ini menjelaskan cara menggunakan loader dalam aplikasi Android. Aplikasi
+yang menggunakan loader biasanya berisi yang berikut ini:</p>
+<ul>
+  <li>{@link android.app.Activity} atau {@link android.app.Fragment}.</li>
+  <li>Instance {@link android.app.LoaderManager}.</li>
+  <li>{@link android.content.CursorLoader} akan memuat data yang didukung oleh {@link
+android.content.ContentProvider}. Atau, Anda dapat mengimplementasikan subkelas sendiri
+ dari {@link android.content.Loader} atau {@link android.content.AsyncTaskLoader} untuk
+memuat data dari beberapa sumber lain.</li>
+  <li>Implementasi untuk {@link android.app.LoaderManager.LoaderCallbacks}.
+Di sinilah Anda membuat loader baru dan mengelola acuan bagi loader
+yang ada.</li>
+<li>Cara menampilkan data loader, seperti {@link
+android.widget.SimpleCursorAdapter}.</li>
+  <li>Sumber data, seperti {@link android.content.ContentProvider}, saat menggunakan
+{@link android.content.CursorLoader}.</li>
+</ul>
+<h3 id="starting">Memulai Loader</h3>
+
+<p>{@link android.app.LoaderManager} mengelola satu atau beberapa instance {@link
+android.content.Loader} dalam {@link android.app.Activity} atau
+{@link android.app.Fragment}. Hanya ada satu {@link
+android.app.LoaderManager} per aktivitas atau fragmen.</p>
+
+<p>Anda biasanya
+memulai {@link android.content.Loader} dalam metode {@link
+android.app.Activity#onCreate onCreate()} aktivitas, atau dalam metode
+{@link android.app.Fragment#onActivityCreated onActivityCreated()} fragmen. Anda
+melakukannya dengan cara berikut ini:</p>
+
+<pre>// Prepare the loader.  Either re-connect with an existing one,
+// or start a new one.
+getLoaderManager().initLoader(0, null, this);</pre>
+
+<p>Metode {@link android.app.LoaderManager#initLoader initLoader()} mengambil
+parameter berikut:</p>
+<ul>
+  <li>ID unik yang mengidentifikasi loader. Dalam contoh ini, ID-nya adalah 0.</li>
+<li>Argumen opsional untuk dipasok ke loader
+pada saat pembuatan (dalam contoh ini <code>null</code>).</li>
+
+<li>Implementasi {@link android.app.LoaderManager.LoaderCallbacks}, yang
+akan dipanggil {@link android.app.LoaderManager} untuk melaporkan kejadian loader. Dalam contoh
+ini, kelas lokal mengimplementasikan antarmuka {@link
+android.app.LoaderManager.LoaderCallbacks}, sehingga meneruskan acuan
+ke dirinya sendiri, {@code this}.</li>
+</ul>
+<p>Panggilan {@link android.app.LoaderManager#initLoader initLoader()} memastikan bahwa loader
+telah dimulai dan aktif. Ia memiliki dua kemungkinan hasil:</p>
+<ul>
+  <li>Jika loader yang disebutkan oleh ID sudah ada, loader yang dibuat terakhir akan digunakan
+kembali.</li>
+  <li>Jika loader yang disebutkan oleh ID <em>tidak</em> ada,
+{@link android.app.LoaderManager#initLoader initLoader()} akan memicu metode
+{@link android.app.LoaderManager.LoaderCallbacks} {@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}.
+Di sinilah Anda mengimplementasikan kode untuk membuat instance dan mengembalikan loader baru.
+Untuk diskusi selengkapnya, lihat bagian <a href="#onCreateLoader">onCreateLoader</a>.</li>
+</ul>
+<p>Dalam hal ini, implementasi {@link android.app.LoaderManager.LoaderCallbacks}
+yang ditentukan akan dikaitkan dengan loader, dan akan dipanggil bila
+status loader berubah.  Jika saat panggilan ini status pemanggil sudah
+dimulai, dan loader yang diminta sudah ada dan telah menghasilkan
+datanya, maka sistem segera memanggil {@link
+android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}
+(selama {@link android.app.LoaderManager#initLoader initLoader()}),
+sehingga Anda harus siap bila hal ini terjadi. Lihat <a href="#onLoadFinished">
+onLoadFinished</a> untuk diskusi selengkapnya mengenai callback ini</p>
+
+<p>Perhatikan bahwa metode {@link android.app.LoaderManager#initLoader initLoader()}
+mengembalikan {@link android.content.Loader} yang dibuat, namun Anda tidak
+perlu menangkap acuan ke sana. {@link android.app.LoaderManager} mengelola
+masa hidup loader secara otomatis. {@link android.app.LoaderManager}
+memulai dan menghentikan pemuatan jika perlu, dan menjaga status loader
+dan konten terkaitnya. Seperti yang tersirat di sini, Anda akan jarang berinteraksi dengan loader
+secara langsung (meskipun misalnya menggunakan metode loader untuk menyempurnakan perilaku
+loader, lihat contoh <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a>).
+Anda paling sering akan menggunakan metode {@link
+android.app.LoaderManager.LoaderCallbacks} untuk mengintervensi proses
+pemuatan saat terjadi kejadian tertentu. Untuk diskusi selengkapnya mengenai topik ini, lihat <a href="#callback">Menggunakan Callback LoaderManager</a>.</p>
+
+<h3 id="restarting">Me-restart Loader</h3>
+
+<p>Bila Anda menggunakan {@link android.app.LoaderManager#initLoader initLoader()}, seperti
+ditampilkan di atas, loader yang ada akan digunakan dengan ID yang ditetapkan jika ada.
+Jika tidak ada, ID akan dibuat. Namun kadang-kadang Anda perlu membuang data lama
+dan mulai dari awal.</p>
+
+<p>Untuk membuang data lama, gunakan {@link
+android.app.LoaderManager#restartLoader restartLoader()}. Misalnya, implementasi
+{@link android.widget.SearchView.OnQueryTextListener} ini akan me-restart
+bila query pengguna berubah. Loader perlu di-restart
+agar dapat menggunakan filter pencarian yang telah direvisi untuk melakukan query baru:</p>
+
+<pre>
+public boolean onQueryTextChanged(String newText) {
+    // Called when the action bar search text has changed.  Update
+    // the search filter, and restart the loader to do a new query
+    // with this filter.
+    mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
+    getLoaderManager().restartLoader(0, null, this);
+    return true;
+}</pre>
+
+<h3 id="callback">Menggunakan Callback LoaderManager</h3>
+
+<p>{@link android.app.LoaderManager.LoaderCallbacks} adalah antarmuka callback
+yang memungkinkan klien berinteraksi dengan {@link android.app.LoaderManager}. </p>
+<p>Loader, khususnya {@link android.content.CursorLoader}, diharapkan
+mempertahankan datanya setelah dihentikan. Ini memungkinkan aplikasi mempertahankan
+datanya di aktivitas atau metode {@link android.app.Activity#onStop
+onStop()} fragmen dan {@link android.app.Activity#onStart onStart()}, sehingga
+bila pengguna kembali ke aplikasi, mereka tidak harus menunggu data
+dimuat kembali. Anda menggunakan metode {@link android.app.LoaderManager.LoaderCallbacks}
+untuk mengetahui waktu membuat loader baru, dan memberi tahu aplikasi kapan
+berhenti menggunakan data loader.</p>
+
+<p>{@link android.app.LoaderManager.LoaderCallbacks} berisi metode
+ini:</p>
+<ul>
+  <li>{@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} —
+Membuat instance dan mengembalikan {@link android.content.Loader} baru untuk ID yang diberikan.
+</li></ul>
+<ul>
+  <li> {@link android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}
+— Dipanggil bila loader yang dibuat sebelumnya selesai dimuat.
+</li></ul>
+<ul>
+  <li>{@link android.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()}
+    — Dipanggil bila loader yang dibuat sebelumnya sedang di-reset, sehingga datanya
+tidak tersedia.
+</li>
+</ul>
+<p>Metode ini dijelaskan lebih detail dalam bagian berikutnya.</p>
+
+<h4 id ="onCreateLoader">onCreateLoader</h4>
+
+<p>Saat Anda mencoba mengakses loader (misalnya, melalui {@link
+android.app.LoaderManager#initLoader initLoader()}), ia akan memeriksa untuk mengetahui adanya
+loader yang ditetapkan oleh ID. Jika tidak ada, ia akan memicu metode {@link
+android.app.LoaderManager.LoaderCallbacks} {@link
+android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. Di
+sinilah Anda membuat loader baru. Biasanya ini adalah {@link
+android.content.CursorLoader}, namun Anda bisa mengimplementasikan sendiri subkelas {@link
+android.content.Loader}. </p>
+
+<p>Dalam contoh ini, metode callback {@link
+android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}
+ akan membuat {@link android.content.CursorLoader}. Anda harus membuat
+{@link android.content.CursorLoader} menggunakan metode konstruktornya, yang
+memerlukan set informasi lengkap untuk melakukan query ke {@link
+android.content.ContentProvider}. Secara khusus, ia memerlukan:</p>
+<ul>
+  <li><em>uri</em> — URI untuk konten yang akan diambil. </li>
+  <li><em>projection</em> — Daftar berisi kolom yang akan dikembalikan. Meneruskan
+<code>null</code> akan mengembalikan semua kolom, jadi tidak efisien. </li>
+  <li><em>selection</em> — Filter yang mendeklarasikan baris yang akan dikembalikan,
+diformat sebagai klausa SQL WHERE (tidak termasuk WHERE itu sendiri). Meneruskan
+<code>null</code> akan mengembalikan semua baris untuk URI yang diberikan. </li>
+  <li><em>selectionArgs</em> — Anda dapat menyertakan ?s dalam pilihan, yang akan
+digantikan dengan nilai dari <em>selectionArgs</em>, agar muncul dalam
+pilihan. Nilai-nilai akan diikat sebagai String. </li>
+  <li><em>sortOrder</em> — Cara menyusun baris, diformat sebagai klausa SQL
+ORDER BY (tidak termasuk ORDER BY itu sendiri). Meneruskan <code>null</code> akan
+menggunakan urutan sortir default, yang mungkin tidak berurutan.</li>
+</ul>
+<p>Misalnya:</p>
+<pre>
+ // If non-null, this is the current filter the user has provided.
+String mCurFilter;
+...
+public Loader&lt;Cursor&gt; onCreateLoader(int id, Bundle args) {
+    // This is called when a new Loader needs to be created.  This
+    // sample only has one Loader, so we don't care about the ID.
+    // First, pick the base URI to use depending on whether we are
+    // currently filtering.
+    Uri baseUri;
+    if (mCurFilter != null) {
+        baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
+                  Uri.encode(mCurFilter));
+    } else {
+        baseUri = Contacts.CONTENT_URI;
+    }
+
+    // Now create and return a CursorLoader that will take care of
+    // creating a Cursor for the data being displayed.
+    String select = &quot;((&quot; + Contacts.DISPLAY_NAME + &quot; NOTNULL) AND (&quot;
+            + Contacts.HAS_PHONE_NUMBER + &quot;=1) AND (&quot;
+            + Contacts.DISPLAY_NAME + &quot; != '' ))&quot;;
+    return new CursorLoader(getActivity(), baseUri,
+            CONTACTS_SUMMARY_PROJECTION, select, null,
+            Contacts.DISPLAY_NAME + &quot; COLLATE LOCALIZED ASC&quot;);
+}</pre>
+<h4 id="onLoadFinished">onLoadFinished</h4>
+
+<p>Metode ini dipanggil bila loader yang dibuat sebelumnya selesai dimuat.
+Metode ini dijamin dipanggil sebelum pelepasan data terakhir
+yang disediakan untuk loader ini.  Di titik ini Anda harus menyingkirkan semua penggunaan
+data lama (karena akan segera dilepas), namun jangan melepas sendiri
+data tersebut karena loader memilikinya dan akan menanganinya.</p>
+
+
+<p>Loader akan melepas data setelah mengetahui bahwa aplikasi tidak
+lagi menggunakannya.  Misalnya, jika data adalah kursor dari {@link
+android.content.CursorLoader}, Anda tidak boleh memanggil {@link
+android.database.Cursor#close close()} sendiri. Jika kursor ditempatkan
+dalam {@link android.widget.CursorAdapter}, Anda harus menggunakan metode {@link
+android.widget.SimpleCursorAdapter#swapCursor swapCursor()} agar
+{@link android.database.Cursor} lama tidak ditutup. Misalnya:</p>
+
+<pre>
+// This is the Adapter being used to display the list's data.<br
+/>SimpleCursorAdapter mAdapter;
+...
+
+public void onLoadFinished(Loader&lt;Cursor&gt; loader, Cursor data) {
+    // Swap the new cursor in.  (The framework will take care of closing the
+    // old cursor once we return.)
+    mAdapter.swapCursor(data);
+}</pre>
+
+<h4 id="onLoaderReset">onLoaderReset</h4>
+
+<p>Metode ini dipanggil bila loader yang dibuat sebelumnya sedang di-reset, sehingga datanya
+tidak tersedia. Callback ini memungkinkan Anda mengetahui
+kapan data akan dilepas sehingga dapat menghapus acuannya ke callback.  </p>
+<p>Implementasi ini memanggil
+{@link android.widget.SimpleCursorAdapter#swapCursor swapCursor()}
+dengan nilai <code>null</code>:</p>
+
+<pre>
+// This is the Adapter being used to display the list's data.
+SimpleCursorAdapter mAdapter;
+...
+
+public void onLoaderReset(Loader&lt;Cursor&gt; loader) {
+    // This is called when the last Cursor provided to onLoadFinished()
+    // above is about to be closed.  We need to make sure we are no
+    // longer using it.
+    mAdapter.swapCursor(null);
+}</pre>
+
+
+<h2 id="example">Contoh</h2>
+
+<p>Sebagai contoh, berikut ini adalah implementasi penuh {@link
+android.app.Fragment} yang menampilkan {@link android.widget.ListView} berisi
+hasil query terhadap penyedia konten kontak. Ia menggunakan {@link
+android.content.CursorLoader} untuk mengelola query pada penyedia.</p>
+
+<p>Agar aplikasi dapat mengakses kontak pengguna, seperti yang ditampilkan dalam contoh ini,
+manifesnya harus menyertakan izin
+{@link android.Manifest.permission#READ_CONTACTS READ_CONTACTS}.</p>
+
+<pre>
+public static class CursorLoaderListFragment extends ListFragment
+        implements OnQueryTextListener, LoaderManager.LoaderCallbacks&lt;Cursor&gt; {
+
+    // This is the Adapter being used to display the list's data.
+    SimpleCursorAdapter mAdapter;
+
+    // If non-null, this is the current filter the user has provided.
+    String mCurFilter;
+
+    @Override public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        // Give some text to display if there is no data.  In a real
+        // application this would come from a resource.
+        setEmptyText(&quot;No phone numbers&quot;);
+
+        // We have a menu item to show in action bar.
+        setHasOptionsMenu(true);
+
+        // Create an empty adapter we will use to display the loaded data.
+        mAdapter = new SimpleCursorAdapter(getActivity(),
+                android.R.layout.simple_list_item_2, null,
+                new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
+                new int[] { android.R.id.text1, android.R.id.text2 }, 0);
+        setListAdapter(mAdapter);
+
+        // Prepare the loader.  Either re-connect with an existing one,
+        // or start a new one.
+        getLoaderManager().initLoader(0, null, this);
+    }
+
+    @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        // Place an action bar item for searching.
+        MenuItem item = menu.add(&quot;Search&quot;);
+        item.setIcon(android.R.drawable.ic_menu_search);
+        item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+        SearchView sv = new SearchView(getActivity());
+        sv.setOnQueryTextListener(this);
+        item.setActionView(sv);
+    }
+
+    public boolean onQueryTextChange(String newText) {
+        // Called when the action bar search text has changed.  Update
+        // the search filter, and restart the loader to do a new query
+        // with this filter.
+        mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
+        getLoaderManager().restartLoader(0, null, this);
+        return true;
+    }
+
+    @Override public boolean onQueryTextSubmit(String query) {
+        // Don't care about this.
+        return true;
+    }
+
+    @Override public void onListItemClick(ListView l, View v, int position, long id) {
+        // Insert desired behavior here.
+        Log.i(&quot;FragmentComplexList&quot;, &quot;Item clicked: &quot; + id);
+    }
+
+    // These are the Contacts rows that we will retrieve.
+    static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
+        Contacts._ID,
+        Contacts.DISPLAY_NAME,
+        Contacts.CONTACT_STATUS,
+        Contacts.CONTACT_PRESENCE,
+        Contacts.PHOTO_ID,
+        Contacts.LOOKUP_KEY,
+    };
+    public Loader&lt;Cursor&gt; onCreateLoader(int id, Bundle args) {
+        // This is called when a new Loader needs to be created.  This
+        // sample only has one Loader, so we don't care about the ID.
+        // First, pick the base URI to use depending on whether we are
+        // currently filtering.
+        Uri baseUri;
+        if (mCurFilter != null) {
+            baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
+                    Uri.encode(mCurFilter));
+        } else {
+            baseUri = Contacts.CONTENT_URI;
+        }
+
+        // Now create and return a CursorLoader that will take care of
+        // creating a Cursor for the data being displayed.
+        String select = &quot;((&quot; + Contacts.DISPLAY_NAME + &quot; NOTNULL) AND (&quot;
+                + Contacts.HAS_PHONE_NUMBER + &quot;=1) AND (&quot;
+                + Contacts.DISPLAY_NAME + &quot; != '' ))&quot;;
+        return new CursorLoader(getActivity(), baseUri,
+                CONTACTS_SUMMARY_PROJECTION, select, null,
+                Contacts.DISPLAY_NAME + &quot; COLLATE LOCALIZED ASC&quot;);
+    }
+
+    public void onLoadFinished(Loader&lt;Cursor&gt; loader, Cursor data) {
+        // Swap the new cursor in.  (The framework will take care of closing the
+        // old cursor once we return.)
+        mAdapter.swapCursor(data);
+    }
+
+    public void onLoaderReset(Loader&lt;Cursor&gt; loader) {
+        // This is called when the last Cursor provided to onLoadFinished()
+        // above is about to be closed.  We need to make sure we are no
+        // longer using it.
+        mAdapter.swapCursor(null);
+    }
+}</pre>
+<h3 id="more_examples">Contoh Selengkapnya</h3>
+
+<p>Ada beberapa contoh berbeda dalam <strong>ApiDemos</strong> yang
+mengilustrasikan cara menggunakan loader:</p>
+<ul>
+  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderCursor.html">
+LoaderCursor</a> — Versi lengkap dari
+cuplikan yang ditampilkan di atas.</li>
+  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a> — Contoh cara penggunaan throttling untuk
+mengurangi jumlah query dari penyedia konten saat datanya berubah.</li>
+</ul>
+
+<p>Untuk informasi tentang mengunduh dan menginstal contoh SDK, lihat <a href="http://developer.android.com/resources/samples/get.html"> Mendapatkan
+Contoh</a>. </p>
+
diff --git a/docs/html-intl/intl/id/guide/components/processes-and-threads.jd b/docs/html-intl/intl/id/guide/components/processes-and-threads.jd
new file mode 100644
index 0000000..cdab715
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/components/processes-and-threads.jd
@@ -0,0 +1,411 @@
+page.title=Proses dan Thread
+page.tags=daur hidup,latar belakang
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>Dalam dokumen ini</h2>
+<ol>
+<li><a href="#Processes">Proses</a>
+  <ol>
+    <li><a href="#Lifecycle">Daur hidup proses</a></li>
+  </ol>
+</li>
+<li><a href="#Threads">Thread</a>
+  <ol>
+    <li><a href="#WorkerThreads">Thread pekerja</a></li>
+    <li><a href="#ThreadSafe">Metode thread-safe</a></li>
+  </ol>
+</li>
+<li><a href="#IPC">Komunikasi antarproses</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>Bila komponen aplikasi dimulai dan tidak ada komponen aplikasi lain yang
+berjalan, sistem Android akan memulai proses Linux baru untuk aplikasi dengan satu thread
+eksekusi. Secara default, semua komponen aplikasi yang sama berjalan dalam proses dan
+thread yang sama (disebut thread "utama"). Jika komponen aplikasi dimulai dan sudah ada
+proses untuk aplikasi itu (karena komponen lain dari aplikasi itu sudah ada), maka komponen
+akan dimulai dalam proses itu dan menggunakan thread eksekusi yang sama. Akan tetapi, Anda bisa
+mengatur komponen berbeda di aplikasi agar berjalan di proses terpisah, dan Anda bisa membuat thread tambahan untuk
+setiap proses.</p>
+
+<p>Dokumen ini membahas cara kerja proses dan thread di aplikasi Android.</p>
+
+
+<h2 id="Processes">Proses</h2>
+
+<p>Secara default, semua komponen aplikasi yang sama berjalan dalam proses yang sama dan kebanyakan
+aplikasi tidak boleh mengubah ini. Akan tetapi, jika Anda merasa perlu mengontrol proses milik
+komponen tertentu, Anda dapat melakukannya dalam file manifes.</p>
+
+<p>Entri manifes untuk setiap tipe elemen komponen&mdash;<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
+&lt;activity&gt;}</a>, <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code
+&lt;service&gt;}</a>, <a href="{@docRoot}guide/topics/manifest/receiver-element.html">{@code
+&lt;receiver&gt;}</a>, dan <a href="{@docRoot}guide/topics/manifest/provider-element.html">{@code
+&lt;provider&gt;}</a>&mdash;mendukung atribut {@code android:process} yang bisa menetapkan
+dalam proses mana komponen harus dijalankan. Anda bisa mengatur atribut ini agar setiap komponen
+berjalan dalam prosesnya sendiri atau agar beberapa komponen menggunakan proses yang sama sementara yang lainnya tidak.  Anda juga bisa mengatur
+{@code android:process} agar komponen aplikasi yang berbeda berjalan dalam proses yang sama
+&mdash;sepanjang aplikasi menggunakan ID Linux yang sama dan ditandatangani
+dengan sertifikat yang sama.</p>
+
+<p>Elemen <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code
+&lt;application&gt;}</a> juga mendukung atribut {@code android:process}, untuk mengatur
+nilai default yang berlaku bagi semua komponen.</p>
+
+<p>Android bisa memutuskan untuk mematikan proses pada waktu tertentu, bila memori tinggal sedikit dan diperlukan oleh
+proses lain yang lebih mendesak untuk melayani pengguna. Komponen
+aplikasi yang berjalan dalam proses yang dimatikan maka sebagai konsekuensinya juga akan dimusnahkan.  Proses dimulai
+kembali untuk komponen itu bila ada lagi pekerjaan untuk mereka lakukan.</p>
+
+<p>Saat memutuskan proses yang akan dimatikan, sistem Android akan mempertimbangkan kepentingan relatifnya bagi
+pengguna.  Misalnya, sistem lebih mudah menghentikan proses yang menjadi host aktivitas yang tidak
+ lagi terlihat di layar, dibandingkan dengan proses yang menjadi host aktivitas yang terlihat. Karena itu, keputusan
+untuk menghentikan proses bergantung pada keadaan komponen yang berjalan dalam proses tersebut. Aturan
+yang digunakan untuk menentukan proses yang akan dihentikan dibahas di bawah ini. </p>
+
+
+<h3 id="Lifecycle">Daur hidup proses</h3>
+
+<p>Sistem Android mencoba mempertahankan proses aplikasi selama mungkin, namun
+pada akhirnya perlu menghapus proses lama untuk mengambil kembali memori bagi proses baru atau yang lebih penting.  Untuk
+menentukan proses yang akan
+dipertahankan dan yang harus dimatikan, sistem menempatkan setiap proses ke dalam "hierarki prioritas" berdasarkan
+komponen yang berjalan dalam proses dan status komponen tersebut.  Proses yang memiliki
+prioritas terendah akan dimatikan terlebih dahulu, kemudian yang terendah berikutnya, dan seterusnya, jika perlu
+untuk memulihkan sumber daya sistem.</p>
+
+<p>Ada lima tingkatan dalam hierarki prioritas. Daftar berikut berisi beberapa
+tipe proses berdasarkan urutan prioritas (proses pertama adalah yang <em>terpenting</em> dan
+<em>dimatikan terakhir</em>):</p>
+
+<ol>
+  <li><b>Proses latar depan</b>
+    <p>Proses yang diperlukan untuk aktivitas yang sedang dilakukan pengguna.  Proses
+dianggap berada di latar depan jika salah satu kondisi berikut terpenuhi:</p>
+
+      <ul>
+        <li>Proses menjadi host {@link android.app.Activity} yang berinteraksi dengan pengguna dengan metode ({@link
+android.app.Activity}{@link android.app.Activity#onResume onResume()} telah
+dipanggil).</li>
+
+        <li>Proses menjadi host {@link android.app.Service} yang terikat dengan aktivitas yang sedang berinteraksi dengan
+pengguna.</li>
+
+        <li>Proses menjadi host {@link android.app.Service} yang berjalan "di latar depan"&mdash;
+layanan telah memanggil{@link android.app.Service#startForeground startForeground()}.
+
+        <li>Proses menjadi host {@link android.app.Service} yang menjalankan salah satu callback
+daur hidupnya ({@link android.app.Service#onCreate onCreate()}, {@link android.app.Service#onStart
+onStart()}, atau {@link android.app.Service#onDestroy onDestroy()}).</li>
+
+        <li>Proses menjadi host {@link android.content.BroadcastReceiver} yang menjalankan metode {@link
+        android.content.BroadcastReceiver#onReceive onReceive()}-nya.</li>
+    </ul>
+
+    <p>Secara umum, hanya ada beberapa proses latar depan pada waktu yang diberikan.  Proses dimatikan hanya sebagai
+upaya terakhir&mdash; jika memori hampir habis sehingga semuanya tidak bisa terus berjalan.  Pada umumnya, pada
+titik itu, perangkat dalam keadaan memory paging, sehingga menghentikan beberapa proses latar depan
+diperlukan agar antarmuka pengguna tetap responsif.</p></li>
+
+  <li><b>Proses yang terlihat</b>
+    <p>Proses yang tidak memiliki komponen latar depan, namun masih bisa
+memengaruhi apa yang dilihat pengguna di layar. Proses dianggap terlihat jika salah satu kondisi
+berikut terpenuhi:</p>
+
+      <ul>
+        <li>Proses ini menjadi host {@link android.app.Activity} yang tidak berada di latar depan, namun masih
+terlihat oleh penggunanya (metode {@link android.app.Activity#onPause onPause()} telah dipanggil).
+Ini bisa terjadi, misalnya, jika aktivitas latar depan memulai dialog, sehingga
+aktivitas sebelumnya terlihat berada di belakangnya.</li>
+
+        <li>Proses menjadi host {@link android.app.Service} yang terikat dengan aktivitas yang terlihat (atau latar
+depan)</li>
+      </ul>
+
+      <p>Proses yang terlihat dianggap sangat penting dan tidak akan dimatikan kecuali jika hal itu
+diperlukan agar semua proses latar depan tetap berjalan. </p>
+    </li>
+
+  <li><b>Proses layanan</b>
+    <p>Proses yang menjalankan layanan yang telah dimulai dengan metode {@link
+android.content.Context#startService startService()} dan tidak termasuk dalam salah satu dari dua kategori
+yang lebih tinggi. Walaupun proses pelayanan tidak langsung terkait dengan semua yang dilihat oleh pengguna, proses ini
+umumnya melakukan hal-hal yang dipedulikan pengguna (seperti memutar musik di latar belakang
+atau mengunduh data di jaringan), jadi sistem membuat proses tetap berjalan kecuali memori tidak cukup untuk
+mempertahankannya bersama semua proses latar depan dan proses yang terlihat. </p>
+  </li>
+
+  <li><b>Proses latar belakang</b>
+    <p>Proses yang menampung aktivitas yang saat ini tidak terlihat oleh pengguna (metode
+{@link android.app.Activity#onStop onStop()} aktivitas telah dipanggil). Proses ini tidak memiliki dampak
+langsung pada pengalaman pengguna, dan sistem bisa menghentikannya kapan saja untuk memperoleh kembali memori bagi
+proses latar depan, proses yang terlihat,
+atau proses layanan. Biasanya ada banyak proses latar belakang yang berjalan, sehingga disimpan
+dalam daftar LRU (least recently used atau paling sedikit digunakan) untuk memastikan bahwa proses dengan aktivitas yang paling baru
+terlihat oleh pengguna sebagai yang terakhir untuk dimatikan. Jika aktivitas mengimplementasikan metode
+ daur hidupnya dengan benar, dan menyimpan statusnya saat ini, menghentikan prosesnya tidak akan memiliki efek
+yang terlihat pada pengalaman pengguna, karena ketika pengguna kembali ke aktivitas, aktivitas itu memulihkan
+semua statusnya yang terlihat. Lihat dokumen <a href="{@docRoot}guide/components/activities.html#SavingActivityState">Aktivitas</a>
+ untuk mendapatkan informasi tentang menyimpan dan memulihkan status.</p>
+  </li>
+
+  <li><b>Proses kosong</b>
+    <p>Sebuah proses yang tidak berisi komponen aplikasi aktif apa pun.  Alasan satu-satunya mempertahankan proses
+seperti ini tetap hidup adalah untuk keperluan caching, meningkatkan waktu mulai (startup) bila
+nanti komponen perlu dijalankan di dalamnya.  Sistem sering menghentikan proses ini untuk menyeimbangkan sumber
+daya sistem secara keseluruhan antara proses cache dan cache kernel yang mendasarinya.</p>
+  </li>
+</ol>
+
+
+  <p>Android sebisa mungkin memeringkat proses setinggi
+mungkin, berdasarkan prioritas komponen yang sedang aktif dalam proses.  Misalnya, jika suatu proses menjadi host sebuah layanan dan
+aktivitas yang terlihat, proses akan diperingkat sebagai proses yang terlihat, bukan sebagai proses layanan.</p>
+
+  <p>Selain itu, peringkat proses dapat meningkat karena adanya proses lain yang bergantung padanya
+&mdash;proses yang melayani proses lain tidak bisa diperingkat lebih rendah daripada proses yang
+sedang dilayaninya. Misalnya, jika penyedia konten dalam proses A melayani klien dalam proses B, atau
+jika layanan dalam proses A terikat dengan komponen dalam proses B, proses A selalu dipertimbangkan sebagai paling rendah
+prioritasnya dibandingkan dengan proses B.</p>
+
+  <p>Karena proses yang menjalankan layanan diperingkat lebih tinggi daripada aktivitas latar belakang,
+aktivitas yang memulai operasi yang berjalan lama mungkin lebih baik memulai <a href="{@docRoot}guide/components/services.html">layanan</a> untuk operasi itu, daripada hanya
+membuat thread pekerja&mdash;khususnya jika operasi mungkin akan berlangsung lebih lama daripada aktivitas.
+ Misalnya, aktivitas yang mengunggah gambar ke situs web harus memulai layanan
+untuk mengunggah sehingga unggahan bisa terus berjalan di latar belakang meskipun pengguna meninggalkan aktivitas tersebut.
+Menggunakan layanan akan memastikan operasi paling tidak memiliki prioritas "proses layanan",
+apa pun yang terjadi pada aktivitas. Ini menjadi alasan yang sama yang membuat penerima siaran harus
+menjalankan layanan daripada hanya menempatkan operasi yang menghabiskan waktu di thread.</p>
+
+
+
+
+<h2 id="Threads">Thread</h2>
+
+<p>Bila aplikasi diluncurkan, sistem akan membuat thread eksekusi untuk aplikasi tersebut, yang diberi nama,
+"main". Thread ini sangat penting karena bertugas mengirim kejadian ke widget
+antarmuka pengguna yang sesuai, termasuk kejadian menggambar. Ini juga merupakan thread yang
+membuat aplikasi berinteraksi dengan komponen dari Android UI toolkit (komponen dari paket {@link
+android.widget} dan {@link android.view}). Karena itu, thread 'main' juga terkadang
+disebut thread UI.</p>
+
+<p>Sistem ini <em>tidak</em> membuat thread terpisah untuk setiap instance komponen. Semua
+komponen yang berjalan di proses yang sama akan dibuat instance-nya dalam thread UI, dan sistem akan memanggil
+setiap komponen yang dikirim dari thread itu. Akibatnya, metode yang merespons callback sistem
+ (seperti {@link android.view.View#onKeyDown onKeyDown()} untuk melaporkan tindakan pengguna atau metode callback daur hidup)
+ selalu berjalan di thread UI proses.</p>
+
+<p>Misalnya saat pengguna menyentuh tombol pada layar, thread UI aplikasi akan mengirim kejadian
+sentuh ke widget, yang selanjutnya menetapkan status ditekan dan mengirim permintaan yang tidak divalidasi ke
+antrean kejadian. Thread UI akan menghapus antrean permintaan dan memberi tahu widget bahwa widget harus menggambar
+dirinya sendiri.</p>
+
+<p>Saat aplikasi melakukan pekerjaan intensif sebagai respons terhadap interaksi pengguna, model
+thread tunggal ini bisa menghasilkan kinerja yang buruk kecuali jika Anda mengimplementasikan aplikasi dengan benar. Khususnya jika
+ semua terjadi di thread UI, melakukan operasi yang panjang seperti akses ke jaringan atau query
+database akan memblokir seluruh UI. Bila thread diblokir, tidak ada kejadian yang bisa dikirim,
+termasuk kejadian menggambar. Dari sudut pandang pengguna, aplikasi
+tampak mogok (hang). Lebih buruk lagi, jika thread UI diblokir selama lebih dari beberapa detik
+(saat ini sekitar 5 detik) pengguna akan ditampilkan dialog "<a href="http://developer.android.com/guide/practices/responsiveness.html">aplikasi tidak
+merespons</a>" (ANR) yang populer karena reputasi buruknya. Pengguna nanti bisa memutuskan untuk keluar dari aplikasi dan menghapus aplikasi
+jika mereka tidak suka.</p>
+
+<p>Selain itu, toolkit Android UI <em>bukan</em> thread-safe. Jadi, Anda tidak harus memanipulasi
+UI dari thread pekerja&mdash;Anda harus melakukan semua manipulasi pada antarmuka pengguna dari thread
+UI. Sehingga hanya ada dua aturan untuk model thread tunggal Android:</p>
+
+<ol>
+<li>Jangan memblokir thread UI
+<li>Jangan mengakses toolkit Android UI dari luar thread UI
+</ol>
+
+<h3 id="WorkerThreads">Thread pekerja</h3>
+
+<p>Karena model thread tunggal yang dijelaskan di atas, Anda dilarang memblokir thread
+UI demi daya respons UI aplikasi. Jika memiliki operasi untuk dijalankan
+yang tidak seketika, Anda harus memastikan untuk melakukannya di thread terpisah (thread "latar belakang" atau
+thread "pekerja").</p>
+
+<p>Misalnya, berikut ini beberapa kode untuk listener klik yang mengunduh gambar dari
+thread terpisah dan menampilkannya dalam {@link android.widget.ImageView}:</p>
+
+<pre>
+public void onClick(View v) {
+    new Thread(new Runnable() {
+        public void run() {
+            Bitmap b = loadImageFromNetwork("http://example.com/image.png");
+            mImageView.setImageBitmap(b);
+        }
+    }).start();
+}
+</pre>
+
+<p>Awalnya hal ini tampak bekerja dengan baik, karena menciptakan thread baru untuk menangani
+operasi jaringan. Akan tetapi, hal tersebut melanggar aturan kedua model thread tunggal: <em>jangan mengakses
+ toolkit Android UI dari luar thread UI</em>&mdash;sampel ini memodifikasi {@link
+android.widget.ImageView} dari thread pekerja sebagai ganti thread UI. Ini bisa
+mengakibatkan perilaku yang tidak terdefinisi dan tidak diharapkan, yang bisa menyulitkan dan menghabiskan waktu untuk melacaknya.</p>
+
+<p>Untuk memperbaiki masalah ini, Android menawarkan beberapa cara untuk mengakses thread UI dari
+thread lainnya. Berikut ini daftar metode yang bisa membantu:</p>
+
+<ul>
+<li>{@link android.app.Activity#runOnUiThread(java.lang.Runnable)
+Activity.runOnUiThread(Runnable)}</li>
+<li>{@link android.view.View#post(java.lang.Runnable) View.post(Runnable)}</li>
+<li>{@link android.view.View#postDelayed(java.lang.Runnable, long) View.postDelayed(Runnable,
+long)}</li>
+</ul>
+
+<p>Misalnya, Anda bisa memperbaiki kode di atas dengan menggunakan metode {@link
+android.view.View#post(java.lang.Runnable) View.post(Runnable)}:</p>
+
+<pre>
+public void onClick(View v) {
+    new Thread(new Runnable() {
+        public void run() {
+            final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
+            mImageView.post(new Runnable() {
+                public void run() {
+                    mImageView.setImageBitmap(bitmap);
+                }
+            });
+        }
+    }).start();
+}
+</pre>
+
+<p>Kini implementasi ini thread-safe: operasi jaringan dilakukan terpisah dari thread
+ sementara {@link android.widget.ImageView} dimanipulasi dari thread UI.</p>
+
+<p>Akan tetapi, karena operasi semakin kompleks, jenis kode seperti ini bisa semakin rumit
+dan sulit dipertahankan. Untuk menangani interaksi yang lebih kompleks dengan thread pekerja, Anda bisa mempertimbangkan
+ penggunaan {@link android.os.Handler}di thread pekerja, untuk memproses pesan yang dikirim dari
+ thread UI. Mungkin solusi terbaiknya adalah memperpanjang kelas {@link android.os.AsyncTask},
+yang akan menyederhanakan eksekusi tugas-tugas thread pekerja yang perlu berinteraksi dengan UI.</p>
+
+
+<h4 id="AsyncTask">Menggunakan AsyncTask</h4>
+
+<p>Dengan {@link android.os.AsyncTask}, Anda bisa melakukan pekerjaan asinkron pada antarmuka
+pengguna. AsyncTask memblokir operasi di thread pekerja kemudian mempublikasikan hasilnya
+di thread UI, tanpa mengharuskan Anda untuk menangani sendiri thread dan/atau handler sendiri.</p>
+
+<p>Untuk menggunakannya, Anda harus menempatkan {@link android.os.AsyncTask} sebagai subkelas dan mengimplementasikan metode callback {@link
+android.os.AsyncTask#doInBackground doInBackground()} yang berjalan di kumpulan
+thread latar belakang. Untuk memperbarui UI, Anda harus mengimplementasikan {@link
+android.os.AsyncTask#onPostExecute onPostExecute()}, yang memberikan hasil dari {@link
+android.os.AsyncTask#doInBackground doInBackground()} dan berjalan di thread UI, jadi Anda bisa
+memperbarui UI dengan aman. Selanjutnya Anda bisa menjalankan tugas dengan memanggil {@link android.os.AsyncTask#execute execute()}
+dari thread UI.</p>
+
+<p>Misalnya, Anda bisa mengimplementasikan contoh sebelumnya menggunakan {@link android.os.AsyncTask} dengan cara
+ini:</p>
+
+<pre>
+public void onClick(View v) {
+    new DownloadImageTask().execute("http://example.com/image.png");
+}
+
+private class DownloadImageTask extends AsyncTask&lt;String, Void, Bitmap&gt; {
+    /** The system calls this to perform work in a worker thread and
+      * delivers it the parameters given to AsyncTask.execute() */
+    protected Bitmap doInBackground(String... urls) {
+        return loadImageFromNetwork(urls[0]);
+    }
+
+    /** The system calls this to perform work in the UI thread and delivers
+      * the result from doInBackground() */
+    protected void onPostExecute(Bitmap result) {
+        mImageView.setImageBitmap(result);
+    }
+}
+</pre>
+
+<p>Kini UI aman dan kode jadi lebih sederhana, karena memisahkan pekerjaan ke
+dalam bagian-bagian yang harus dilakukan pada thread pekerja dan thread UI.</p>
+
+<p>Anda harus membaca acuan {@link android.os.AsyncTask} untuk memahami sepenuhnya
+cara menggunakan kelas ini, namun berikut ini ikhtisar singkat cara kerjanya:</p>
+
+<ul>
+<li>Anda bisa menetapkan tipe parameter, nilai kemajuan, dan nilai
+ akhir tugas, dengan menggunakan generik</li>
+<li>Metode {@link android.os.AsyncTask#doInBackground doInBackground()} berjalan secara otomatis pada
+thread pekerja</li>
+<li>{@link android.os.AsyncTask#onPreExecute onPreExecute()}, {@link
+android.os.AsyncTask#onPostExecute onPostExecute()}, dan {@link
+android.os.AsyncTask#onProgressUpdate onProgressUpdate()} semuanya dipanggil pada thread UI</li>
+<li>Nilai yang dikembalikan oleh {@link android.os.AsyncTask#doInBackground doInBackground()} akan dikirim ke
+{@link android.os.AsyncTask#onPostExecute onPostExecute()}</li>
+<li>Anda bisa memangil {@link android.os.AsyncTask#publishProgress publishProgress()} setiap saat di {@link
+android.os.AsyncTask#doInBackground doInBackground()} untuk mengeksekusi {@link
+android.os.AsyncTask#onProgressUpdate onProgressUpdate()} pada thread UI</li>
+<li>Anda bisa membatalkan tugas ini kapan saja, dari thread mana saja</li>
+</ul>
+
+<p class="caution"><strong>Perhatian:</strong> Masalah lain yang mungkin Anda temui saat menggunakan
+thread pekerja adalah restart tak terduga dalam aktivitas karena <a href="{@docRoot}guide/topics/resources/runtime-changes.html">perubahan konfigurasi runtime</a>
+ (seperti saat pengguna mengubah orientasi layar), yang bisa memusnahkan thread pekerja. Untuk
+melihat cara mempertahankan tugas selama restart ini dan cara membatalkan
+tugas dengan benar saat aktivitas dimusnahkan, lihat kode sumber untuk aplikasi sampel <a href="http://code.google.com/p/shelves/">Shelves</a>.</p>
+
+
+<h3 id="ThreadSafe">Metode thread-safe</h3>
+
+<p> Dalam beberapa situasi, metode yang Anda implementasikan bisa dipanggil dari lebih dari satu thread,
+dan karena itu harus ditulis agar menjadi thread-safe. </p>
+
+<p>Ini terutama terjadi untuk metode yang bisa dipanggil dari jauh &mdash;seperti metode dalam <a href="{@docRoot}guide/components/bound-services.html">layanan terikat</a>. Bila sebuah panggilan pada
+metode yang dijalankan dalam {@link android.os.IBinder} berasal dari proses yang sama di mana
+{@link android.os.IBinder IBinder} berjalan, metode ini akan dieksekusi di thread pemanggil.
+Akan tetapi, bila panggilan berasal proses lain, metode akan dieksekusi dalam thread yang dipilih dari
+ kumpulan (pool) thread yang dipertahankan sistem dalam proses yang sama seperti{@link android.os.IBinder
+IBinder} (tidak dieksekusi dalam thread UI proses).  Misalnya, karena metode
+{@link android.app.Service#onBind onBind()} layanan akan dipanggil dari thread UI
+proses layanan, metode yang diimplementasikan dalam objek yang dikembalikan {@link android.app.Service#onBind
+onBind()} (misalnya, subkelas yang mengimplementasikan metode RPC) akan dipanggil dari thread
+di pool. Karena layanan bisa memiliki lebih dari satu klien, maka lebih dari satu pool thread bisa melibatkan
+ metode {@link android.os.IBinder IBinder} yang sama sekaligus. Metode {@link android.os.IBinder
+IBinder} karenanya harus diimplementasikan sebagai thread-safe.</p>
+
+<p> Penyedia konten juga bisa menerima permintaan data yang berasal dalam proses lain.
+Meskipun kelas {@link android.content.ContentResolver} dan {@link android.content.ContentProvider}
+ menyembunyikan detail cara komunikasi antarproses dikelola, metode {@link
+android.content.ContentProvider} yang merespons permintaan itu&mdash;metode {@link
+android.content.ContentProvider#query query()}, {@link android.content.ContentProvider#insert
+insert()}, {@link android.content.ContentProvider#delete delete()}, {@link
+android.content.ContentProvider#update update()}, dan {@link android.content.ContentProvider#getType
+getType()}&mdash; dipanggil dari pool thread pada proses penyedia konten, bukan thread UI
+untuk proses tersebut.  Mengingat metode ini bisa dipanggil dari thread mana pun
+sekaligus, metode-metode ini juga harus diimplementasikan sebagai thread-safe. </p>
+
+
+<h2 id="IPC">Komunikasi Antarproses</h2>
+
+<p>Android menawarkan mekanisme komunikasi antarproses (IPC) menggunakan panggilan prosedur jauh
+ (RPC), yang mana metode ini dipanggil oleh aktivitas atau komponen aplikasi lain, namun dieksekusi dari
+jauh (di proses lain), bersama hasil yang dikembalikan ke
+pemanggil. Ini mengharuskan penguraian panggilan metode dan datanya ke tingkat yang bisa
+dipahami sistem operasi, mentransmisikannya dari proses lokal dan ruang alamat untuk proses jauh
+dan ruang proses, kemudian merakit kembali dan menetapkannya kembali di sana.  Nilai-nilai yang dikembalikan
+akan ditransmisikan dalam arah berlawanan.  Android menyediakan semua kode untuk melakukan transaksi IPC
+ ini, sehingga Anda bisa fokus pada pendefinisian dan implementasi antarmuka pemrograman RPC. </p>
+
+<p>Untuk melakukan IPC, aplikasi Anda harus diikat ke layanan, dengan menggunakan {@link
+android.content.Context#bindService bindService()}. Untuk informasi selengkapnya, lihat panduan pengembang <a href="{@docRoot}guide/components/services.html">Layanan</a>.</p>
+
+
+<!--
+<h2>Beginner's Path</h2>
+
+<p>For information about how to perform work in the background for an indefinite period of time
+(without a user interface), continue with the <b><a
+href="{@docRoot}guide/components/services.html">Services</a></b> document.</p>
+-->
diff --git a/docs/html-intl/intl/id/guide/components/recents.jd b/docs/html-intl/intl/id/guide/components/recents.jd
new file mode 100644
index 0000000..286fdc1
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/components/recents.jd
@@ -0,0 +1,256 @@
+page.title=Layar Ikhtisar
+page.tags="recents","overview"
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+  <h2>Dalam dokumen ini</h2>
+  <ol>
+    <li><a href="#adding">Menambahkan Tugas ke Layar Ikhtisar</a>
+      <ol>
+        <li><a href="#flag-new-doc">Menggunakan flag Intent untuk menambahkan tugas</a></li>
+        <li><a href="#attr-doclaunch">Menggunakan atribut Aktivitas untuk menambahkan tugas</a></li>
+      </ol>
+    </li>
+    <li><a href="#removing">Menghapus Tugas</a>
+      <ol>
+        <li><a href="#apptask-remove">Menggunakan kelas AppTask untuk menghapus tugas</a></li>
+        <li><a href="#retain-finished">Mempertahankan tugas yang telah selesai</a></li>
+      </ol>
+    </li>
+  </ol>
+
+  <h2>Kelas-kelas utama</h2>
+  <ol>
+    <li>{@link android.app.ActivityManager.AppTask}</li>
+    <li>{@link android.content.Intent}</li>
+  </ol>
+
+  <h2>Kode contoh</h2>
+  <ol>
+    <li><a href="{@docRoot}samples/DocumentCentricApps/index.html">Aplikasi yang berorientasi dokumen</a></li>
+  </ol>
+
+</div>
+</div>
+
+<p>Layar ikhtisar (juga disebut sebagai layar terbaru, daftar tugas terbaru, atau aplikasi terbaru)
+UI tingkat sistem yang mencantumkan <a href="{@docRoot}guide/components/activities.html">
+aktivitas</a> dan <a href="{@docRoot}guide/components/tasks-and-back-stack.html">tugas</a> yang baru saja diakses. Pengguna
+bisa menyusuri daftar ini dan memilih satu tugas untuk dilanjutkan, atau pengguna bisa menghapus tugas dari
+daftar dengan gerakan mengusap. Dengan dirilisnya Android 5.0 (API level 21), beberapa instance aktivitas yang
+sama yang berisi dokumen berbeda dapat muncul sebagai tugas di layar ikhtisar. Misalnya,
+Google Drive mungkin memiliki satu tugas untuk setiap beberapa dokumen Google. Setiap dokumen muncul sebagai
+tugas dalam layar ikhtisar.</p>
+
+<img src="{@docRoot}images/components/recents.png" alt="" width="284" />
+<p class="img-caption"><strong>Gambar 1.</strong> Layar ikhtisar menampilkan tiga dokumen
+Google Drive, masing-masing dinyatakan sebagai tugas terpisah.</p>
+
+<p>Biasanya Anda harus mengizinkan sistem mendefinisikan cara menyatakan tugas dan
+aktivitas di layar ikhtisar, dan Anda tidak perlu memodifikasi perilaku ini.
+Akan tetapi, aplikasi Anda dapat menentukan cara dan waktu munculnya aktivitas di layar ikhtisar. Kelas
+{@link android.app.ActivityManager.AppTask} memungkinkan Anda mengelola tugas, dan flag
+ aktivitas kelas {@link android.content.Intent} memungkinkan Anda menentukan kapan aktivitas ditambahkan atau dihapus dari
+layar ikhtisar. Selain itu, atribut <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">
+&lt;activity&gt;</a></code> memungkinkan Anda menetapkan perilaku di manifes.</p>
+
+<h2 id="adding">Menambahkan Tugas ke Layar Ikhtisar</h2>
+
+<p>Penggunaan flag kelas {@link android.content.Intent} untuk menambahkan tugas memberi kontrol lebih besar
+atas waktu dan cara dokumen dibuka atau dibuka kembali di layar ikhtisar. Bila menggunakan atribut
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+, Anda dapat memilih antara selalu membuka dokumen dalam tugas baru atau menggunakan kembali tugas
+yang ada untuk dokumen tersebut.</p>
+
+<h3 id="flag-new-doc">Menggunakan flag Intent untuk menambahkan tugas</h3>
+
+<p>Bila membuat dokumen baru untuk aktivitas, Anda memanggil metode
+{@link android.app.ActivityManager.AppTask#startActivity(android.content.Context, android.content.Intent, android.os.Bundle) startActivity()}
+ dari kelas {@link android.app.ActivityManager.AppTask}, dengan meneruskannya ke intent yang
+menjalankan aktivitas tersebut. Untuk menyisipkan jeda logis agar sistem memperlakukan aktivitas Anda sebagai tugas
+baru di layar ikhtisar, teruskan flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT}
+dalam metode {@link android.content.Intent#addFlags(int) addFlags()} dari {@link android.content.Intent}
+yang memulai aktivitas itu.</p>
+
+<p class="note"><strong>Catatan:</strong> Flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT}
+menggantikan flag {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET},
+yang tidak digunakan lagi pada Android 5.0 (API level 21).</p>
+
+<p>Jika Anda menetapkan flag {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK} saat membuat
+dokumen baru, sistem akan selalu membuat tugas baru dengan aktivitas target sebagai akar.
+Dengan pengaturan ini, dokumen yang sama dapat dibuka di lebih dari satu tugas. Kode berikut memperagakan
+cara aktivitas utama melakukannya:</p>
+
+<p class="code-caption"><a href="{@docRoot}samples/DocumentCentricApps/index.html">
+DocumentCentricActivity.java</a></p>
+<pre>
+public void createNewDocument(View view) {
+      final Intent newDocumentIntent = newDocumentIntent();
+      if (useMultipleTasks) {
+          newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+      }
+      startActivity(newDocumentIntent);
+  }
+
+  private Intent newDocumentIntent() {
+      boolean useMultipleTasks = mCheckbox.isChecked();
+      final Intent newDocumentIntent = new Intent(this, NewDocumentActivity.class);
+      newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
+      newDocumentIntent.putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, incrementAndGet());
+      return newDocumentIntent;
+  }
+
+  private static int incrementAndGet() {
+      Log.d(TAG, "incrementAndGet(): " + mDocumentCounter);
+      return mDocumentCounter++;
+  }
+}
+</pre>
+
+<p class="note"><strong>Catatan:</strong> Aktivitas yang dimulai dengan flag {@code FLAG_ACTIVITY_NEW_DOCUMENT}
+ harus telah menetapkan nilai atribut {@code android:launchMode="standard"} (default) dalam
+manifes.</p>
+
+<p>Bila aktivitas utama memulai aktivitas baru, sistem akan mencari tugas yang intent
+-nya cocok dengan nama komponen intent dalam tugas-tugas yang sudah ada dan mencari aktivitas dalam data Intent. Jika tugas
+tidak ditemukan, atau intent ada dalam flag {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}
+, tugas baru akan dibuat dengan aktivitas tersebut sebagai akarnya. Jika ditemukan, sistem akan
+mengedepankan tugas itu dan meneruskan intent baru ke {@link android.app.Activity#onNewIntent onNewIntent()}.
+Aktivitas baru akan mendapatkan intent dan membuat dokumen baru di layar ikhtisar, seperti dalam
+contoh berikut:</p>
+
+<p class="code-caption"><a href="{@docRoot}samples/DocumentCentricApps/index.html">
+NewDocumentActivity.java</a></p>
+<pre>
+&#64;Override
+protected void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    setContentView(R.layout.activity_new_document);
+    mDocumentCount = getIntent()
+            .getIntExtra(DocumentCentricActivity.KEY_EXTRA_NEW_DOCUMENT_COUNTER, 0);
+    mDocumentCounterTextView = (TextView) findViewById(
+            R.id.hello_new_document_text_view);
+    setDocumentCounterText(R.string.hello_new_document_counter);
+}
+
+&#64;Override
+protected void onNewIntent(Intent intent) {
+    super.onNewIntent(intent);
+    /* If FLAG_ACTIVITY_MULTIPLE_TASK has not been used, this activity
+    is reused to create a new document.
+     */
+    setDocumentCounterText(R.string.reusing_document_counter);
+}
+</pre>
+
+
+<h3 id="#attr-doclaunch">Menggunakan atribut Aktivitas untuk menambahkan tugas</h3>
+
+<p>Aktivitas juga dapat menetapkan dalam manifesnya agar selalu dimulai ke dalam tugas baru dengan menggunakan
+atribut <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+, <a href="{@docRoot}guide/topics/manifest/activity-element.html#dlmode">
+{@code android:documentLaunchMode}</a>. Atribut ini memiliki empat nilai yang menghasilkan efek berikut
+bila pengguna membuka dokumen dengan aplikasi:</p>
+
+<dl>
+  <dt>"{@code intoExisting}"</dt>
+  <dd>Aktivitas menggunakan kembali tugas yang ada untuk dokumen tersebut. Ini sama dengan mengatur flag
+ {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} <em>tanpa</em> mengatur flag
+ {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}, seperti dijelaskan dalam
+ <a href="#flag-new-doc">Menggunakan flag Intent untuk menambahkan tugas</a>, di atas.</dd>
+
+  <dt>"{@code always}"</dt>
+  <dd>Aktivitas ini membuat tugas baru untuk dokumen, meski dokumen sudah dibuka. Menggunakan
+ nilai ini sama dengan menetapkan flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT}
+ maupun {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}.</dd>
+
+  <dt>"{@code none”}"</dt>
+  <dd>Aktivitas ini tidak membuat tugas baru untuk dokumen. Layar ikhtisar memperlakukan
+ aktivitas seperti itu secara default: satu tugas ditampilkan untuk aplikasi, yang
+dilanjutkan dari aktivitas apa pun yang terakhir dipanggil pengguna.</dd>
+
+  <dt>"{@code never}"</dt>
+  <dd>Aktivitas ini tidak membuat tugas baru untuk dokumen. Mengatur nilai ini akan mengesampingkan
+ perilaku flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT}
+ dan {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}, jika salah satunya ditetapkan di
+intent, dan layar ikhtisar menampilkan satu tugas untuk aplikasi, yang dilanjutkan dari
+ aktivitas apa pun yang terakhir dipanggil pengguna.</dd>
+</dl>
+
+<p class="note"><strong>Catatan:</strong> Untuk nilai selain {@code none} dan {@code never},
+aktivitas harus didefinisikan dengan {@code launchMode="standard"}. Jika atribut ini tidak ditetapkan, maka
+{@code documentLaunchMode="none"} akan digunakan.</p>
+
+<h2 id="removing">Menghapus Tugas</h2>
+
+<p>Secara default, tugas dokumen secara otomatis dihapus dari layar ikhtisar bila aktivitasnya
+selesai. Anda bisa mengesampingkan perilaku ini dengan kelas {@link android.app.ActivityManager.AppTask},
+dengan flag {@link android.content.Intent} atau atribut <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">
+&lt;activity&gt;</a></code>.</p>
+
+<p>Kapan saja Anda bisa mengecualikan tugas dari layar ikhtisar secara keseluruhan dengan menetapkan atribut
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+, <a href="{@docRoot}guide/topics/manifest/activity-element.html#exclude">
+{@code android:excludeFromRecents}</a> hingga {@code true}.</p>
+
+<p>Anda bisa menetapkan jumlah maksimum tugas yang dapat disertakan aplikasi Anda dalam layar ikhtisar dengan menetapkan
+atribut <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+ <a href="{@docRoot}guide/topics/manifest/activity-element.html#maxrecents">{@code android:maxRecents}
+</a> ke satu nilai integer. Nilai default-nya adalah 16. Bila telah mencapai jumlah maksimum, tugas yang terakhir
+digunakan akan dihapus dari layar ikhtisar. Nilai maksimum {@code android:maxRecents}
+ adalah 50 (25 pada perangkat dengan memori sedikit); nilai yang kurang dari 1 tidak berlaku.</p>
+
+<h3 id="#apptask-remove">Menggunakan kelas AppTask untuk menghapus tugas</h3>
+
+<p>Dalam aktivitas yang membuat tugas baru di layar ikhtisar, Anda bisa
+menetapkan kapan menghapus tugas dan menyelesaikan semua aktivitas yang terkait dengannya
+dengan memanggil metode {@link android.app.ActivityManager.AppTask#finishAndRemoveTask() finishAndRemoveTask()}.</p>
+
+<p class="code-caption"><a href="{@docRoot}samples/DocumentCentricApps/index.html">
+NewDocumentActivity.java</a></p>
+<pre>
+public void onRemoveFromRecents(View view) {
+    // The document is no longer needed; remove its task.
+    finishAndRemoveTask();
+}
+</pre>
+
+<p class="note"><strong>Catatan:</strong> Penggunaan metode
+{@link android.app.ActivityManager.AppTask#finishAndRemoveTask() finishAndRemoveTask()}
+akan mengesampingkan penggunaan tag {@link android.content.Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS}, seperti
+dibahas di bawah ini.</p>
+
+<h3 id="#retain-finished">Mempertahankan tugas yang telah selesai</h3>
+
+<p>Jika Anda ingin mempertahankan tugas di layar ikhtisar, sekalipun aktivitas sudah selesai, teruskan
+flag {@link android.content.Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS} dalam metode
+{@link android.content.Intent#addFlags(int) addFlags()} dari Intent yang memulai aktivitas itu.</p>
+
+<p class="code-caption"><a href="{@docRoot}samples/DocumentCentricApps/index.html">
+DocumentCentricActivity.java</a></p>
+<pre>
+private Intent newDocumentIntent() {
+    final Intent newDocumentIntent = new Intent(this, NewDocumentActivity.class);
+    newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
+      android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
+    newDocumentIntent.putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, incrementAndGet());
+    return newDocumentIntent;
+}
+</pre>
+
+<p>Untuk memperoleh efek yang sama, tetapkan atribut
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+ <a href="{@docRoot}guide/topics/manifest/activity-element.html#autoremrecents">
+{@code android:autoRemoveFromRecents}</a> hingga {@code false}. Nilai default-nya adalah {@code true}
+untuk aktivitas dokumen, dan {@code false} untuk aktivitas biasa. Penggunaan atribut ini akan mengesampingkan flag
+{@link android.content.Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS}, yang telah dibahas sebelumnya.</p>
+
+
+
+
+
+
+
diff --git a/docs/html-intl/intl/id/guide/components/services.jd b/docs/html-intl/intl/id/guide/components/services.jd
new file mode 100644
index 0000000..b36e565
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/components/services.jd
@@ -0,0 +1,813 @@
+page.title=Layanan
+@jd:body
+
+<div id="qv-wrapper">
+<ol id="qv">
+<h2>Dalam dokumen ini</h2>
+<ol>
+<li><a href="#Basics">Dasar-Dasar</a></li>
+<ol>
+  <li><a href="#Declaring">Mendeklarasikan layanan dalam manifes</a></li>
+</ol>
+<li><a href="#CreatingAService">Membuat Layanan yang Sudah Dimulai</a>
+  <ol>
+    <li><a href="#ExtendingIntentService">Memperluas kelas IntentService</a></li>
+    <li><a href="#ExtendingService">Memperluas kelas Layanan</a></li>
+    <li><a href="#StartingAService">Memulai layanan</a></li>
+    <li><a href="#Stopping">Menghentikan layanan</a></li>
+  </ol>
+</li>
+<li><a href="#CreatingBoundService">Membuat Layanan Terikat</a></li>
+<li><a href="#Notifications">Mengirim Pemberitahuan ke Pengguna</a></li>
+<li><a href="#Foreground">Menjalankan Layanan di Latar Depan</a></li>
+<li><a href="#Lifecycle">Mengelola Daur Hidup Layanan</a>
+<ol>
+  <li><a href="#LifecycleCallbacks">Mengimplementasikan callback daur hidup</a></li>
+</ol>
+</li>
+</ol>
+
+<h2>Kelas-kelas utama</h2>
+<ol>
+  <li>{@link android.app.Service}</li>
+  <li>{@link android.app.IntentService}</li>
+</ol>
+
+<h2>Contoh</h2>
+<ol>
+  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.html">{@code
+      ServiceStartArguments}</a></li>
+  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
+      LocalService}</a></li>
+</ol>
+
+<h2>Lihat juga</h2>
+<ol>
+<li><a href="{@docRoot}guide/components/bound-services.html">Layanan Terikat</a></li>
+</ol>
+
+</div>
+
+
+<p>{@link android.app.Service} adalah sebuah komponen aplikasi yang bisa melakukan
+operasi yang berjalan lama di latar belakang dan tidak menyediakan antarmuka pengguna. Komponen
+aplikasi lain bisa memulai layanan dan komponen aplikasi tersebut akan terus berjalan
+di latar belakang walaupun pengguna beralih ke aplikasi lain. Selain itu, komponen bisa mengikat ke layanan
+untuk berinteraksi dengannya dan bahkan melakukan komunikasi antarproses (IPC). Misalnya, layanan mungkin
+menangani transaksi jaringan, memutar musik, melakukan file I/O, atau berinteraksi dengan penyedia konten
+dari latar belakang.</p>
+
+<p>Ada dua bentuk dasar layanan:</p>
+
+<dl>
+  <dt>Sudah Dimulai</dt>
+  <dd>Layanan "sudah dimulai" bila komponen aplikasi (misalnya aktivitas) memulainya dengan
+memanggil {@link android.content.Context#startService startService()}. Sesudah dimulai, layanan
+bisa berjalan terus-menerus di latar belakang walaupun komponen yang memulainya telah dimusnahkan. Biasanya,
+layanan yang sudah dimulai akan melakukan operasi tunggal dan tidak mengembalikan hasil ke pemanggilnya.
+Misalnya, layanan bisa mengunduh atau mengunggah file melalui jaringan. Bila operasi selesai,
+layanan seharusnya berhenti sendiri.</dd>
+  <dt>Terikat</dt>
+  <dd>Layanan "terikat" bila komponen aplikasi mengikat kepadanya dengan memanggil {@link
+android.content.Context#bindService bindService()}. Layanan terikat menawarkan antarmuka
+klien-server yang memungkinkan komponen berinteraksi dengan layanan tersebut, mengirim permintaan, mendapatkan hasil dan bahkan
+melakukannya pada sejumlah proses dengan komunikasi antarproses (IPC). Layanan terikat hanya berjalan selama
+ada komponen aplikasi lain yang terikat padanya. Sejumlah komponen bisa terikat pada layanan secara bersamaan,
+namun bila semuanya melepas ikatan, layanan tersebut akan dimusnahkan.</dd>
+</dl>
+
+<p>Walaupun dokumentasi ini secara umum membahas kedua jenis layanan secara terpisah, layanan
+Anda bisa menggunakan keduanya&mdash;layanan bisa dimulai (untuk berjalan terus-menerus) sekaligus memungkinkan pengikatan.
+Cukup mengimplementasikan dua metode callback: {@link
+android.app.Service#onStartCommand onStartCommand()} untuk memungkinkan komponen memulainya dan {@link
+android.app.Service#onBind onBind()} untuk memungkinkan pengikatan.</p>
+
+<p>Apakah aplikasi Anda sudah dimulai, terikat, atau keduanya, semua komponen aplikasi
+bisa menggunakan layanan (bahkan dari aplikasi terpisah), demikian pula semua komponen bisa menggunakan
+suatu aktivitas&mdash;dengan memulainya dengan {@link android.content.Intent}. Akan tetapi, Anda bisa mendeklarasikan
+layanan sebagai privat, pada file manifes, dan memblokir akses dari aplikasi lain. Hal ini
+dibahas selengkapnya di bagian tentang <a href="#Declaring">Mendeklarasikan layanan dalam
+manifes</a>.</p>
+
+<p class="caution"><strong>Perhatian:</strong> Layanan berjalan di
+thread utama proses yang menjadi host-nya&mdash;layanan <strong>tidak</strong> membuat thread-nya sendiri
+dan <strong>tidak</strong> berjalan pada proses terpisah (kecuali bila Anda tentukan demikian). Artinya,
+jika layanan Anda akan melakukan pekerjaan yang membutuhkan tenaga CPU besar atau operasi yang memblokir (seperti
+pemutaran MP3 atau jaringan), Anda perlu membuat thread baru dalam layanan untuk melakukan pekerjaan tersebut. Dengan menggunakan
+thread terpisah, Anda mengurangi risiko terjadinya kesalahan Aplikasi Tidak Merespons (Application Not Responding/ANR) dan
+thread utama aplikasi bisa tetap dikhususkan pada interaksi pengguna dengan aktivitas Anda.</p>
+
+
+<h2 id="Basics">Dasar-Dasar</h2>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+  <h3>Haruskah menggunakan layanan atau thread?</h3>
+  <p>Layanan sekadar komponen yang bisa berjalan di latar belakang walaupun pengguna sedang tidak
+berinteraksi dengan aplikasi Anda. Sehingga, Anda harus membuat layanan bila memang itu
+yang dibutuhkan.</p>
+  <p>Bila Anda perlu melakukan pekerjaan di luar thread utama, namun hanya bila pengguna sedang berinteraksi
+dengan aplikasi, maka Anda harus membuat thread baru sebagai ganti layanan baru. Misalnya,
+bila Anda ingin memutar musik, namun hanya saat aktivitas Anda berjalan, Anda bisa membuat
+thread dalam {@link android.app.Activity#onCreate onCreate()}, mulai menjalankannya di {@link
+android.app.Activity#onStart onStart()}, kemudian menghentikannya di {@link android.app.Activity#onStop
+onStop()}. Pertimbangkan juga untuk menggunakan {@link android.os.AsyncTask} atau {@link android.os.HandlerThread},
+sebagai ganti kelas {@link java.lang.Thread} yang lazim digunakan. Lihat dokumen <a href="{@docRoot}guide/components/processes-and-threads.html#Threads">Proses dan
+Threading</a> untuk informasi selengkapnya tentang thread.</p>
+  <p>Ingatlah jika menggunakan layanan, layanan tersebut tetap berjalan di thread utama aplikasi Anda secara
+default, jadi Anda harus tetap membuat thread baru dalam layanan bila layanan tersebut melakukan operasi yang intensif
+atau operasi yang memblokir.</p>
+</div>
+</div>
+
+<p>Untuk membuat layanan, Anda harus membuat subkelas {@link android.app.Service} (atau
+salah satu dari subkelasnya yang ada). Dalam implementasi, Anda perlu mengesampingkan sebagian metode callback yang
+menangani aspek utama daur hidup layanan dan memberikan mekanisme bagi komponen untuk mengikat
+pada layanan, bila dibutuhkan. Metode callback terpenting yang perlu Anda kesampingkan adalah:</p>
+
+<dl>
+  <dt>{@link android.app.Service#onStartCommand onStartCommand()}</dt>
+    <dd>Sistem akan memanggil metode ini bila komponen lain, misalnya aktivitas,
+meminta dimulainya layanan, dengan memanggil {@link android.content.Context#startService
+startService()}. Setelah metode ini dieksekusi, layanan akan dimulai dan bisa berjalan di
+latar belakang terus-menerus. Jika mengimplementasikan ini, Anda bertanggung jawab menghentikan layanan bila
+bila pekerjaannya selesai, dengan memanggil {@link android.app.Service#stopSelf stopSelf()} atau {@link
+android.content.Context#stopService stopService()}. (Jika hanya ingin menyediakan pengikatan, Anda tidak
+perlu mengimplementasikan metode ini.)</dd>
+  <dt>{@link android.app.Service#onBind onBind()}</dt>
+    <dd>Sistem akan memanggil metode ini bila komponen lain ingin mengikat pada
+layanan (misalnya untuk melakukan RPC), dengan memanggil {@link android.content.Context#bindService
+bindService()}. Dalam mengimplementasikan metode ini, Anda harus menyediakan antarmuka yang digunakan
+klien untuk berkomunikasi dengan layanan, dengan mengembalikan {@link android.os.IBinder}. Anda harus selalu
+mengimplementasikan metode ini, namun jika tidak ingin mengizinkan pengikatan, Anda perlu mengembalikan null.</dd>
+  <dt>{@link android.app.Service#onCreate()}</dt>
+    <dd>Sistem memanggil metode ini bila layanan dibuat untuk pertama kalinya, untuk melakukan prosedur
+penyiapan satu kali (sebelum memanggil {@link android.app.Service#onStartCommand onStartCommand()} atau
+{@link android.app.Service#onBind onBind()}). Bila layanan sudah berjalan, metode ini tidak
+dipanggil.</dd>
+  <dt>{@link android.app.Service#onDestroy()}</dt>
+    <dd>Sistem memanggil metode ini bila layanan tidak lagi digunakan dan sedang dimusnahkan.
+Layanan Anda perlu mengimplementasikannya untuk membersihkan sumber daya seperti thread, listener
+terdaftar, penerima, dll. Ini adalah panggilan terakhir yang diterima layanan.</dd>
+</dl>
+
+<p>Bila komponen memulai layanan dengan memanggil {@link
+android.content.Context#startService startService()} (yang menyebabkan panggilan ke {@link
+android.app.Service#onStartCommand onStartCommand()}), maka layanan
+terus berjalan hingga terhenti sendiri dengan {@link android.app.Service#stopSelf()} atau bila komponen
+lain menghentikannya dengan memanggil {@link android.content.Context#stopService stopService()}.</p>
+
+<p>Bila komponen memanggil
+{@link android.content.Context#bindService bindService()} untuk membuat layanan (dan {@link
+android.app.Service#onStartCommand onStartCommand()} <em>tidak</em> dipanggil), maka layanan hanya berjalan
+selama komponen terikat kepadanya. Setelah layanan dilepas ikatannya dari semua klien,
+sistem akan menghancurkannya.</p>
+
+<p>Sistem Android akan menghentikan paksa layanan hanya bila memori tinggal sedikit dan sistem harus memulihkan
+sumber daya sistem untuk aktivitas yang mendapatkan fokus pengguna. Jika layanan terikat pada suatu aktivitas yang mendapatkan
+fokus pengguna, layanan tersebut lebih kecil kemungkinannya untuk dimatikan, dan jika layanan dideklarasikan untuk <a href="#Foreground">berjalan di latar depan</a> (akan dibahas kemudian), maka sudah hampir pasti ia tidak akan dimatikan.
+Sebaliknya, bila layanan sudah dimulai dan berjalan lama, maka sistem akan menurunkan posisinya
+dalam daftar tugas latar belakang seiring waktu dan layanan akan sangat rentan untuk
+dimatikan&mdash;bila layanan Anda dimulai, maka Anda harus mendesainnya agar bisa menangani restart
+oleh sistem dengan baik. Jika sistem mematikan layanan Anda, layanan akan dimulai kembali begitu sumber daya
+kembali tersedia (tetapi ini juga bergantung pada nilai yang Anda kembalikan dari {@link
+android.app.Service#onStartCommand onStartCommand()}, sebagaimana akan dibahas nanti). Untuk informasi selengkapnya
+tentang kapan sistem mungkin akan memusnahkan layanan, lihat dokumen
+<a href="{@docRoot}guide/components/processes-and-threads.html">Proses dan Threading</a>.</p>
+
+<p>Dalam bagian selanjutnya, Anda akan melihat bagaimana membuat masing-masing tipe layanan dan cara menggunakannya
+dari komponen aplikasi lain.</p>
+
+
+
+<h3 id="Declaring">Mendeklarasikan layanan dalam manifes</h3>
+
+<p>Sebagaimana aktivitas (dan komponen lainnya), Anda harus mendeklarasikan semua layanan dalam file manifes
+aplikasi Anda.</p>
+
+<p>Untuk mendeklarasikan layanan Anda, tambahkan sebuah elemen <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a>
+sebagai anak
+elemen <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a>. Misalnya:</p>
+
+<pre>
+&lt;manifest ... &gt;
+  ...
+  &lt;application ... &gt;
+      &lt;service android:name=".ExampleService" /&gt;
+      ...
+  &lt;/application&gt;
+&lt;/manifest&gt;
+</pre>
+
+<p>Lihat acuan elemen <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a>
+untuk informasi selengkapnya tentang cara mendeklarasikan layanan Anda dalam manifes.</p>
+
+<p>Ada atribut lain yang bisa Anda sertakan dalam elemen <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a> untuk
+mendefinisikan properti seperti izin yang dibutuhkan untuk memulai layanan dan proses
+tempat berjalannya layanan. <a href="{@docRoot}guide/topics/manifest/service-element.html#nm">{@code android:name}</a> adalah satu-satunya atribut yang diperlukan
+&mdash;atribut tersebut menetapkan nama kelas layanan. Setelah
+mempublikasikan aplikasi, Anda tidak boleh mengubah nama ini, karena jika melakukannya, Anda bisa merusak
+kode karena dependensi terhadap intent eksplisit untuk memulai atau mengikat layanan (bacalah posting blog berjudul <a href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things
+That Cannot Change</a>).
+
+<p>Untuk memastikan aplikasi Anda aman, <strong>selalu gunakan intent eksplisit saat memulai atau mengikat
+{@link android.app.Service} Anda</strong> dan jangan mendeklarasikan filter intent untuk layanan. Jika
+Anda perlu membiarkan adanya ambiguitas tentang layanan mana yang dimulai, Anda bisa
+menyediakan filter intent bagi layanan dan tidak memasukkan nama komponen pada {@link
+android.content.Intent}, namun Anda juga harus menyesuaikan paket bagi intent tersebut dengan {@link
+android.content.Intent#setPackage setPackage()}, yang memberikan klarifikasi memadai bagi
+target layanan.</p>
+
+<p>Anda juga bisa memastikan layanan tersedia hanya bagi aplikasi Anda dengan
+menyertakan atribut <a href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code android:exported}</a>
+dan mengaturnya ke {@code "false"}. Hal ini efektif menghentikan aplikasi lain agar tidak memulai
+layanan Anda, bahkan saat menggunakan intent eksplisit.</p>
+
+
+
+
+<h2 id="CreatingStartedService">Membuat Layanan yang Sudah Dimulai</h2>
+
+<p>Layanan yang sudah dimulai adalah layanan yang dimulai komponen lain dengan memanggil {@link
+android.content.Context#startService startService()}, yang menyebabkan panggilan ke metode
+{@link android.app.Service#onStartCommand onStartCommand()} layanan.</p>
+
+<p>Bila layanan sudah dimulai, layanan tersebut memiliki daur hidup yang tidak bergantung pada
+komponen yang memulainya dan bisa berjalan terus-menerus di latar belakang walaupun
+komponen yang memulainya dimusnahkan. Dengan sendirinya, layanan akan berhenti sendiri bila pekerjaannya
+selesai dengan memanggil {@link android.app.Service#stopSelf stopSelf()}, atau komponen lain bisa menghentikannya
+dengan memanggil {@link android.content.Context#stopService stopService()}.</p>
+
+<p>Komponen aplikasi seperti aktivitas bisa memulai layanan dengan memanggil {@link
+android.content.Context#startService startService()} dan meneruskan {@link android.content.Intent}
+yang menetapkan layanan dan menyertakan data untuk digunakan layanan. Layanan menerima
+{@link android.content.Intent} ini dalam metode {@link android.app.Service#onStartCommand
+onStartCommand()}.</p>
+
+<p>Sebagai contoh, anggaplah aktivitas perlu menyimpan data ke database online. Aktivitas tersebut bisa
+memulai layanan pendamping dan mengiriminya data untuk disimpan dengan meneruskan intent ke {@link
+android.content.Context#startService startService()}. Layanan akan menerima intent dalam {@link
+android.app.Service#onStartCommand onStartCommand()}, menghubungkan ke Internet dan melakukan
+transaksi database. Bila transaksi selesai, layanan akan berhenti sendiri dan
+dimusnahkan.</p>
+
+<p class="caution"><strong>Perhatian:</strong> Layanan berjalan dalam proses yang sama dengan aplikasi
+tempatnya dideklarasikan dan dalam thread utama aplikasi tersebut, secara default. Jadi, bila layanan Anda
+melakukan operasi yang intensif atau operasi pemblokiran saat pengguna berinteraksi dengan aktivitas dari
+aplikasi yang sama, layanan akan memperlambat kinerja aktivitas. Agar tidak memengaruhi
+kinerja aplikasi, Anda harus memulai thread baru di dalam layanan.</p>
+
+<p>Biasanya, ada dua kelas yang bisa Anda perluas untuk membuat layanan yang sudah dimulai:</p>
+<dl>
+  <dt>{@link android.app.Service}</dt>
+  <dd>Ini adalah kelas dasar untuk semua layanan. Bila memperluas kelas ini, Anda perlu
+membuat thread baru sebagai tempat melaksanakan semua pekerjaan layanan tersebut, karena layanan
+menggunakan thread utama aplikasi Anda secara default, dan hal ini bisa memperlambat
+kinerja aktivitas yang dijalankan aplikasi Anda.</dd>
+  <dt>{@link android.app.IntentService}</dt>
+  <dd>Ini adalah subkelas {@link android.app.Service} yang menggunakan thread pekerja untuk menangani
+semua permintaan memulai, satu per satu. Ini adalah pilihan terbaik jika Anda tidak mengharuskan layanan
+menangani beberapa permintaan sekaligus. Anda cukup mengimplementasikan {@link
+android.app.IntentService#onHandleIntent onHandleIntent()}, yang menerima intent untuk setiap
+permintaan memulai agar bisa melakukan pekerjaan latar belakang.</dd>
+</dl>
+
+<p>Bagian selanjutnya membahas cara mengimplementasikan layanan Anda menggunakan
+salah satu dari kelas-kelas ini.</p>
+
+
+<h3 id="ExtendingIntentService">Memperluas kelas IntentService</h3>
+
+<p>Mengingat kebanyakan layanan yang sudah dimulai tidak perlu menangani beberapa permintaan
+sekaligus (yang bisa berupa skenario multi-threading berbahaya), mungkin Anda sebaiknya mengimplementasikan
+layanan menggunakan kelas {@link android.app.IntentService}.</p>
+
+<p>Berikut ini yang dilakukan {@link android.app.IntentService}:</p>
+
+<ul>
+  <li>Membuat thread pekerja default yang menjalankan semua intent yang disampaikan ke {@link
+android.app.Service#onStartCommand onStartCommand()} terpisah dari thread utama aplikasi
+Anda.</li>
+  <li>Membuat antrean pekerjaan yang meneruskan intent satu per satu ke implementasi {@link
+android.app.IntentService#onHandleIntent onHandleIntent()}, sehingga Anda tidak perlu
+mengkhawatirkan multi-threading.</li>
+  <li>Menghentikan layanan setelah semua permintaan memulai telah ditangani, jadi Anda tidak perlu memanggil
+{@link android.app.Service#stopSelf}.</li>
+  <li>Menyediakan implementasi default {@link android.app.IntentService#onBind onBind()} yang
+mengembalikan null.</li>
+  <li>Menyediakan implementasi default {@link android.app.IntentService#onStartCommand
+onStartCommand()} yang mengirimkan intent ke antrean pekerjaan kemudian ke implementasi {@link
+android.app.IntentService#onHandleIntent onHandleIntent()} Anda.</li>
+</ul>
+
+<p>Oleh karena itu, Anda hanya perlu mengimplementasikan {@link
+android.app.IntentService#onHandleIntent onHandleIntent()} untuk melakukan pekerjaan yang diberikan oleh
+klien. (Akan tetapi, Anda juga perlu menyediakan konstruktor kecil bagi layanan.)</p>
+
+<p>Berikut ini contoh implementasi {@link android.app.IntentService}:</p>
+
+<pre>
+public class HelloIntentService extends IntentService {
+
+  /**
+   * A constructor is required, and must call the super {@link android.app.IntentService#IntentService}
+   * constructor with a name for the worker thread.
+   */
+  public HelloIntentService() {
+      super("HelloIntentService");
+  }
+
+  /**
+   * The IntentService calls this method from the default worker thread with
+   * the intent that started the service. When this method returns, IntentService
+   * stops the service, as appropriate.
+   */
+  &#64;Override
+  protected void onHandleIntent(Intent intent) {
+      // Normally we would do some work here, like download a file.
+      // For our sample, we just sleep for 5 seconds.
+      long endTime = System.currentTimeMillis() + 5*1000;
+      while (System.currentTimeMillis() &lt; endTime) {
+          synchronized (this) {
+              try {
+                  wait(endTime - System.currentTimeMillis());
+              } catch (Exception e) {
+              }
+          }
+      }
+  }
+}
+</pre>
+
+<p>Anda hanya memerlukan: konstruktor dan implementasi {@link
+android.app.IntentService#onHandleIntent onHandleIntent()}.</p>
+
+<p>Jika Anda memutuskan untuk juga mengesampingkan metode callback lain, seperti {@link
+android.app.IntentService#onCreate onCreate()}, {@link
+android.app.IntentService#onStartCommand onStartCommand()}, atau {@link
+android.app.IntentService#onDestroy onDestroy()}, pastikan memanggil implementasi super, sehingga
+{@link android.app.IntentService} bisa menangani hidup thread pekerja dengan baik.</p>
+
+<p>Misalnya, {@link android.app.IntentService#onStartCommand onStartCommand()} harus mengembalikan
+implementasi default (yang merupakan cara penyampaian intent ke {@link
+android.app.IntentService#onHandleIntent onHandleIntent()}):</p>
+
+<pre>
+&#64;Override
+public int onStartCommand(Intent intent, int flags, int startId) {
+    Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
+    return super.onStartCommand(intent,flags,startId);
+}
+</pre>
+
+<p>Selain {@link android.app.IntentService#onHandleIntent onHandleIntent()}, satu-satunya metode lain
+yang tidak mengharuskan Anda memanggil super kelas adalah {@link android.app.IntentService#onBind
+onBind()} (namun Anda hanya perlu mengimplementasikannya bila layanan mengizinkan pengikatan).</p>
+
+<p>Dalam bagian berikutnya, Anda akan melihat bagaimana layanan serupa diimplementasikan saat
+memperluas kelas {@link android.app.Service} basis, yang membutuhkan kode lebih banyak lagi, namun mungkin
+cocok jika Anda perlu menangani beberapa permintaan memulai sekaligus.</p>
+
+
+<h3 id="ExtendingService">Memperluas kelas Layanan</h3>
+
+<p>Seperti telah Anda lihat di bagian sebelumnya, menggunakan {@link android.app.IntentService} membuat
+implementasi layanan yang sudah dimulai jadi sangat sederhana. Namun, bila Anda mengharuskan layanan untuk
+melakukan multi-threading (sebagai ganti memproses permintaan memulai melalui antrean pekerjaan), maka Anda
+bisa memperluas kelas {@link android.app.Service} untuk menangani masing-masing intent.</p>
+
+<p>Sebagai perbandingan, contoh kode berikut ini adalah implementasi kelas {@link
+android.app.Service} yang melakukan pekerjaan yang persis sama dengan contoh di atas menggunakan {@link
+android.app.IntentService}. Artinya, untuk setiap permintaan memulai, kode tersebut akan menggunakan thread pekerja
+untuk melakukan pekerjaan dan memproses permintaan satu per satu.</p>
+
+<pre>
+public class HelloService extends Service {
+  private Looper mServiceLooper;
+  private ServiceHandler mServiceHandler;
+
+  // Handler that receives messages from the thread
+  private final class ServiceHandler extends Handler {
+      public ServiceHandler(Looper looper) {
+          super(looper);
+      }
+      &#64;Override
+      public void handleMessage(Message msg) {
+          // Normally we would do some work here, like download a file.
+          // For our sample, we just sleep for 5 seconds.
+          long endTime = System.currentTimeMillis() + 5*1000;
+          while (System.currentTimeMillis() &lt; endTime) {
+              synchronized (this) {
+                  try {
+                      wait(endTime - System.currentTimeMillis());
+                  } catch (Exception e) {
+                  }
+              }
+          }
+          // Stop the service using the startId, so that we don't stop
+          // the service in the middle of handling another job
+          stopSelf(msg.arg1);
+      }
+  }
+
+  &#64;Override
+  public void onCreate() {
+    // Start up the thread running the service.  Note that we create a
+    // separate thread because the service normally runs in the process's
+    // main thread, which we don't want to block.  We also make it
+    // background priority so CPU-intensive work will not disrupt our UI.
+    HandlerThread thread = new HandlerThread("ServiceStartArguments",
+            Process.THREAD_PRIORITY_BACKGROUND);
+    thread.start();
+
+    // Get the HandlerThread's Looper and use it for our Handler
+    mServiceLooper = thread.getLooper();
+    mServiceHandler = new ServiceHandler(mServiceLooper);
+  }
+
+  &#64;Override
+  public int onStartCommand(Intent intent, int flags, int startId) {
+      Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
+
+      // For each start request, send a message to start a job and deliver the
+      // start ID so we know which request we're stopping when we finish the job
+      Message msg = mServiceHandler.obtainMessage();
+      msg.arg1 = startId;
+      mServiceHandler.sendMessage(msg);
+
+      // If we get killed, after returning from here, restart
+      return START_STICKY;
+  }
+
+  &#64;Override
+  public IBinder onBind(Intent intent) {
+      // We don't provide binding, so return null
+      return null;
+  }
+
+  &#64;Override
+  public void onDestroy() {
+    Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
+  }
+}
+</pre>
+
+<p>Seperti yang bisa Anda lihat, ini membutuhkan lebih banyak pekerjaan daripada menggunakan {@link android.app.IntentService}.</p>
+
+<p>Akan tetapi, karena Anda menangani sendiri setiap panggilan ke {@link android.app.Service#onStartCommand
+onStartCommand()}, Anda bisa melakukan beberapa permintaan sekaligus. Itu bukan yang
+dilakukan contoh ini, namun jika itu yang diinginkan, Anda bisa membuat thread baru untuk setiap
+permintaan dan langsung menjalankannya (sebagai ganti menunggu permintaan sebelumnya selesai).</p>
+
+<p>Perhatikan bahwa metode {@link android.app.Service#onStartCommand onStartCommand()} harus mengembalikan
+integer. Integer tersebut merupakan nilai yang menjelaskan cara sistem melanjutkan layanan dalam
+kejadian yang dimatikan oleh sistem (sebagaimana dibahas di atas, implementasi default {@link
+android.app.IntentService} menangani hal ini untuk Anda, walaupun Anda bisa memodifikasinya). Nilai yang dikembalikan
+dari {@link android.app.Service#onStartCommand onStartCommand()} harus berupa salah satu
+konstanta berikut ini:</p>
+
+<dl>
+  <dt>{@link android.app.Service#START_NOT_STICKY}</dt>
+    <dd>Jika sistem mematikan layanan setelah {@link android.app.Service#onStartCommand
+onStartCommand()} dikembalikan, <em>jangan</em> membuat lagi layanan tersebut, kecuali jika ada intent
+tertunda yang akan disampaikan. Inilah pilihan teraman untuk menghindari menjalankan layanan Anda
+bila tidak diperlukan dan bila aplikasi Anda bisa me-restart pekerjaan yang belum selesai.</dd>
+  <dt>{@link android.app.Service#START_STICKY}</dt>
+    <dd>Jika sistem mematikan layanan setelah {@link android.app.Service#onStartCommand
+onStartCommand()} dikembalikan, buat kembali layanan dan panggil {@link
+android.app.Service#onStartCommand onStartCommand()}, namun <em>jangan</em> menyampaikan ulang intent terakhir.
+Sebagai gantinya, sistem akan memanggil {@link android.app.Service#onStartCommand onStartCommand()} dengan
+intent null, kecuali jika ada intent tertunda untuk memulai layanan, dan dalam hal ini,
+intent tersebut disampaikan. Ini cocok bagi pemutar media (atau layanan serupa) yang tidak
+mengeksekusi perintah, namun berjalan terus-menerus dan menunggu pekerjaan.</dd>
+  <dt>{@link android.app.Service#START_REDELIVER_INTENT}</dt>
+    <dd>Jika sistem mematikan layanan setelah {@link android.app.Service#onStartCommand
+onStartCommand()} kembali, buat kembali layanan dan panggil {@link
+android.app.Service#onStartCommand onStartCommand()} dengan intent terakhir yang disampaikan ke
+layanan. Intent yang tertunda akan disampaikan pada gilirannya. Ini cocok bagi layanan yang
+aktif melakukan pekerjaan yang harus segera dilanjutkan, misalnya mengunduh file.</dd>
+</dl>
+<p>Untuk detail selengkapnya tentang nilai pengembalian ini, lihat dokumentasi acuan untuk setiap
+konstanta.</p>
+
+
+
+<h3 id="StartingAService">Memulai Layanan</h3>
+
+<p>Anda bisa memulai layanan dari aktivitas atau komponen aplikasi lain dengan meneruskan
+{@link android.content.Intent} (yang menetapkan layanan yang akan dimulai) ke {@link
+android.content.Context#startService startService()}. Sistem Android akan memanggil metode {@link
+android.app.Service#onStartCommand onStartCommand()} layanan dan meneruskan {@link
+android.content.Intent} padanya. (Jangan sekali-kali memanggil {@link android.app.Service#onStartCommand
+onStartCommand()} secara langsung.)</p>
+
+<p>Misalnya, aktivitas bisa memulai contoh layanan di bagian sebelumnya ({@code
+HelloSevice}) menggunakan intent eksplisit dengan {@link android.content.Context#startService
+startService()}:</p>
+
+<pre>
+Intent intent = new Intent(this, HelloService.class);
+startService(intent);
+</pre>
+
+<p>Metode {@link android.content.Context#startService startService()} segera kembali dan
+sistem Android akan memanggil metode {@link android.app.Service#onStartCommand
+onStartCommand()} layanan. Jika layanan belum berjalan, sistem mula-mula memanggil {@link
+android.app.Service#onCreate onCreate()}, kemudian memanggil {@link android.app.Service#onStartCommand
+onStartCommand()}.</p>
+
+<p>Jika layanan juga tidak menyediakan pengikatan, intent yang disampaikan dengan {@link
+android.content.Context#startService startService()} adalah satu-satunya mode komunikasi antara
+komponen aplikasi dan layanan. Akan tetapi, jika Anda ingin agar layanan mengirimkan hasilnya kembali, maka
+klien yang memulai layanan bisa membuat {@link android.app.PendingIntent} untuk siaran
+(dengan {@link android.app.PendingIntent#getBroadcast getBroadcast()}) dan menyampaikannya ke layanan
+dalam {@link android.content.Intent} yang memulai layanan. Layanan kemudian bisa menggunakan
+siaran untuk menyampaikan hasil.</p>
+
+<p>Beberapa permintaan untuk memulai layanan menghasilkan beberapa panggilan pula ke
+{@link android.app.Service#onStartCommand onStartCommand()} layanan. Akan tetapi, hanya satu permintaan untuk menghentikan
+layanan (dengan {@link android.app.Service#stopSelf stopSelf()} atau {@link
+android.content.Context#stopService stopService()}) dibutuhkan untuk menghentikannya.</p>
+
+
+<h3 id="Stopping">Menghentikan layanan</h3>
+
+<p>Layanan yang sudah dimulai harus mengelola daur hidupnya sendiri. Artinya, sistem tidak menghentikan atau
+memusnahkan layanan kecuali jika harus memulihkan memori sistem dan layanan
+terus berjalan setelah {@link android.app.Service#onStartCommand onStartCommand()} kembali. Jadi,
+layanan tersebut harus berhenti sendiri dengan memanggil {@link android.app.Service#stopSelf stopSelf()} atau
+komponen lain bisa menghentikannya dengan memanggil {@link android.content.Context#stopService stopService()}.</p>
+
+<p>Setelah diminta untuk berhenti dengan {@link android.app.Service#stopSelf stopSelf()} atau {@link
+android.content.Context#stopService stopService()}, sistem akan menghapus layanan
+secepatnya.</p>
+
+<p>Akan tetapi, bila layanan Anda menangani beberapa permintaan ke {@link
+android.app.Service#onStartCommand onStartCommand()} sekaligus, Anda tidak boleh menghentikan
+layanan bila Anda baru selesai memproses permintaan memulai, karena setelah itu mungkin Anda sudah menerima permintaan memulai
+yang baru (berhenti pada permintaan pertama akan menghentikan permintaan kedua). Untuk menghindari
+masalah ini, Anda bisa menggunakan {@link android.app.Service#stopSelf(int)} untuk memastikan bahwa permintaan
+Anda untuk menghentikan layanan selalu berdasarkan pada permintaan memulai terbaru. Artinya, bila Anda memanggil {@link
+android.app.Service#stopSelf(int)}, Anda akan meneruskan ID permintaan memulai (<code>startId</code>
+yang disampaikan ke {@link android.app.Service#onStartCommand onStartCommand()}) yang terkait dengan permintaan berhenti
+Anda. Kemudian jika layanan menerima permintaan memulai baru sebelum Anda bisa memanggil {@link
+android.app.Service#stopSelf(int)}, maka ID tidak akan sesuai dan layanan tidak akan berhenti.</p>
+
+<p class="caution"><strong>Perhatian:</strong> Aplikasi Anda perlu menghentikan layanannya
+bila selesai bekerja untuk menghindari pemborosan sumber daya sistem dan tenaga baterai. Jika perlu,
+komponen lain bisa menghentikan layanan secara eksplisit dengan memanggil {@link
+android.content.Context#stopService stopService()}. Bahkan jika Anda mengaktifkan pengikatan bagi layanan,
+Anda harus selalu menghentikan layanan sendiri jika layanan tersebut menerima panggilan ke {@link
+android.app.Service#onStartCommand onStartCommand()}.</p>
+
+<p>Untuk informasi selengkapnya tentang daur hidup layanan, lihat bagian di bawah ini tentang <a href="#Lifecycle">Mengelola Daur Hidup Layanan</a>.</p>
+
+
+
+<h2 id="CreatingBoundService">Membuat Layanan Terikat</h2>
+
+<p>Layanan terikat adalah layanan yang memungkinkan komponen aplikasi untuk mengikatnya dengan memanggil {@link
+android.content.Context#bindService bindService()} guna membuat koneksi yang berlangsung lama
+(dan umumnya tidak mengizinkan komponen untuk <em>memulainya</em> dengan memanggil {@link
+android.content.Context#startService startService()}).</p>
+
+<p>Anda sebaiknya membuat layanan terikat bila ingin berinteraksi dengan layanan dari aktivitas
+dan komponen lain dalam aplikasi Anda atau mengeskpos sebagian fungsionalitas aplikasi Anda ke
+ke aplikasi lain, melalui komunikasi antarproses (IPC).</p>
+
+<p>Untuk membuat layanan terikat, Anda harus mengimplementasikan metode callback {@link
+android.app.Service#onBind onBind()} untuk mengembalikan {@link android.os.IBinder} yang
+mendefinisikan antarmuka bagi komunikasi dengan layanan. Komponen aplikasi lain kemudian bisa memanggil
+{@link android.content.Context#bindService bindService()} untuk mengambil antarmuka dan
+mulai memanggil metode pada layanan. Layanan hanya hidup untuk melayani komponen aplikasi yang
+terikat padanya, jadi bila tidak ada komponen yang terikat pada layanan, sistem akan memusnahkannya
+(Anda <em>tidak</em> perlu menghentikan layanan terikat seperti halnya bila layanan dimulai
+melalui {@link android.app.Service#onStartCommand onStartCommand()}).</p>
+
+<p>Untuk membuat layanan terikat, hal yang perlu dilakukan pertama kali adalah mendefinisikan antarmuka yang menetapkan
+cara klien berkomunikasi dengan layanan. Antarmuka antara layanan
+dan klien ini harus berupa implementasi {@link android.os.IBinder} dan yang harus dikembalikan
+layanan Anda dari metode callback {@link android.app.Service#onBind
+onBind()}. Setelah menerima {@link android.os.IBinder}, klien bisa mulai
+berinteraksi dengan layanan melalui antarmuka tersebut.</p>
+
+<p>Beberapa klien bisa mengikat ke layanan sekaligus. Bila klien selesai berinteraksi dengan
+layanan, klien akan memanggil {@link android.content.Context#unbindService unbindService()} untuk melepas ikatan. Bila
+tidak ada klien yang terikat pada layanan, sistem akan menghapus layanan tersebut.</p>
+
+<p>Ada beberapa cara untuk mengimplementasikan layanan terikat dan implementasinya lebih
+rumit daripada layanan yang sudah dimulai, jadi layanan terikat dibahas dalam dokumen
+terpisah tentang <a href="{@docRoot}guide/components/bound-services.html">Layanan Terikat</a>.</p>
+
+
+
+<h2 id="Notifications">Mengirim Pemberitahuan ke Pengguna</h2>
+
+<p>Setelah berjalan, layanan bisa memberi tahu pengguna tentang suatu kejadian menggunakan <a href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Pemberitahuan Toast</a> atau <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Pemberitahuan Baris Status</a>.</p>
+
+<p>Pemberitahuan Toast adalah pesan yang muncul sebentar pada permukaan jendela saat ini
+kemudian menghilang, sementara pemberitahuan baris status memberikan ikon di baris status dengan
+pesan yang bisa dipilih oleh pengguna untuk melakukan suatu tindakan (misalnya memulai suatu aktivitas).</p>
+
+<p>Biasanya, pemberitahuan baris status adalah teknik terbaik bila ada pekerjaan latar belakang yang sudah selesai
+(misalnya file selesai
+diunduh) dan pengguna kini bisa menggunakannya. Bila pengguna memilih pemberitahuan dari
+tampilan diperluas, pemberitahuan akan bisa memulai aktivitas (misalnya menampilkan file yang baru diunduh).</p>
+
+<p>Lihat panduan pengembang <a href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Pemberitahuan Toast</a> atau <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Pemberitahuan Baris Status</a>
+untuk informasi selengkapnya.</p>
+
+
+
+<h2 id="Foreground">Menjalankan Layanan di Latar Depan</h2>
+
+<p>Layanan latar depan adalah layanan yang dianggap sebagai sesuatu yang
+diketahui secara aktif oleh pengguna, jadi bukan sesuatu yang akan dihapus oleh sistem bila memori menipis. Sebuah
+layanan latar depan harus memberikan pemberitahuan bagi baris status, yang ditempatkan pada
+heading "Ongoing" yang artinya pemberitahuan tersebut tidak bisa diabaikan kecuali jika layanan
+dihentikan atau dihapus dari latar depan.</p>
+
+<p>Misalnya, pemutar musik yang memutar musik dari suatu layanan harus diatur untuk berjalan di
+latar depan, karena pengguna mengetahui operasi tersebut
+secara eksplisit. Pemberitahuan di baris status bisa menunjukkan lagu saat ini dan memungkinkan
+pengguna untuk menjalankan suatu aktivitas untuk berinteraksi dengan pemutar musik.</p>
+
+<p>Untuk meminta agar layanan Anda berjalan di latar depan, panggil {@link
+android.app.Service#startForeground startForeground()}. Metode ini memerlukan dua parameter: sebuah integer
+yang mengidentifikasi pemberitahuan secara unik dan {@link
+android.app.Notification} untuk baris status. Misalnya:</p>
+
+<pre>
+Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
+        System.currentTimeMillis());
+Intent notificationIntent = new Intent(this, ExampleActivity.class);
+PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
+notification.setLatestEventInfo(this, getText(R.string.notification_title),
+        getText(R.string.notification_message), pendingIntent);
+startForeground(ONGOING_NOTIFICATION_ID, notification);
+</pre>
+
+<p class="caution"><strong>Perhatian:</strong> ID integer yang Anda berikan ke {@link
+android.app.Service#startForeground startForeground()} tidak boleh 0.</p>
+
+
+<p>Untuk menghapus layanan dari latar depan, panggil {@link
+android.app.Service#stopForeground stopForeground()}. Metode ini memerlukan boolean, yang menunjukkan
+apakah pemberitahuan baris status juga akan dihapus. Metode ini <em>tidak</em> menghentikan
+layanan. Akan tetapi, jika Anda menghentikan layanan saat masih berjalan di latar depan
+maka pemberitahuan juga akan dihapus.</p>
+
+<p>Untuk informasi selengkapnya tentang pemberitahuan, lihat <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Membuat Pemberitahuan
+Baris Status</a>.</p>
+
+
+
+<h2 id="Lifecycle">Mengelola Daur Hidup Layanan</h2>
+
+<p>Daur hidup layanan jauh lebih sederhana daripada daur hidup aktivitas. Akan tetapi, lebih penting lagi adalah
+memerhatikan dengan cermat bagaimana layanan Anda dibuat dan dimusnahkan, karena suatu layanan
+bisa berjalan di latar belakang tanpa disadari oleh pengguna.</p>
+
+<p>Daur hidup layanan&mdash;dari saat dibuat hingga dimusnahkan&mdash;bisa mengikuti
+dua path berbeda:</p>
+
+<ul>
+<li>Layanan yang sudah dimulai
+  <p>Layanan dibuat bila komponen lain memanggil {@link
+android.content.Context#startService startService()}. Layanan kemudian berjalan terus-menerus dan harus
+berhenti sendiri dengan memanggil {@link
+android.app.Service#stopSelf() stopSelf()}. Komponen lain juga bisa menghentikan
+layanan dengan memanggil {@link android.content.Context#stopService
+stopService()}. Bila layanan dihentikan, sistem akan menghancurkannya.</p></li>
+
+<li>Layanan terikat
+  <p>Layanan dibuat bila komponen lain (klien) memanggil {@link
+android.content.Context#bindService bindService()}. Klien kemudian berkomunikasi dengan layanan
+melalui antarmuka {@link android.os.IBinder}. Klien bisa menutup koneksi dengan memanggil
+{@link android.content.Context#unbindService unbindService()}. Sejumlah klien bisa mengikat pada
+layanan yang sama dan bila semuanya melepas ikatan, sistem akan memusnahkan layanan tersebut. (Layanan
+<em>tidak</em> perlu berhenti sendiri.)</p></li>
+</ul>
+
+<p>Kedua path tersebut tidak benar-benar terpisah. Artinya, Anda bisa mengikat ke layanan yang sudah
+dimulai dengan {@link android.content.Context#startService startService()}. Misalnya, layanan
+musik latar belakang bisa dimulai dengan memanggil {@link android.content.Context#startService
+startService()} dengan {@link android.content.Intent} yang mengidentifikasi musik yang akan diputar. Kemudian,
+mungkin saat pengguna ingin mengontrol pemutar musik atau mendapatkan informasi
+tentang lagu yang diputar, aktivitas bisa mengikat ke layanan dengan memanggil {@link
+android.content.Context#bindService bindService()}. Dalam kasus seperti ini, {@link
+android.content.Context#stopService stopService()} atau {@link android.app.Service#stopSelf
+stopSelf()} tidak menghentikan layanan sampai semua klien melepas ikatan. </p>
+
+
+<h3 id="LifecycleCallbacks">Mengimplementasikan callback daur hidup</h3>
+
+<p>Seperti halnya aktivitas, layanan memiliki metode callback daur hidup yang bisa Anda implementasikan
+untuk memantau perubahan status layanan dan melakukan pekerjaan pada waktu yang tepat. Layanan skeleton
+berikut memperagakan setiap metode daur hidup:</p>
+
+<pre>
+public class ExampleService extends Service {
+    int mStartMode;       // indicates how to behave if the service is killed
+    IBinder mBinder;      // interface for clients that bind
+    boolean mAllowRebind; // indicates whether onRebind should be used
+
+    &#64;Override
+    public void {@link android.app.Service#onCreate onCreate}() {
+        // The service is being created
+    }
+    &#64;Override
+    public int {@link android.app.Service#onStartCommand onStartCommand}(Intent intent, int flags, int startId) {
+        // The service is starting, due to a call to {@link android.content.Context#startService startService()}
+        return <em>mStartMode</em>;
+    }
+    &#64;Override
+    public IBinder {@link android.app.Service#onBind onBind}(Intent intent) {
+        // A client is binding to the service with {@link android.content.Context#bindService bindService()}
+        return <em>mBinder</em>;
+    }
+    &#64;Override
+    public boolean {@link android.app.Service#onUnbind onUnbind}(Intent intent) {
+        // All clients have unbound with {@link android.content.Context#unbindService unbindService()}
+        return <em>mAllowRebind</em>;
+    }
+    &#64;Override
+    public void {@link android.app.Service#onRebind onRebind}(Intent intent) {
+        // A client is binding to the service with {@link android.content.Context#bindService bindService()},
+        // after onUnbind() has already been called
+    }
+    &#64;Override
+    public void {@link android.app.Service#onDestroy onDestroy}() {
+        // The service is no longer used and is being destroyed
+    }
+}
+</pre>
+
+<p class="note"><strong>Catatan:</strong> Tidak seperti metode callback daur hidup aktivitas, Anda
+<em>tidak</em> perlu memanggil implementasi superkelas metode callback tersebut.</p>
+
+<img src="{@docRoot}images/service_lifecycle.png" alt="" />
+<p class="img-caption"><strong>Gambar 2.</strong> Daur hidup layanan. Diagram di sebelah kiri
+menampilkan daur hidup bila layanan dibuat dengan {@link android.content.Context#startService
+startService()} dan diagram di sebelah kanan menampilkan daur hidup bila layanan dibuat
+dengan {@link android.content.Context#bindService bindService()}.</p>
+
+<p>Dengan mengimplementasikan metode-metode ini, Anda bisa memantau dua loop tersarang (nested loop) daur hidup layanan: </p>
+
+<ul>
+<li><strong>Seluruh masa pakai</strong> layanan terjadi antara saat {@link
+android.app.Service#onCreate onCreate()} dipanggil dan saat {@link
+android.app.Service#onDestroy} kembali. Seperti halnya aktivitas, layanan melakukan penyiapan awal di
+{@link android.app.Service#onCreate onCreate()} dan melepaskan semua sisa sumber daya yang ada di {@link
+android.app.Service#onDestroy onDestroy()}.  Misalnya,
+layanan pemutar musik bisa membuat thread tempat musik akan diputar dalam {@link
+android.app.Service#onCreate onCreate()}, kemudian menghentikan thread tersebut dalam {@link
+android.app.Service#onDestroy onDestroy()}.
+
+<p>Metode {@link android.app.Service#onCreate onCreate()} dan {@link android.app.Service#onDestroy
+onDestroy()} diperlukan semua layanan, baik yang
+dibuat oleh {@link android.content.Context#startService startService()} maupun {@link
+android.content.Context#bindService bindService()}.</p></li>
+
+<li><strong>Masa pakai aktif</strong> layanan dimulai dengan panggilan ke {@link
+android.app.Service#onStartCommand onStartCommand()} atau {@link android.app.Service#onBind onBind()}.
+Masing-masing metode diberikan {@link
+android.content.Intent} yang diteruskan ke {@link android.content.Context#startService
+startService()} atau {@link android.content.Context#bindService bindService()}.
+<p>Jika layanan telah dimulai, masa pakai aktif akan berakhir pada saat yang sama dengan
+berakhirnya seluruh masa pakai (layanan masih aktif bahkan setelah {@link android.app.Service#onStartCommand
+onStartCommand()} kembali). Jika layanan tersebut terikat, masa pakai aktifnya akan berakhir bila {@link
+android.app.Service#onUnbind onUnbind()} kembali.</p>
+</li>
+</ul>
+
+<p class="note"><strong>Catatan:</strong> Meskipun layanan yang sudah dimulai dihentikan dengan panggilan ke
+{@link android.app.Service#stopSelf stopSelf()} atau {@link
+android.content.Context#stopService stopService()}, tidak ada callback tersendiri bagi
+layanan tersebut (tidak ada callback {@code onStop()}). Jadi, kecuali jika layanan terikat ke klien,
+sistem akan memusnahkannya bila layanan dihentikan&mdash;{@link
+android.app.Service#onDestroy onDestroy()} adalah satu-satunya callback yang diterima.</p>
+
+<p>Gambar 2 mengilustrasikan metode callback yang lazim bagi suatu layanan. Walaupun gambar tersebut memisahkan
+layanan yang dibuat oleh {@link android.content.Context#startService startService()} dari layanan
+yang dibuat oleh {@link android.content.Context#bindService bindService()}, ingatlah
+bahwa suatu layanan, bagaimana pun dimulainya, bisa memungkinkan klien mengikat padanya.
+Jadi, suatu layanan yang awalnya dimulai dengan {@link android.app.Service#onStartCommand
+onStartCommand()} (oleh klien yang memanggil {@link android.content.Context#startService startService()})
+masih bisa menerima panggilan ke {@link android.app.Service#onBind onBind()} (bila klien memanggil
+{@link android.content.Context#bindService bindService()}).</p>
+
+<p>Untuk informasi selengkapnya tentang membuat layanan yang menyediakan pengikatan, lihat dokumen <a href="{@docRoot}guide/components/bound-services.html">Layanan Terikat</a>,
+yang menyertakan informasi selengkapnya tentang metode callback {@link android.app.Service#onRebind onRebind()}
+di bagian tentang <a href="{@docRoot}guide/components/bound-services.html#Lifecycle">Mengelola Daur Hidup
+Layanan Terikat</a>.</p>
+
+
+<!--
+<h2>Beginner's Path</h2>
+
+<p>To learn how to query data from the system or other applications (such as contacts or media
+stored on the device), continue with the <b><a
+href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a></b>
+document.</p>
+-->
diff --git a/docs/html-intl/intl/id/guide/components/tasks-and-back-stack.jd b/docs/html-intl/intl/id/guide/components/tasks-and-back-stack.jd
new file mode 100644
index 0000000..4c344ae
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/components/tasks-and-back-stack.jd
@@ -0,0 +1,578 @@
+page.title=Tugas dan Back-Stack
+parent.title=Aktivitas
+parent.link=activities.html
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>Dalam dokumen ini</h2>
+<ol>
+<li><a href="#ActivityState">Menyimpan Status Aktivitas</a></li></li>
+<li><a href="#ManagingTasks">Mengelola Tugas</a>
+  <ol>
+    <li><a href="#TaskLaunchModes">Mendefinisikan mode peluncuran</a></li>
+    <li><a href="#Affinities">Menangani afinitas</a></li>
+    <li><a href="#Clearing">Menghapus back-stack</a></li>
+    <li><a href="#Starting">Memulai tugas</a></li>
+  </ol>
+</li>
+</ol>
+
+<h2>Artikel</h2>
+<ol>
+  <li><a href="http://android-developers.blogspot.com/2010/04/multitasking-android-way.html">
+  Multitasking Ala Android</a></li>
+</ol>
+
+<h2>Lihat juga</h2>
+<ol>
+  <li><a href="{@docRoot}design/patterns/navigation.html">Desain Android:
+Navigasi</a></li>
+  <li><a href="{@docRoot}guide/topics/manifest/activity-element.html">Elemen manifes
+{@code &lt;activity&gt;}</a></li>
+  <li><a href="{@docRoot}guide/components/recents.html">Layar Ikhtisar</a></li>
+</ol>
+</div>
+</div>
+
+
+<p>Sebuah aplikasi biasanya berisi beberapa <a href="{@docRoot}guide/components/activities.html">aktivitas</a>. Setiap aktivitas
+harus didesain dengan jenis tindakan tertentu yang bisa dilakukan pengguna dan bisa memulai aktivitas
+lain. Misalnya, aplikasi email mungkin memiliki satu aktivitas untuk menampilkan daftar pesan baru.
+Bila pengguna memilih sebuah pesan, aktivitas baru akan terbuka untuk melihat pesan tersebut.</p>
+
+<p>Aktivitas bahkan bisa memulai aktivitas yang ada dalam aplikasi lain di perangkat. Misalnya
+, jika aplikasi Anda ingin mengirim pesan email, Anda bisa mendefinisikan intent untuk melakukan tindakan
+"kirim" dan menyertakan sejumlah data, seperti alamat email dan pesan. Aktivitas dari aplikasi
+lain yang mendeklarasikan dirinya untuk menangani jenis intent ini akan terbuka. Dalam hal ini, intent
+tersebut untuk mengirim email, sehingga aktivitas "menulis" pada aplikasi email akan dimulai (jika beberapa aktivitas
+mendukung intent yang sama, maka sistem akan memungkinkan pengguna memilih mana yang akan digunakan). Bila email telah
+dikirim, aktivitas Anda akan dilanjutkan dan seolah-olah aktivitas email adalah bagian dari aplikasi Anda. Meskipun
+aktivitas mungkin dari aplikasi yang berbeda, Android akan tetap mempertahankan pengalaman pengguna yang mulus
+dengan menjalankan kedua aktivitas dalam <em>tugas</em> yang sama.</p>
+
+<p>Tugas adalah kumpulan aktivitas yang berinteraksi dengan pengguna
+saat melakukan pekerjaan tertentu. Aktivitas tersebut diatur dalam tumpukan (<em>back-stack</em>), dalam
+urutan membuka setiap aktivitas.</p>
+
+<!-- SAVE FOR WHEN THE FRAGMENT DOC IS ADDED
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<h3>Adding fragments to a task's back stack</h3>
+
+<p>Your activity can also include {@link android.app.Fragment}s to the back stack. For example,
+suppose you have a two-pane layout using fragments, one of which is a list view (fragment A) and the
+other being a layout to display an item from the list (fragment B). When the user selects an item
+from the list, fragment B is replaced by a new fragment (fragment C). In this case, it might be
+desireable for the user to navigate back to reveal fragment B, using the <em>Back</em> button.</p>
+<p>In order to add fragment B to the back stack so that this is possible, you must call {@link
+android.app.FragmentTransaction#addToBackStack addToBackStack()} before you {@link
+android.app.FragmentTransaction#commit()} the transaction that replaces fragment B with fragment
+C.</p>
+<p>For more information about using fragments and adding them to the back stack, see the {@link
+android.app.Fragment} class documentation.</p>
+
+</div>
+</div>
+-->
+
+<p>Layar Home perangkat adalah tempat memulai hampir semua tugas. Bila pengguna menyentuh ikon di launcher
+aplikasi
+(atau pintasan pada layar Home), tugas aplikasi tersebut akan muncul pada latar depan. Jika tidak ada
+tugas untuk aplikasi (aplikasi tidak digunakan baru-baru ini), maka tugas baru
+akan dibuat dan aktivitas "utama" untuk aplikasi tersebut akan terbuka sebagai aktivitas akar dalam back-stack.</p>
+
+<p>Bila aktivitas saat ini dimulai lagi, aktivitas baru akan didorong ke atas back-stack dan
+mengambil fokus. Aktivitas sebelumnya tetap dalam back-stack, namun dihentikan. Bila aktivitas
+dihentikan, sistem akan mempertahankan status antarmuka penggunanya saat ini. Bila pengguna menekan tombol
+<em>Back</em>
+, aktivitas saat ini akan dikeluarkan dari atas back-stack (aktivitas dimusnahkan) dan
+ aktivitas sebelumnya dilanjutkan (status UI sebelumnya dipulihkan). Aktivitas dalam back-stack
+tidak pernah disusun ulang, hanya didorong dan dikeluarkan dari back-stack&mdash;yang didorong ke back-stack saat dimulai oleh
+aktivitas saat ini dan dikeluarkan bila pengguna meninggalkannya menggunakan tombol <em>Back</em>. Dengan demikian,
+back-stack
+beroperasi sebagai struktur objek "masuk terakhir, keluar pertama". Gambar 1 melukiskan perilaku
+ini dengan jangka waktu yang menunjukkan kemajuan antar aktivitas beserta
+back-stack pada setiap waktu.</p>
+
+<img src="{@docRoot}images/fundamentals/diagram_backstack.png" alt="" />
+<p class="img-caption"><strong>Gambar 1.</strong> Representasi tentang cara setiap aktivitas baru dalam
+tugas menambahkan item ke back-stack. Bila pengguna menekan tombol <em>Back</em>, aktivitas
+saat ini
+akan dimusnahkan dan aktivitas sebelumnya dilanjutkan.</p>
+
+
+<p>Jika pengguna terus menekan <em>Back</em>, maka setiap aktivitas dalam back-stack akan dikeluarkan untuk
+menampilkan
+yang sebelumnya, sampai pengguna kembali ke layar Home (atau aktivitas mana pun yang sedang dijalankan saat tugas
+dimulai. Bila semua aktivitas telah dihapus dari back-stack, maka tugas tidak akan ada lagi.</p>
+
+<div class="figure" style="width:287px">
+<img src="{@docRoot}images/fundamentals/diagram_multitasking.png" alt="" /> <p
+class="img-caption"><strong>Gambar 2.</strong> Dua tugas: Tugas B menerima interaksi pengguna
+di latar depan, sedangkan Tugas A di latar belakang, menunggu untuk dilanjutkan.</p>
+</div>
+<div class="figure" style="width:215px">
+  <img src="{@docRoot}images/fundamentals/diagram_multiple_instances.png" alt="" /> <p
+class="img-caption"><strong>Gambar 3.</strong> Satu aktivitas dibuat instance-nya beberapa kali.</p>
+</div>
+
+<p>Tugas adalah unit kohesif yang bisa dipindahkan ke "latar belakang" bila pengguna memulai tugas baru atau masuk ke
+layar Home, melalui tombol<em>Home</em>. Sementara di latar belakang, semua aktivitas dalam
+tugas
+dihentikan, namun back-stack untuk tugas tidak berubah&mdash;tugas kehilangan fokus saat
+tugas lain berlangsung, seperti yang ditampilkan dalam gambar 2. Kemudian, tugas bisa kembali ke "latar depan" agar pengguna
+bisa melanjutkan tugas di tempat menghentikannya. Anggaplah, misalnya, tugas saat ini (Tugas A) memiliki tiga
+aktivitas dalam back-stack&mdash;dua pada aktivitas saat ini. Pengguna menekan tombol <em>Home</em>
+, kemudian
+memulai aplikasi baru dari launcher aplikasi. Bila muncul layar Home, Tugas A akan beralih
+ke latar belakang. Bila aplikasi baru dimulai, sistem akan memulai tugas untuk aplikasi tersebut
+(Tugas B) dengan back-stack aktivitas sendiri. Setelah berinteraksi dengan aplikasi
+tersebut, pengguna akan kembali ke Home lagi dan memilih aplikasi yang semula
+memulai Tugas A. Sekarang, Tugas A muncul di
+latar depan&mdash;ketiga aktivitas dalam back-stack tidak berubah dan aktivitas di atas
+back-stack akan dilanjutkan. Pada
+titik ini pengguna juga bisa beralih kembali ke Tugas B dengan masuk ke Home dan memilih ikon aplikasi
+yang memulai tugas tersebut (atau dengan memilih tugas aplikasi dari
+<a href="{@docRoot}guide/components/recents.html">layar ikhtisar</a>).
+Ini adalah contoh dari melakukan multitasking di Android.</p>
+
+<p class="note"><strong>Catatan:</strong> Beberapa tugas bisa berlangsung di latar belakang secara bersamaan.
+Akan tetapi, jika pengguna menjalankan banyak tugas di latar belakang sekaligus, sistem mungkin mulai
+menghapus aktivitas latar belakang untuk memulihkan memori, yang akan menyebabkan status aktivitas hilang.
+Lihat bagian berikut tentang <a href="#ActivityState">Status aktivitas</a>.</p>
+
+<p>Karena aktivitas di back-stack tidak pernah diatur ulang, jika aplikasi Anda memungkinkan
+pengguna untuk memulai aktivitas tertentu dari lebih dari satu aktivitas, instance baru
+aktivitas tersebut akan dibuat dan didorong ke back-stack (bukannya memunculkan instance sebelumnya dari
+aktivitas ke atas). Dengan demikian, satu aktivitas pada aplikasi Anda mungkin dibuat beberapa
+kali (bahkan dari beberapa tugas), seperti yang ditampilkan dalam gambar 3. Dengan demikian, jika pengguna mengarahkan mundur
+menggunakan tombol <em>Back</em>, setiap instance aktivitas ini akan ditampilkan dalam urutan saat
+dibuka (masing-masing
+dengan status UI sendiri). Akan tetapi, Anda bisa memodifikasi perilaku ini jika tidak ingin aktivitas
+dibuat instance-nya lebih dari sekali. Caranya dibahas di bagian selanjutnya tentang <a href="#ManagingTasks">Mengelola Tugas</a>.</p>
+
+
+<p>Untuk meringkas perilaku default aktivitas dan tugas:</p>
+
+<ul>
+  <li>Bila Aktivitas A memulai Aktivitas B, Aktivitas A dihentikan, namun sistem mempertahankan statusnya
+(seperti posisi gulir dan teks yang dimasukkan ke dalam formulir).
+Jika pengguna menekan tombol <em>Back</em> saat dalam Aktivitas B, Aktivitas A akan dilanjutkan dengan status
+yang dipulihkan.</li>
+  <li>Bila pengguna meninggalkan tugas dengan menekan tombol <em>Home</em> aktivitas saat ini akan
+dihentikan dan
+tugas beralih ke latar belakang. Sistem akan mempertahankan status setiap aktivitas dalam tugas. Jika
+nanti pengguna melanjutkan tugas dengan memilih ikon launcher yang memulai tugas, tugas tersebut akan
+beralih ke latar depan dan melanjutkan aktivitas di atas back-stack.</li>
+  <li>Jika pengguna menekan tombol <em>Back</em>, aktivitas saat ini akan dikeluarkan dari back-stack
+dan
+dimusnahkan. Aktivitas sebelumnya dalam back-stack akan dilanjutkan. Bila suatu aktivitas dimusnahkan, sistem
+<em>tidak akan</em>mempertahankan status aktivitas.</li>
+  <li>Aktivitas bisa dibuat instance-nya beberapa kali, bahkan dari tugas-tugas lainnya.</li>
+</ul>
+
+
+<div class="note design">
+<p><strong>Desain Navigasi</strong></p>
+  <p>Untuk mengetahui selengkapnya tentang cara kerja navigasi aplikasi di Android, baca panduan <a href="{@docRoot}design/patterns/navigation.html">Navigasi</a> Desain Android.</p>
+</div>
+
+
+<h2 id="ActivityState">Menyimpan Status Aktivitas</h2>
+
+<p>Seperti dibahas di atas, perilaku default sistem akan mempertahankan status aktivitas bila
+dihentikan. Dengan cara ini, bila pengguna mengarah kembali ke aktivitas sebelumnya, antarmuka pengguna akan muncul
+seperti saat ditinggalkan. Akan tetapi, Anda bisa&mdash;dan <strong>harus</strong>&mdash;secara proaktif mempertahankan
+status aktivitas menggunakan metode callback, jika aktivitas ini dimusnahkan dan harus
+dibuat kembali.</p>
+
+<p>Bila sistem menghentikan salah satu aktivitas (seperti saat aktivitas baru dimulai atau tugas
+dipindah ke latar belakang), sistem mungkin memusnahkan aktivitas sepenuhnya jika perlu memulihkan
+memori sistem. Bila hal ini terjadi, informasi tentang status aktivitas akan hilang. Jika hal ini terjadi, sistem
+masih
+mengetahui bahwa aktivitas memiliki tempat di back-stack, namun saat aktivitas tersebut dibawa ke bagian teratas
+back-stack, sistem harus membuatnya kembali (bukan melanjutkannya). Untuk
+menghindari hilangnya pekerjaan pengguna, Anda harus secara proaktif mempertahankannya dengan menerapkan metode callback
+{@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}
+dalam aktivitas.</p>
+
+<p>Untuk informasi selengkapnya tentang cara menyimpan status aktivitas Anda, lihat dokumen
+<a href="{@docRoot}guide/components/activities.html#SavingActivityState">Aktivitas</a>.</p>
+
+
+
+<h2 id="ManagingTasks">Mengelola Tugas</h2>
+
+<p>Cara Android mengelola tugas dan back-stack, seperti yang dijelaskan di atas&mdash;dengan menempatkan semua
+aktivitas yang dimulai secara berurutan dalam tugas yang sama dan dalam back-stack "masuk terakhir, keluar pertama"&mdash;berfungsi
+dengan baik untuk kebanyakan aplikasi dan Anda tidak perlu khawatir tentang cara mengaitkan aktivitas
+dengan tugas atau cara penempatannya di back-stack. Akan tetapi, Anda bisa memutuskan apakah ingin menyela
+perilaku normal. Mungkin Anda ingin agar suatu aktivitas dalam aplikasi untuk memulai tugas baru bila telah
+dimulai (sebagai ganti menempatkannya dalam tugas saat ini); atau, bila memulai aktivitas, Anda ingin
+memajukan instance yang ada (sebagai ganti membuat instance
+baru pada bagian teratas back-stack); atau, Anda ingin back-stack dihapus dari semua
+aktivitas selain untuk aktivitas akar bila pengguna meninggalkan tugas.</p>
+
+<p>Anda bisa melakukan semua ini dan lainnya, dengan atribut dalam elemen manifes
+<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
+dan dengan flag pada intent yang Anda teruskan ke
+{@link android.app.Activity#startActivity startActivity()}.</p>
+
+<p>Dalam hal ini, atribut<a href="{@docRoot}guide/topics/manifest/activity-element.html">
+{@code &lt;activity&gt;}</a> utama yang bisa Anda gunakan adalah:</p>
+
+<ul class="nolist">
+  <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">
+  {@code taskAffinity}</a></li>
+  <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">
+  {@code launchMode}</a></li>
+  <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">
+  {@code allowTaskReparenting}</a></li>
+  <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#clear">
+  {@code clearTaskOnLaunch}</a></li>
+  <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#always">
+  {@code alwaysRetainTaskState}</a></li>
+  <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#finish">
+  {@code finishOnTaskLaunch}</a></li>
+</ul>
+
+<p>Dan flag intent utama yang bisa Anda gunakan adalah:</p>
+
+<ul class="nolist">
+  <li>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</li>
+  <li>{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}</li>
+  <li>{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}</li>
+</ul>
+
+<p>Dalam bagian berikut, Anda akan melihat cara menggunakan beberapa atribut manifes ini dan flag
+intent untuk mendefinisikan cara mengaitkan aktivitas dengan tugas dan cara perilakunya di back-stack.</p>
+
+<p>Juga, pertimbangan cara menyatakan dan mengelola tugas dan aktivitas
+dibahas secara terpisah di layar ikhtisar. Lihat <a href="{@docRoot}guide/components/recents.html">Layar Ikhtisar</a>
+untuk informasi selengkapnya. Biasanya Anda harus mengizinkan sistem mendefinisikan cara menyatakan tugas dan
+aktivitas di layar ikhtisar, dan Anda tidak perlu memodifikasi perilaku ini.</p>
+
+<p class="caution"><strong>Perhatian:</strong> Kebanyakan aplikasi tidak harus menyela perilaku
+default untuk aktivitas dan tugas. Jika merasa bahwa aktivitas Anda perlu memodifikasi
+perilaku default, lakukan dengan hati-hati dan pastikan menguji kegunaan aktivitas selama
+dijalankan dan saat mengarahkan kembali ke sana dari aktivitas dan tugas lain dengan tombol <em>Back</em>.
+Pastikan menguji perilaku navigasi yang mungkin bertentangan dengan perilaku yang diharapkan pengguna.</p>
+
+
+<h3 id="TaskLaunchModes">Mendefinisikan mode peluncuran</h3>
+
+<p>Mode peluncuran memungkinkan Anda mendefinisikan cara mengaitkan instance baru dari suatu aktivitas dengan
+tugas saat ini. Anda bisa mendefinisikan beragam mode peluncuran dalam dua cara:</p>
+<ul class="nolist">
+  <li><a href="#ManifestForTasks">Menggunakan file manifes</a>
+    <p>Bila Anda mendeklarasikan aktivitas dalam file manifes, Anda bisa menetapkan cara mengaitkan aktivitas
+dengan tugas-tugas saat mulai.</li>
+  <li><a href="#IntentFlagsForTasks">Menggunakan flag intent</a>
+    <p>Saat memanggil{@link android.app.Activity#startActivity startActivity()},
+Anda bisa menyertakan flag dalam {@link android.content.Intent} yang menyatakan cara (atau
+apakah) aktivitas baru tersebut harus dikaitkan dengan tugas saat ini.</p></li>
+</ul>
+
+<p>Dengan demikian, jika Aktivitas A memulai Aktivitas B, Aktivitas B bisa mendefinisikan dalam manifesnya cara
+mengaitkan dengan tugas saat ini (jika sama sekali) dan Aktivitas A juga bisa meminta cara mengaitkan Aktivitas B
+dengan tugas saat ini. Jika kedua aktivitas mendefinisikan cara mengaitkan Aktivitas B
+dengan tugas, maka permintaan Aktivitas A (sebagaimana didefinisikan dalam intent) lebih dihargai daripada
+permintaan Aktivitas B (sebagaimana didefinisikan dalam manifesnya).</p>
+
+<p class="note"><strong>Catatan:</strong> Beberapa mode peluncuran yang tersedia untuk file manifes
+tidak tersedia sebagai flag untuk intent dan, juga, beberapa mode peluncuran yang tersedia sebagai flag
+untuk intent tidak bisa didefinisikan dalam manifest.</p>
+
+
+<h4 id="ManifestForTasks">Menggunakan file manifes</h4>
+
+<p>Saat mendeklarasikan aktivitas dalam file manifes, Anda bisa menetapkan cara mengaitkan aktivitas
+dengan tugas menggunakan <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
+melalui atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code
+launchMode}</a> elemen.</p>
+
+<p>Atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code
+launchMode}</a> menetapkan instruksi tentang cara meluncurkan aktivitas
+ke dalam tugas. Ada empat macam mode peluncuran yang bisa Anda tetapkan ke atribut
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">launchMode</a></code>
+:</p>
+
+<dl>
+<dt>{@code "standard"} (mode default)</dt>
+  <dd>Default. Sistem membuat instance baru aktivitas dalam tugas yang
+akan menjadi tempat memulainya dan mengarahkan intent ke sana. Aktivitas ini bisa dibuat instance-nya beberapa kali,
+masing-masing instance bisa dimiliki oleh tugas berbeda, dan satu tugas bisa memiliki beberapa instance.</dd>
+<dt>{@code "singleTop"}</dt>
+  <dd>Jika instance aktivitas sudah ada di bagian teratas tugas saat ini, sistem
+akan mengarahkan intent ke instance tersebut melalui panggilan ke metode {@link
+android.app.Activity#onNewIntent onNewIntent()}, bukan membuat instance baru dari
+aktivitas tersebut. Aktivitas bisa dibuat instance-nya beberapa kali, masing-masing instance bisa dimiliki
+oleh tugas berbeda, dan satu tugas bisa memiliki beberapa instance (namun hanya jika
+aktivitas di bagian teratas back-stack <em>bukan</em> instance yang ada dari aktivitas tersebut).
+  <p>Misalnya, anggaplah back-stack tugas terdiri dari aktivitas A akar dengan aktivitas B, C,
+dan D di bagian teratas (back-stack adalah A-B-C-D; D yang teratas). Intent masuk untuk aktivitas tipe D.
+Jika D memiliki mode peluncuran {@code "standard"} default, instance baru dari kelas ini akan diluncurkan dan
+back-stack menjadi A-B-C-D-D. Namun, jika mode peluncuran D adalah {@code "singleTop"}, instance
+yang ada dari D akan menerima intent melalui {@link
+android.app.Activity#onNewIntent onNewIntent()}, karena ada di bagian teratas back-stack&mdash;
+back-stack tetap A-B-C-D. Akan tetapi, jika intent masuk untuk aktivitas tipe B, maka
+instance B baru akan ditambahkan ke back-stack, sekalipun mode peluncuran adalah{@code "singleTop"}.</p>
+  <p class="note"><strong>Catatan:</strong> Bila instance dari aktivitas baru telah dibuat,
+pengguna bisa menekan tombol <em>Back</em> untuk kembali ke aktivitas sebelumnya. Namun bila instance
+yang ada dari
+aktivitas menangani intent baru, pengguna tidak bisa menekan tombol <em>Back</em> untuk kembali ke
+status
+aktivitas sebelum intent baru masuk di {@link android.app.Activity#onNewIntent
+onNewIntent()}.</p>
+</dd>
+
+<dt>{@code "singleTask"}</dt>
+  <dd>Sistem membuat tugas baru dan membuat instance aktivitas di akar tugas baru.
+Akan tetapi, jika instance aktivitas sudah ada dalam tugas terpisah, sistem akan mengarahkan
+intent ke instance yang ada melalui panggilan ke metode {@link
+android.app.Activity#onNewIntent onNewIntent()}, bukan membuat instance baru. Hanya
+boleh ada satu instance aktivitas untuk setiap kalinya.
+  <p class="note"><strong>Catatan:</strong> Meskipun aktivitas dimulai di tugas baru, tombol
+<em>Back</em> tetap akan mengembalikan pengguna ke aktivitas sebelumnya.</p></dd>
+<dt>{@code "singleInstance"}.</dt>
+  <dd>Sama seperti {@code "singleTask"}, namun sistem tidak meluncurkan aktivitas lain ke
+tugas yang menyimpan instance. Aktivitas selalu satu dan satu-satunya anggota dari tugasnya;
+aktivitas apa pun yang dimulai dengan ini akan dibuka di tugas yang terpisah.</dd>
+</dl>
+
+
+<p>Sebagai contoh lainnya, aplikasi Browser Android mendeklarasikan bahwa aktivitas browser web harus
+selalu dibuka dalam tugasnya sendiri&mdash;dengan menetapkan mode pembuka {@code singleTask} dalam elemen<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>.
+Ini berarti bahwa jika aplikasi Anda mengeluarkan
+intent untuk membuka Browser Android, aktivitasnya <em>tidak</em> akan ditempatkan dalam tugas
+yang sama seperti aplikasi Anda. Sebagai gantinya, tugas baru akan dimulai untuk Browser atau, jika Browser
+sudah memiliki tugas yang berjalan di latar belakang, tugas tersebut akan dimajukan untuk menangani intent
+baru.</p>
+
+<p>Baik aktivitas dimulai dalam tugas baru atau maupun dalam tugas yang sama seperti aktivitas yang memulainya, tombol
+<em>Back</em> selalu membawa pengguna ke aktivitas sebelumnya. Akan tetapi, jika
+Anda memulai aktivitas yang menetapkan mode pembuka {@code singleTask}, maka jika instance
+aktivitas tersebut ada dalam tugas latar belakang, seluruh tugas tersebut akan dibawa ke latar depan. Pada titik
+ini, back-stack sekarang menyertakan semua aktivitas dari tugas yang dimajukan, di atas
+back-stack. Gambar 4 mengilustrasikan tipe skenario ini.</p>
+
+<img src="{@docRoot}images/fundamentals/diagram_backstack_singletask_multiactivity.png" alt="" />
+<p class="img-caption"><strong>Gambar 4.</strong> Representasi tentang cara aktivitas dengan
+mode pembuka "singleTask" ditambahkan ke back-stack. Jika aktivitas tersebut sudah menjadi bagian dari
+tugas latar belakang dengan back-stack sendiri, maka seluruh back-stack juga
+dimajukan, di atas tugas saat ini.</p>
+
+<p>Untuk informasi selengkapnya tentang menggunakan mode pembuka dalam file manifes, lihat dokumentasi elemen
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+, di mana atribut {@code launchMode} dan nilai-nilai yang diterima
+akan dibahas selengkapnya.</p>
+
+<p class="note"><strong>Catatan:</strong> Perilaku yang Anda tentukan untuk aktivitas dengan atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a>
+bisa dikesampingkan dengan flag yang disertakan bersama intent yang memulai aktivitas Anda, seperti dibahas dalam
+bagian berikutnya.</p>
+
+
+
+<h4 id="#IntentFlagsForTasks">Menggunakan flag Intent</h4>
+
+<p>Saat memulai aktivitas, Anda bisa memodifikasi asosiasi default aktivitas pada tugasnya
+ dengan menyertakan flag dalam intent yang Anda kirimkan ke {@link
+android.app.Activity#startActivity startActivity()}. Flag yang bisa Anda gunakan untuk memodifikasi perilaku default
+adalah:</p>
+
+<p>
+  <dt>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</dt>
+    <dd>Memulai aktivitas dalam tugas baru. Jika tugas sudah dijalankan untuk aktivitas yang sekarang
+Anda mulai, tugas tersebut akan dibawa ke latar depan dengan status terakhir yang dipulihkan dan aktivitas
+akan menerima intent baru dalam {@link android.app.Activity#onNewIntent onNewIntent()}.
+    <p>Ini menghasilkan perilaku yang sama dengan nilai {@code "singleTask"} <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a>
+yang dibahas di bagian sebelumnya.</p></dd>
+  <dt>{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}</dt>
+    <dd>Jika aktivitas yang dimulai adalah aktivitas saat ini (di bagian teratas back-stack), maka
+instance yang ada akan menerima panggilan ke {@link android.app.Activity#onNewIntent onNewIntent()}
+sebagai ganti membuat instance baru aktivitas.
+    <p>Ini menghasilkan perilaku yang sama dengan nilai {@code "singleTop"} <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a>
+yang dibahas di bagian sebelumnya.</p></dd>
+  <dt>{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}</dt>
+    <dd>Jika aktivitas yang dimulai sudah berjalan dalam tugas saat ini, maka sebagai
+ganti meluncurkan instance baru aktivitas tersebut, semua kegiatan lain di atasnya akan
+dimusnahkan dan intent ini akan disampaikan ke instance aktivitas yang dilanjutkan (sekarang di atas),
+melalui {@link android.app.Activity#onNewIntent onNewIntent()}).
+    <p>Tidak ada nilai untuk atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a>
+ yang menghasilkan perilaku ini.</p>
+    <p>{@code FLAG_ACTIVITY_CLEAR_TOP} paling sering digunakan bersama dengan
+    {@code FLAG_ACTIVITY_NEW_TASK}.
+Bila digunakan bersama-sama, flag ini adalah cara penempatan aktivitas yang ada
+dalam tugas lain dan meletakkannya dalam posisi yang memungkinkannya merespons intent. </p>
+    <p class="note"><strong>Catatan:</strong> Jika mode pembuka aktivitas yang didesain adalah
+{@code "standard"},
+ini juga akan dihapus dari back-stack dan instance baru akan diluncurkan di tempatnya untuk menangani
+intent yang masuk.  Itu karena instance baru selalu dibuat untuk intent baru bila
+mode peluncuran adalah {@code "standard"}. </p>
+</dd>
+</dl>
+
+
+
+
+
+<h3 id="Affinities">Menangani afinitas</h3>
+
+<p><em>Afinitas</em> menunjukkan tugas mana yang disukai aktivitas untuk dimiliki. Secara default, semua
+aktivitas aplikasi yang sama memiliki afinitas untuk satu sama lain. Jadi, secara default, semua
+aktivitas dalam aplikasi yang sama lebih menyukai berada dalam tugas yang sama. Akan tetapi, Anda bisa memodifikasi
+afinitas default untuk suatu aktivitas. Aktivitas yang didefinisikan dalam
+aplikasi yang berbeda bisa berbagi afinitas, atau aktivitas yang didefinisikan dalam aplikasi yang sama bisa
+diberi afinitas tugas yang berbeda.</p>
+
+<p>Anda bisa memodifikasi afinitas untuk setiap yang diberikan
+dengan atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a>
+elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>.</p>
+
+<p>Atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a>
+mengambil nilai string, yang harus unik dari nama paket default
+yang dideklarasikan dalam elemen <a href="{@docRoot}guide/topics/manifest/manifest-element.html">
+{@code &lt;manifest&gt;}
+</a>, karena sistem menggunakan nama untuk mengidentifikasi afinitas
+tugas default untuk aplikasi.</p>
+
+<p>Afinitas berperan dalam dua keadaan:</p>
+<ul>
+  <li>Bila intent yang meluncurkan aktivitas berisi flag
+  {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}
+.
+
+<p>Aktivitas baru, secara default, diluncurkan ke dalam tugas aktivitas
+yang disebut {@link android.app.Activity#startActivity startActivity()}. Ini didorong ke back-stack
+yang sama seperti caller.  Akan tetapi, jika intent yang diteruskan ke
+{@link android.app.Activity#startActivity startActivity()}
+berisi flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}
+, maka sistem akan mencari tugas yang berbeda untuk menampung aktivitas baru. Sering kali, itu adalah tugas baru.
+Akan tetapi, tidak harus demikian.  Jika sudah ada tugas lama dengan afinitas yang sama seperti
+aktivitas baru, aktivitas ini akan diluncurkan ke dalam tugas tersebut.  Jika tidak, tugas baru akan dimulai.</p>
+
+<p>Jika flag ini menyebabkan aktivitas memulai tugas baru dan pengguna menekan tombol <em>Home</em>
+untuk meninggalkannya,
+harus ada cara bagi pengguna untuk mengarahkan kembali ke tugas. Beberapa entitas (seperti
+notification manager) selalu memulai aktivitas dalam tugas eksternal, tidak pernah sebagai bagian dari miliknya sendiri, jadi
+selalu menempatkan {@code FLAG_ACTIVITY_NEW_TASK} dalam intent yang diteruskan ke
+{@link android.app.Activity#startActivity startActivity()}.
+Jika Anda memiliki aktivitas yang bisa dipanggil melalui
+entitas eksternal yang mungkin menggunakan flag ini, hati-hatilah karena pengguna memiliki cara independen untuk kembali
+ke tugas yang telah dimulai, seperti dengan ikon launcher (aktivitas akar dari tugas
+memiliki filter intent {@link android.content.Intent#CATEGORY_LAUNCHER}; lihat bagian <a href="#Starting">Memulai tugas</a> di bawah ini).</p>
+</li>
+
+  <li>Bila aktivitas memiliki atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">
+{@code allowTaskReparenting}</a> sendiri yang diatur ke {@code "true"}.
+  <p>Dalam hal ini, aktivitas bisa berpindah dari tugas yang dimulainya ke tugas yang afinitasnya
+dimilikinya, bila tugas tersebut di bawa ke latar depan.</p>
+  <p>Misalnya, anggaplah sebuah aktivitas melaporkan kondisi cuaca di sejumlah kota terpilih
+yang didefinisikan sebagai bagian dari aplikasi perjalanan.  Aktivitas memiliki afinitas yang sama dengan aktivitas lain dalam aplikasi
+yang sama (afinitas aplikasi default) dan aktivitas ini memungkinkan re-parenting dengan atribut ini.
+Bila salah satu aktivitas Anda memulai aktivitas laporan cuaca, awalnya aktivitas ini dimiliki oleh tugas
+yang sama dengan aktivitas Anda. Akan tetapi, bila tugas aplikasi perjalanan di bawa ke latar depan,
+aktivitas laporan cuaca akan ditetapkan kembali ke tugas itu dan ditampilkan di dalamnya.</p>
+</li>
+</ul>
+
+<p class="note"><strong>Tip:</strong> Jika file {@code .apk} berisi lebih dari satu "aplikasi"
+dari sudut pandang pengguna, Anda mungkin perlu menggunakan atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a>
+ untuk menetapkan afinitas berbeda pada aktivitas yang terkait dengan setiap "aplikasi".</p>
+
+
+
+<h3 id="Clearing">Menghapus back-stack</h3>
+
+<p>Jika pengguna meninggalkan tugas dalam waktu yang lama, sistem akan menghapus tugas semua aktivitas kecuali
+aktivitas akar.  Bila pengguna kembali ke tugas itu lagi, hanya aktivitas akar yang akan dipulihkan.
+Sistem berperilaku seperti ini, karena, setelah sekian waktu, pengguna mungkin telah mengabaikan
+apa yang mereka kerjakan sebelum dan kembali ke tugas itu untuk memulai sesuatu yang baru. </p>
+
+<p>Ada beberapa atribut aktivitas yang bisa Anda gunakan untuk memodifikasi perilaku ini: </p>
+
+<dl>
+<dt><code><a
+href="{@docRoot}guide/topics/manifest/activity-element.html#always">alwaysRetainTaskState</a></code>
+</dt>
+<dd>Jika atribut ini ditetapkan ke {@code "true"} dalam aktivitas akar tugas,
+perilaku default yang baru dijelaskan tidak akan terjadi.
+ Tugas akan mempertahankan semua aktivitas dalam back-stack bahkan setelah sekian lama.</dd>
+
+<dt><code><a
+href="{@docRoot}guide/topics/manifest/activity-element.html#clear">clearTaskOnLaunch</a></code></dt>
+<dd>Jika atribut ini diatur ke {@code "true"} dalam aktivitas akar tugas, back-
+stack akan dihapus hingga aktivitas akar bila pengguna meninggalkan tugas
+dan kembali lagi.  Dengan kata lain, ini adalah lawan dari
+<a href="{@docRoot}guide/topics/manifest/activity-element.html#always">
+{@code alwaysRetainTaskState}</a>. Pengguna selalu kembali ke tugas dengan
+status awalnya, walaupun hanya sebentar meninggalkan tugas.</dd>
+
+<dt><code><a
+href="{@docRoot}guide/topics/manifest/activity-element.html#finish">finishOnTaskLaunch</a></code>
+</dt>
+<dd>Atribut ini seperti <a href="{@docRoot}guide/topics/manifest/activity-element.html#clear">{@code clearTaskOnLaunch}</a>,
+namun beroperasi pada
+satu aktivitas, bukan pada seluruh tugas.  Hal ini juga bisa menyebabkan aktivitas
+hilang, termasuk aktivitas akar.  Bila ini diatur ke {@code "true"},
+aktivitas akan tetap menjadi bagian dari tugas hanya untuk sesi saat ini.  Jika pengguna
+keluar dan kemudian kembali ke tugas tersebut, tugas tidak akan ada lagi.</dd>
+</dl>
+
+
+
+
+<h3 id="Starting">Memulai tugas</h3>
+
+<p>Anda bisa mengatur aktivitas sebagai titik masuk untuk tugas dengan memberikan filter intent dengan
+{@code "android.intent.action.MAIN"} sebagai tindakan yang ditetapkan dan
+{@code "android.intent.category.LAUNCHER"}
+sebagai kategori yang ditetapkan. Misalnya:</p>
+
+<pre>
+&lt;activity ... &gt;
+    &lt;intent-filter ... &gt;
+        &lt;action android:name="android.intent.action.MAIN" /&gt;
+        &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
+    &lt;/intent-filter&gt;
+    ...
+&lt;/activity&gt;
+</pre>
+
+<p>Filter intent semacam ini akan menyebabkan ikon dan label untuk
+aktivitas ditampilkan dalam launcher aplikasi, yang akan memberi cara kepada pengguna untuk meluncurkan aktivitas dan
+kembali ke tugas yang dibuatnya kapan saja setelah ia telah diluncurkan.
+</p>
+
+<p>Kemampuan kedua ini penting: Pengguna harus bisa meninggalkan tugas dan kemudian kembali ke tugas tersebut
+nanti dengan menggunakan launcher aktivitas ini. Karena itu, kedua <a href="#LaunchModes">mode
+pembuka</a> yang menandai aktivitas selalu memulai tugas, {@code "singleTask"} dan
+{@code "singleInstance"}, hanya boleh digunakan bila aktivitas memiliki filter
+{@link android.content.Intent#ACTION_MAIN}
+dan {@link android.content.Intent#CATEGORY_LAUNCHER}. Bayangkan, misalnya, apa yang akan
+terjadi jika filter tidak ada: Intent meluncurkan aktivitas{@code "singleTask"}, memulai
+tugas yang baru, dan pengguna menghabiskan lebih banyak waktu mengerjakan tugas tersebut. Pengguna kemudian menekan tombol
+<em>Home</em>. Tugas kini dikirim ke latar belakang dan tidak terlihat. Sekarang pengguna tidak memiliki cara untuk kembali
+ke tugas tersebut, karena tidak dinyatakan dalam launcher aplikasi.</p>
+
+<p>Untuk kasus-kasus di mana Anda tidak ingin pengguna bisa kembali ke aktivitas, atur dalam
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+ pada
+<a href="{@docRoot}guide/topics/manifest/activity-element.html#finish">{@code finishOnTaskLaunch}</a>
+elemen ke {@code "true"} (lihat <a href="#Clearing">Menghapus back-stack</a>).</p>
+
+<p>Informasi lebih jauh tentang cara menyatakan dan mengelola tugas dan aktivitas dalam
+layar ikhtisar tersedia dalam<a href="{@docRoot}guide/components/recents.html">
+Layar Ikhtisar</a>.</p>
+
+<!--
+<h2>Beginner's Path</h2>
+
+<p>For more information about how to use intents to
+activate other application components and publish the intents to which your components
+respond, continue with the <b><a
+href="{@docRoot}guide/components/intents-filters.html">Intents and Intent
+Filters</a></b> document.</p>
+-->
diff --git a/docs/html-intl/intl/id/guide/index.jd b/docs/html-intl/intl/id/guide/index.jd
new file mode 100644
index 0000000..f24fab6
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/index.jd
@@ -0,0 +1,74 @@
+page.title=Pengantar Android
+
+@jd:body
+
+
+<div class="sidebox" style="width:220px"><!-- width to match col-4 below -->
+<p>Untuk mempelajari cara kerja aplikasi, mulailah dengan
+<a href="{@docRoot}guide/components/fundamentals.html">Dasar-Dasar Aplikasi</a>.</p>
+<p>Untuk langsung memulai pemrograman, bacalah <a href="{@docRoot}training/basics/firstapp/index.html">Membangun Aplikasi Pertama Anda.</a></p>
+</div>
+
+<p>Android menyediakan kerangka kerja aplikasi yang kaya dan memungkinkan Anda membangun aplikasi dan permainan
+inovatif untuk perangkat seluler di lingkungan bahasa pemrograman Java. Dokumen yang tercantum di navigasi
+sebelah kiri menyediakan detail tentang cara membangun aplikasi menggunakan berbagai API Android.</p>
+
+<p>Jika Anda masih baru dengan pengembangan Android, Anda perlu memahami
+konsep dasar berikut mengenai kerangka kerja aplikasi Android:</p>
+
+
+<div class="landing-banner">
+
+<div class="col-6">
+
+<h4>Aplikasi menyediakan beberapa titik masuk</h4>
+
+<p>Aplikasi Android dibangun sebagai kombinasi beragam komponen yang bisa dipanggil
+satu per satu. Misalnya, satu <em>aktivitas</em> individual menyediakan satu
+layar untuk antarmuka pengguna, dan <em>layanan</em> yang secara terpisah melakukan
+tugas di latar belakang.</p>
+
+<p>Dari satu komponen Anda dapat memulai komponen lainnya menggunakan <em>intent</em>. Anda bahkan dapat memulai
+satu komponen dalam aplikasi berbeda, seperti aktivitas dalam aplikasi peta untuk menampilkan alamat. Model ini
+menyediakan beberapa titik masuk untuk aplikasi tunggal dan memungkinkan setiap aplikasi untuk berfungsi sebagai "default"
+pengguna bagi tindakan yang dapat dipanggil aplikasi lain.</p>
+
+
+<p><b>Ketahui selengkapnya:</b></p>
+<ul class="nolist">
+<li><a href="{@docRoot}guide/components/fundamentals.html">Dasar-Dasar Aplikasi</a>
+<li><a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter Intent</a>
+<li><a href="{@docRoot}guide/components/activities.html">Aktivitas</a>
+</ul>
+
+</div>
+
+
+<div class="col-6">
+
+<h4>Aplikasi beradaptasi dengan perangkat berbeda</h4>
+
+<p>Android menyediakan kerangka kerja aplikasi adaptif yang memungkinkan Anda menyediakan sumber daya unik
+bagi konfigurasi perangkat yang berbeda-beda. Misalnya, Anda bisa membuat berbagai file layout
+XML untuk ukuran layar yang berbeda-beda dan sistem akan menentukan
+layout yang akan diterapkan berdasarkan ukuran layar perangkat yang ada saat ini.</p>
+
+<p>Anda dapat melakukan query ketersediaan fitur perangkat saat dijalankan (runtime) jika ada fitur aplikasi yang memerlukan
+perangkat keras spesifik seperti kamera. Jika diperlukan, Anda juga bisa mendeklarasikan fitur yang dibutuhkan aplikasi
+agar pasar aplikasi seperti Google Play Store tidak mengizinkan instalasi pada perangkat yang tidak
+mendukung fitur itu.</p>
+
+
+<p><b>Ketahui selengkapnya:</b></p>
+<ul class="nolist">
+<li><a href="{@docRoot}guide/practices/compatibility.html">Kompatibilitas Perangkat</a>
+<li><a href="{@docRoot}guide/topics/resources/overview.html">Ikhtisar Sumber Daya</a>
+<li><a href="{@docRoot}guide/topics/ui/overview.html">Ikhtisar Antarmuka Pengguna</a>
+</ul>
+
+</div>
+
+</div><!-- end landing-banner -->
+
+
+
diff --git a/docs/html-intl/intl/id/guide/platform/j8-jack.jd b/docs/html-intl/intl/id/guide/platform/j8-jack.jd
new file mode 100644
index 0000000..4389184
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/platform/j8-jack.jd
@@ -0,0 +1,197 @@
+page.title=Fitur Bahasa Java 8
+page.keywords="android N", "Java 8", "Jack"
+@jd:body
+
+<div id="qv-wrapper">
+  <div id="qv">
+    <ol>
+      <li>
+        <a href="#supported-features">API dan Fitur Bahasa Java 8 yang didukung</a>
+      </li>
+      <li>
+        <a href="#configuration">Mengaktifkan Fitur Java 8 dan Jack Toolchain</a>
+      </li>
+    </ol>
+  </div>
+</div>
+
+<p>Android N memperkenalkan dukungan untuk fitur bahasa Java 8
+  yang bisa Anda gunakan saat mengembangkan aplikasi yang menargetkan Android N.
+  Halaman ini menjelaskan fitur bahasa baru yang didukung dalam Android N
+  Preview, cara menyiapkan proyek Anda dengan benar untuk menggunakannya, dan setiap masalah
+  yang diketahui yang mungkin Anda temui.
+</p>
+
+<p>Untuk mulai menggunakan fitur-fitur ini, Anda perlu mengunduh dan menyiapkan Android
+Studio 2.1 dan Android N Preview SDK, yang menyertakan
+Jack toolchain yang diperlukan dan Plugin Android untuk Gradle yang telah diperbarui. Jika Anda belum
+memasang Android N Preview SDK, lihat <a href="{@docRoot}preview/setup-sdk.html">Menyiapkan Pengembangan untuk Android N</a>.</p>
+
+
+
+<p class="note">
+  <strong>Catatan:</strong> Menggunakan fitur bahasa Java 8 yang baru bukanlah
+  persyaratan untuk mengembangkan aplikasi yang menargetkan platform Android N. Jika Anda
+  tidak ingin menulis kode dengan fitur bahasa Java 8, Anda bisa membiarkan nilai kompatibilitas
+  sumber dan target proyek disetel ke Java 7, namun Anda tetap harus
+  mengompilasi dengan JDK 8 untuk membangun pada platform Android N.
+</p>
+
+<h2 id="supported-features">
+  API dan Fitur Bahasa Java 8 yang Didukung
+</h2>
+
+<p>
+  Saat ini tidak semua fitur bahasa Java 8 didukung Android. Akan tetapi,
+  fitur berikut sekarang tersedia saat mengembangkan aplikasi yang menargetkan
+  Android N Preview:
+</p>
+
+<ul>
+  <li>
+    <a class="external-link" href="https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html">Metode
+    antarmuka default dan statis</a>
+  </li>
+
+  <li>
+    <a class="external-link" href="https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html">
+    Ekspresi Lambda</a> (juga tersedia pada API level 23 dan yang lebih rendah)
+  </li>
+
+  <li>
+    <a class="external-link" href="https://docs.oracle.com/javase/tutorial/java/annotations/repeating.html">Anotasi
+    yang bisa diulang</a>
+  </li>
+
+  <li>
+    <a class="external-link" href="https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html">
+    Referensi Metode</a> (juga tersedia pada API level 23 dan yang lebih rendah)
+  </li>
+</ul>
+
+<p class="note">
+  <strong>Catatan:</strong> Untuk menguji ekspresi lambda dan referensi metode pada
+  Android versi sebelumnya, bukalah file {@code build.gradle}
+  Anda, serta setel {@code compileSdkVersion} dan {@code targetSdkVersion} ke 23 atau
+  yang lebih rendah. Anda tetap perlu <a href="#configuration">mengaktifkan Jack
+  toolchain</a> untuk menggunakan fitur Java 8 ini.
+</p>
+
+<p>
+  Selain itu, API fitur bahasa Java 8 berikut ini sekarang tersedia:
+</p>
+
+<ul>
+  <li>Reflection API dan API terkait bahasa:
+    <ul>
+      <li>
+        <a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html">
+        {@code java.lang.FunctionalInterface}</a>
+      </li>
+
+      <li>
+        <a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/lang/annotation/Repeatable.html">
+        {@code java.lang.annotation.Repeatable}</a>
+      </li>
+
+      <li>
+        <a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#isDefault--">
+        {@code java.lang.reflect.Method.isDefault()}</a>
+      </li>
+
+      <li>dan Reflection API yang terkait dengan anotasi yang bisa diulang, seperti
+     <a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/AnnotatedElement.html#getAnnotationsByType-java.lang.Class-">
+{@code AnnotatedElement.getAnnotationsByType(Class)}</a>
+      </li>
+    </ul>
+  </li>
+
+  <li>Utility API:
+    <ul>
+      <li>
+        <a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html">
+        {@code java.util.function}</a>
+      </li>
+
+      <li>
+        <a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html">
+        {@code java.util.stream}</a>
+      </li>
+    </ul>
+  </li>
+</ul>
+
+<h2 id="configuration">
+  Mengaktifkan Fitur Java 8 dan Jack Toolchain
+</h2>
+
+<p>
+  Agar dapat menggunakan fitur bahasa Java 8 yang baru, Anda juga perlu menggunakan
+  <a class="external-link" href="https://source.android.com/source/jack.html">Jack toolchain</a> yang baru.  Toolchain Android
+ yang baru ini mengompilasi sumber bahasa Java menjadi dex
+  bytecode yang bisa dibaca Android, memiliki format  pustaka {@code .jack} sendiri, dan menyediakan sebagian besar fitur toolchain
+  sebagai bagian dari alat bantu tunggal: pengemasan ulang, penciutan, pengaburan, dan
+  multidex.
+</p>
+
+<p>Inilah perbandingan dua toolchain yang digunakan untuk membangun file Android DEX:</p>
+<ul>
+  <li>Toolchain javac lawas:<br>
+  <b>javac</b> ({@code .java} --&gt; {@code .class}) --&gt; <b>dx</b> ({@code
+ .class} --&gt; {@code .dex})
+  </li>
+
+  <li>Jack Toolchain baru:<br>
+  <b>Jack</b> ({@code .java} --&gt; {@code .jack} --&gt; {@code .dex})
+  </li>
+</ul>
+
+<h3>
+  Mengonfigurasi Gradle
+</h3>
+
+<p>
+  Untuk mengaktifkan fitur bahasa Java 8 dan Jack bagi proyek Anda, masukkan
+  yang berikut dalam file {@code build.gradle} level modul Anda:
+</p>
+
+<pre>
+android {
+  ...
+  defaultConfig {
+    ...
+    jackOptions {
+      enabled true
+    }
+  }
+  compileOptions {
+    sourceCompatibility JavaVersion.VERSION_1_8
+    targetCompatibility JavaVersion.VERSION_1_8
+  }
+}
+</pre>
+
+<h3 id="known-issues">
+  Masalah yang Diketahui
+</h3>
+
+<p>
+  <a href="{@docRoot}tools/building/building-studio.html#instant-run">Instant
+  Run</a> saat ini tidak berfungsi pada Jack dan akan dinonaktifkan saat menggunakan
+  toolchain baru.
+</p>
+
+<p>Karena Jack tidak menghasilkan file kelas antara saat mengompilasi sebuah
+aplikasi, alat yang bergantung pada file-file ini sekarang tidak berfungsi pada Jack. Beberapa
+contoh alat ini adalah:</p>
+
+<ul>
+  <li>Pendeteksi lint yang beroperasi pada file kelas
+  </li>
+
+  <li>Alat dan pustaka yang mewajibkan file kelas aplikasi (misalnya
+pengujian instrumentasi dengan JaCoCo)
+  </li>
+</ul>
+
+<p>Jika Anda menemukan masalah lain saat menggunakan Jack, <a href="http://tools.android.com/filing-bugs">laporkan bug</a>.</p>
\ No newline at end of file
diff --git a/docs/html-intl/intl/id/guide/topics/manifest/manifest-intro.jd b/docs/html-intl/intl/id/guide/topics/manifest/manifest-intro.jd
new file mode 100644
index 0000000..050abf4
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/manifest/manifest-intro.jd
@@ -0,0 +1,517 @@
+page.title=Manifes Aplikasi
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>Dalam dokumen ini</h2>
+<ol>
+<li><a href="#filestruct">Struktur File Manifes</a></li>
+<li><a href="#filec">Konvensi File</a>
+<li><a href="#filef">Fitur File</a>
+	<ol>
+	<li><a href="#ifs">Filter Intent</a></li>
+	<li><a href="#iconlabel">Ikon dan Label</a></li>
+	<li><a href="#perms">Izin</a></li>
+	<li><a href="#libs">Pustaka</a></li>
+	</ol></li>
+</ol>
+</div>
+</div>
+
+<p>
+  Setiap aplikasi harus memiliki file AndroidManifest.xml (bernama persis seperti ini) di direktori akar.
+ <span itemprop="description">File manifes
+ menyediakan informasi penting tentang aplikasi ke sistem Android,
+ informasi yang harus dimiliki sistem agar bisa menjalankan setiap kode
+aplikasi.</span> Di antaranya, manifes melakukan hal berikut ini:
+</p>
+
+<ul>
+<li>Menamai paket Java untuk aplikasi.
+Nama paket berfungsi sebagai identifier unik untuk aplikasi.</li>
+
+<li>Menjelaskan berbagai komponen aplikasi&mdash;aktivitas,
+ layanan, penerima siaran, dan penyedia konten
+yang membentuk aplikasi.  Menamai kelas yang mengimplementasikan setiap komponen dan
+mempublikasikan kemampuannya (misalnya, pesan {@link android.content.Intent
+Intent} mana yang bisa ditanganinya).  Deklarasi ini memberi tahu sistem Android mengenai
+komponennya dan dalam kondisi apa bisa diluncurkan.</li>
+
+<li>Menentukan proses yang akan menjadi host komponen aplikasi.</li>
+
+<li>Mendeklarasikan izin aplikasi mana yang harus dimiliki untuk
+mengakses bagian yang dilindungi pada API dan berinteraksi dengan aplikasi lain.</li>
+
+<li>Juga mendeklarasikan izin lain yang harus dimiliki untuk
+untuk berinteraksi dengan komponen aplikasi.</li>
+
+<li>Mencantumkan daftar kelas {@link android.app.Instrumentation} yang memberikan
+profil dan informasi lain saat aplikasi berjalan.  Deklarasi ini
+hanya ada di manifes saat aplikasi dibuat dan diuji;
+ deklarasi dihapus sebelum aplikasi dipublikasikan.</li>
+
+<li>Mendeklarasikan tingkat minimum API Android yang diperlukan
+aplikasi.</li>
+
+<li>Mencantumkan daftar pustaka yang harus ditautkan aplikasi.</li>
+</ul>
+
+
+<h2 id="filestruct">Struktur File Manifes</h2>
+
+<p>
+Diagram di bawah ini menampilkan struktur umum file manifes dan setiap
+elemen yang bisa ditampungnya.  Setiap elemen, bersama
+atributnya, didokumentasikan secara lengkap dalam file terpisah.  Untuk melihat
+informasi terperinci tentang setiap elemen, klik nama elemen dalam diagram,
+dalam daftar abjad elemen yang mengikuti diagram, atau penyebutan nama
+elemen lainnya.
+</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+
+<a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a>
+
+    <a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission /&gt;</a>
+    <a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission /&gt;</a>
+    <a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree /&gt;</a>
+    <a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group /&gt;</a>
+    <a href="{@docRoot}guide/topics/manifest/instrumentation-element.html">&lt;instrumentation /&gt;</a>
+    <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk /&gt;</a>
+    <a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration /&gt;</a>  <!-- ##api level 3## -->
+    <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature /&gt;</a>  <!-- ##api level 4## -->
+    <a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens /&gt;</a>  <!-- ##api level 4## -->
+    <a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">&lt;compatible-screens /&gt;</a>  <!-- ##api level 9## -->
+    <a href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">&lt;supports-gl-texture /&gt;</a>  <!-- ##api level 11## -->
+
+    <a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a>
+
+        <a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a>
+            <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a>
+                <a href="{@docRoot}guide/topics/manifest/action-element.html">&lt;action /&gt;</a>
+                <a href="{@docRoot}guide/topics/manifest/category-element.html">&lt;category /&gt;</a>
+                <a href="{@docRoot}guide/topics/manifest/data-element.html">&lt;data /&gt;</a>
+            <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;/intent-filter&gt;</a>
+            <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data /&gt;</a>
+        <a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;/activity&gt;</a>
+
+        <a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a>
+            <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a> . . . <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;/intent-filter&gt;</a>
+            <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data /&gt;</a>
+        <a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;/activity-alias&gt;</a>
+
+        <a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a>
+            <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a> . . . <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;/intent-filter&gt;</a>
+            <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data/&gt;</a>
+        <a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;/service&gt;</a>
+
+        <a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a>
+            <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a> . . . <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;/intent-filter&gt;</a>
+            <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data /&gt;</a>
+        <a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;/receiver&gt;</a>
+
+        <a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a>
+            <a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission /&gt;</a>
+            <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data /&gt;</a>
+            <a href="{@docRoot}guide/topics/manifest/path-permission-element.html">&lt;path-permission /&gt;</a>
+        <a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;/provider&gt;</a>
+
+        <a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library /&gt;</a>
+
+    <a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;/application&gt;</a>
+
+<a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;/manifest&gt;</a>
+</pre>
+
+<p>
+Semua elemen yang bisa muncul dalam file manifes tercantum di bawah ini
+dalam urutan abjad.  Ini adalah satu-satunya elemen legal; Anda tidak bisa
+menambahkan elemen atau atribut sendiri.
+</p>
+
+<p style="margin-left: 2em">
+<code><a href="{@docRoot}guide/topics/manifest/action-element.html">&lt;action&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/category-element.html">&lt;category&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/data-element.html">&lt;data&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/instrumentation-element.html">&lt;instrumentation&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a></code>  <!-- ##api level 4## -->
+<br/><code><a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></code>  <!-- ##api level 3## -->
+<br/><code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature&gt;</a></code>  <!-- ##api level 4## -->
+<br/><code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</a></code>
+</p>
+
+
+
+
+<h2 id="filec">Konvensi File</h2>
+
+<p>
+Sebagian konvensi dan aturan berlaku secara umum untuk semua elemen
+dan atribut di manifes:
+</p>
+
+<dl>
+<dt><b>Elemen</b></dt>
+<dd>Hanya elemen
+<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code> dan
+<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
+yang diwajibkan, masing-masing harus ada dan hanya boleh terjadi sekali.
+Umumnya elemen lain bisa terjadi berkali-kali atau sama sekali tidak terjadi &mdash; meskipun
+setidaknya sebagian dari elemen itu harus ada untuk agar manifes mencapai sesuatu yang
+berarti.
+
+<p>
+Jika elemen tidak berisi apa pun, berarti elemen itu berisi elemen lain.
+Semua nilai diatur melalui atribut, bukan sebagai data karakter dalam elemen.
+</p>
+
+<p>
+Elemen yang sama tingkatan umumnya tidak diurutkan.  Misalnya, elemen
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>,
+<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>, dan
+<code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>
+bisa dicampur dalam urutan apa pun.  (Elemen
+<code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code>
+ merupakan eksepsi untuk aturan ini:  Elemen ini harus mengikuti
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+ini aliasnya.)
+</p></dd>
+
+<dt><b>Atribut</b></dt>
+<dd>Secara formal, semua atribut opsional.  Akan tetapi, ada sebagian
+yang harus ditetapkan agar elemen bisa mencapai tujuannya.  Gunakan
+dokumentasi sebagai panduan.  Bagi atribut yang benar-benar opsional, ini menyebutkan
+nilai default atau menyatakan apa yang terjadi jika tidak ada spesifikasi.
+
+<p>Selain untuk beberapa atribut elemen akar
+<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>,
+ semua nama atribut dimulai dengan awalan {@code android:} &mdash;
+misalnya, {@code android:alwaysRetainTaskState}.  Karena awalan ini universal, dokumentasi umumnya meniadakannya saat mengacu atribut
+dengan nama.
+</p></dd>
+
+<dt><b>Mendeklarasikan nama kelas</b></dt>
+<dd>Banyak elemen berhubungan dengan objek Java, termasuk elemen
+aplikasi itu sendiri (elemen
+<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
+) dan aktivitas komponen &mdash; utamanya
+(<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>),
+layanan
+(<code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>),
+penerima siaran
+(<code><a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code>),
+dan penyedia konten
+(<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>).
+
+<p>
+Jika mendefinisikan subkelas, seperti yang selalu Anda definisikan untuk kelas komponen
+({@link android.app.Activity}, {@link android.app.Service},
+{@link android.content.BroadcastReceiver}, dan {@link android.content.ContentProvider}),
+subkelas dideklarasikan melalui atribut {@code name}.  Nama harus menyertakan tujuan
+paket lengkap.
+Misalnya, subkelas {@link android.app.Service} mungkin dideklarasikan sebagai berikut:
+</p>
+
+<pre>&lt;manifest . . . &gt;
+    &lt;application . . . &gt;
+        &lt;service android:name="com.example.project.SecretService" . . . &gt;
+            . . .
+        &lt;/service&gt;
+        . . .
+    &lt;/application&gt;
+&lt;/manifest&gt;</pre>
+
+<p>
+Akan tetapi, sebagai shorthand, jika karakter pertama string adalah titik,
+string akan ditambahkan ke nama paket aplikasi (seperti yang ditetapkan dalam elemen
+<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
+ melalui atribut
+<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html#package">package</a></code>
+).  Penetapan berikut sama dengan di atas:
+</p>
+
+<pre>&lt;manifest package="com.example.project" . . . &gt;
+    &lt;application . . . &gt;
+        &lt;service android:name=".SecretService" . . . &gt;
+            . . .
+        &lt;/service&gt;
+        . . .
+    &lt;/application&gt;
+&lt;/manifest&gt;</pre>
+
+<p>
+Saat memulai komponen, Android akan membuat instance subkelas yang diberi nama.
+Jika subkelas tidak ditetapkan, maka akak dibuat instance kelas dasar.
+</p></dd>
+
+<dt><b>Banyak nilai</b></dt>
+<dd>Jika lebih dari satu nilai yang dapat ditetapkan, elemen ini hampir selalu
+diulangi, bukan menampilkan daftar banyak nilai dalam satu elemen.
+Misalnya, filter intent dapat mencantumkan beberapa tindakan:
+
+<pre>&lt;intent-filter . . . &gt;
+    &lt;action android:name="android.intent.action.EDIT" /&gt;
+    &lt;action android:name="android.intent.action.INSERT" /&gt;
+    &lt;action android:name="android.intent.action.DELETE" /&gt;
+    . . .
+&lt;/intent-filter&gt;</pre></dd>
+
+<dt><b>Nilai sumber daya</b></dt>
+<dd>Beberapa atribut memiliki nilai yang bisa ditampilkan kepada pengguna &mdash; misalnya
+, label dan ikon aktivitas.  Nilai atribut ini
+harus dilokalkan dan karenanya ditetapkan dari sumber daya atau tema.  Nilai sumber
+daya dinyatakan dalam format berikut,</p>
+
+<p style="margin-left: 2em">{@code @[<i>package</i>:]<i>type</i>:<i>name</i>}</p>
+
+<p>
+dalam hal ini nama <i>package</i> boleh dihilangkan jika sumber daya ada dalam paket yang sama dengan
+dengan aplikasi, <i>type</i> adalah tipe sumber daya &mdash; seperti "string" atau
+"drawable" &mdash; dan <i>name</i> adalah nama yang mengidentifikasi sumber daya tertentu.
+Misalnya:
+</p>
+
+<pre>&lt;activity android:icon="@drawable/smallPic" . . . &gt</pre>
+
+<p>
+Nilai tema diekspresikan dengan cara yang sama, namun dengan awal '{@code ?}'
+dan bukan '{@code @}':
+</p>
+
+<p style="margin-left: 2em">{@code ?[<i>package</i>:]<i>type</i>:<i>name</i>}
+</p></dd>
+
+<dt><b>Nilai-nilai string</b></dt>
+<dd>Bila nilai atribut adalah string, dua garis miring kiri ('{@code \\}')
+harus digunakan untuk meninggalkan karakter &mdash; misalnya, '{@code \\n}' untuk
+baris baru atau '{@code \\uxxxx}' untuk karakter Unicode.</dd>
+</dl>
+
+
+<h2 id="filef">Fitur File</h2>
+
+<p>
+Bagian berikut menjelaskan cara menerapkan sebagian fitur Android
+dalam file manifest.
+</p>
+
+
+<h3 id="ifs">Filter Intent</h3>
+
+<p>
+Komponen inti dari aplikasi (aktivitasnya, layanannya, dan penerima
+siaran) diaktifkan oleh <i>intent</i>.  Intent adalah
+sekumpulan informasi (objek {@link android.content.Intent}) yang menjelaskan
+tindakan yang diinginkan &mdash; termasuk data yang akan ditindaklanjuti, kategori
+komponen yang harus melakukan tindakan, dan petunjuk terkait lainnya.
+Android mencari komponen yang sesuai untuk merespons intent, meluncurkan
+instance komponen baru jika diperlukan, dan meneruskannya ke
+objek Intent.
+</p>
+
+<p>
+Komponen mengiklankan kemampuannya &mdash; jenis intent yang bisa diresponsnya
+ &mdash; melalui <i>filter intent</i>.  Karena sistem Android
+harus mempelajari intent yang dapat ditangani komponen sebelum meluncurkan komponen,
+filter intent ditetapkan dalam manifes sebagai elemen
+<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
+.  Sebuah komponen dapat memiliki filter dalam jumlah berapa saja, masing-masing menjelaskan
+kemampuan yang berbeda.
+</p>
+
+<p>
+Intent yang secara eksplisit menamai komponen target akan mengaktifkan komponen itu;
+filter tidak berperan.  Namun intent yang tidak menetapkan target
+dengan nama dapat mengaktifkan komponen hanya jika dapat melewati salah satu filter
+komponen.
+</p>
+
+<p>
+Untuk informasi tentang cara objek Intent diuji terhadap filter intent,
+lihat dokumen terpisah,
+<a href="{@docRoot}guide/components/intents-filters.html">Intent
+dan Filter Intent</a>.
+</p>
+
+
+<h3 id="iconlabel">Ikon dan Label</h3>
+
+<p>
+Sejumlah elemen memiliki atribut {@code icon} dan {@code label} untuk
+ikon kecil dan label teks yang bisa ditampilkan kepada pengguna.  Sebagian ada juga yang memiliki atribut
+{@code description}untuk teks penjelasan yang lebih panjang yang juga bisa
+ditampilkan pada layar.  Misalnya, elemen
+<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
+ memiliki ketiga atribut ini, jadi saat pengguna ditanya apakah akan
+memberi izin bagi aplikasi yang memintanya, ikon yang mewakili
+izin, nama izin, dan keterangan yang
+mengikutinya bisa ditampilkan kepada pengguna.
+</p>
+
+<p>
+Dalam setiap kasus, ikon dan label yang ditetapkan dalam elemen yang memuatnya menjadi
+{@code icon} default dan pengaturan {@code label} untuk semua subelemen kontainer ini.
+Karena itu, ikon dan label yang ditetapkan dalam elemen
+<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
+adalah ikon dan label default untuk setiap komponen aplikasi.
+Demikian pula, ikon dan label yang ditetapkan untuk komponen &mdash; misalnya, elemen
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+&mdash; adalah pengaturan default untuk setiap elemen komponen
+<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
+.  Jika elemen
+<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
+menetapkan label, namun suatu aktivitas dan filter intent-nya tidak menetapkan label,
+maka label aplikasi akan dianggap sama-sama sebagai label aktvitas dan
+filter intent.
+</p>
+
+<p>
+Ikon dan label yang ditetapkan untuk filter intent digunakan untuk mewakili komponen
+kapan saja komponen ditampilkan kepada pengguna saat memenuhi fungsi yang
+diiklankan oleh filter.  Misalnya, filter dengan pengaturan
+"{@code android.intent.action.MAIN}" dan
+"{@code android.intent.category.LAUNCHER}" mengiklankan aktivitas
+sebagai aktivitas yang memulai aplikasi&mdash;, yaitu
+sebagai salah satu aktivitas yang harus ditampilkan dalam launcher aplikasi.  Ikon dan label yang
+diatur dalam filter karenanya adalah ikon dan label yang ditampilkan dalam launcher.
+</p>
+
+
+<h3 id="perms">Izin</h3>
+
+<p>
+Sebuah <i>izin</i> adalah pembatasan yang membatasi akses ke bagian
+kode atau ke data pada perangkat.   Pembatasan diberlakukan untuk melindungi data dan kode
+penting yang bisa disalahgunakan untuk mengganggu atau merusak pengalaman pengguna.
+</p>
+
+<p>
+Setiap izin diidentifikasi melalui label yang unik.  Sering kali, label menunjukkan
+tindakan yang dibatasi.  Misalnya, berikut ini adalah beberapa izin yang didefinisikan
+oleh Android:
+</p>
+
+<p style="margin-left: 2em">{@code android.permission.CALL_EMERGENCY_NUMBERS}
+<br/>{@code android.permission.READ_OWNER_DATA}
+<br/>{@code android.permission.SET_WALLPAPER}
+<br/>{@code android.permission.DEVICE_POWER}</p>
+
+<p>
+Sebuah fitur bisa dilindungi paling banyak oleh satu izin.
+</p>
+
+<p>
+Jika aplikasi memerlukan akses ke fitur yang dilindungi oleh izin,
+aplikasi harus mendeklarasikan bahwa aplikasi memerlukan izin itu dengan elemen
+<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
+ dalam manifes.  Kemudian, bila aplikasi telah diinstal pada
+perangkat, installer akan menentukan apakah izin yang diminta akan diberikan atau tidak
+dengan memeriksa otoritas yang menandatangani
+sertifikat aplikasi dan, dalam beberapa kasus, bertanya pada pengguna.
+Jika izin diberikan, aplikasi tersebut bisa menggunakan
+fitur yang dilindungi.  Jika tidak, upaya aplikasi untuk mengakses fitur tersebut akan gagal
+tanpa ada pemberitahuan apa pun kepada pengguna.
+</p>
+
+<p>
+Aplikasi juga bisa melindungi komponennya sendiri (aktivitas, layanan,
+penerima siaran, dan penyedia konten) dengan izin.  Aplikasi bisa menerapkan
+izin mana pun yang didefinisikan oleh Android (tercantum dalam
+{@link android.Manifest.permission android.Manifest.permission}) atau dideklarasikan
+oleh aplikasi lain.  Atau aplikasi bisa mendefinisikannya sendiri.  Izin baru dideklarasikan
+dengan elemen
+<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
+.  Misalnya, aktivitas dapat dilindungi sebagai berikut:
+</p>
+
+<pre>
+&lt;manifest . . . &gt;
+    &lt;permission android:name="com.example.project.DEBIT_ACCT" . . . /&gt;
+    &lt;uses-permission android:name="com.example.project.DEBIT_ACCT" /&gt;
+    . . .
+    &lt;application . . .&gt;
+        &lt;activity android:name="com.example.project.FreneticActivity"
+                  android:permission="com.example.project.DEBIT_ACCT"
+                  . . . &gt;
+            . . .
+        &lt;/activity&gt;
+    &lt;/application&gt;
+&lt;/manifest&gt;
+</pre>
+
+<p>
+Perhatikan, dalam contoh ini izin {@code DEBIT_ACCT} tidak hanya
+dideklarasikan dengan elemen
+<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
+, penggunaannya juga diminta dengan elemen
+<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
+.  Penggunaannya harus diminta agar komponen
+aplikasi lainnya bisa menjalankan aktivitas yang dilindungi, meskipun perlindungan itu
+diberlakukan oleh aplikasi itu sendiri.
+</p>
+
+<p>
+Dalam contoh yang sama, jika atribut {@code permission} ditetapkan
+untuk izin yang dideklarasikan di tempat lain
+lain (seperti {@code android.permission.CALL_EMERGENCY_NUMBERS}, maka atribut
+tidak perlu mendeklarasikannya lagi dengan elemen
+<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
+.  Akan tetapi, penggunaannya masih perlu dengan
+<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>.
+</p>
+
+<p>
+Elemen
+<code><a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></code>
+mendeklarasikan namespace untuk grup izin yang akan didefinisikan dalam
+kode.  Dan
+<code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
+mendefinisikan label untuk seperangkat izin (yang sama-sama dideklarasikan dalam manifes dengan elemen
+<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
+dan yang dideklarasikan di tempat lain).  Ini hanya memengaruhi cara izin
+dikelompokkan saat ditampilkan kepada pengguna.  Elemen
+<code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
+ tidak menetapkan izin mana dimiliki grup;
+elemen hanya memberi nama grup.  Izin ditempatkan dalam grup
+dengan memberikan nama grup ke elemen
+<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
+ melalui atribut
+<code><a href="{@docRoot}guide/topics/manifest/permission-element.html#pgroup">permissionGroup</a></code>
+.
+</p>
+
+
+<h3 id="libs">Pustaka</h3>
+
+<p>
+Setiap aplikasi ditautkan dengan pustaka default Android, yang
+menyertakan paket dasar untuk membangun aplikasi (dengan kelas umum
+seperti Activity, Service, Intent, View, Button, Application, ContentProvider,
+dan sebagainya).
+</p>
+
+<p>
+Akan tetapi, sebagian paket berada dalam pustakanya sendiri.  Jika aplikasi Anda
+menggunakan kode salah satu paket ini, aplikasi secara eksplisit meminta untuk ditautkan dengan
+paket tersebut.  Manifes harus berisi elemen
+<code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></code> yang
+terpisah untuk menamai setiap pustaka.  (Nama pustaka bisa ditemukan
+dalam dokumentasi paket.)
+</p>
diff --git a/docs/html-intl/intl/id/guide/topics/providers/calendar-provider.jd b/docs/html-intl/intl/id/guide/topics/providers/calendar-provider.jd
new file mode 100644
index 0000000..3058815
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/providers/calendar-provider.jd
@@ -0,0 +1,1184 @@
+page.title=Penyedia Kalender
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+    <h2>Dalam dokumen ini</h2>
+    <ol>
+  <li><a href="#overview">Dasar-Dasar</a></li>
+  <li><a href="#manifest">Izin Pengguna</a></li>
+  <li><a href="#calendar">Tabel kalender</a>
+<ol>
+      <li><a href="#query">Membuat query kalender</a></li>
+      <li><a href="#modify-calendar">Memodifikasi kalender</a></li>
+      <li><a href="#insert-calendar">Menyisipkan kalender</a></li>
+    </ol>
+  </li>
+  <li><a href="#events">Tabel Events</a>
+<ol>
+      <li><a href="#add-event">Menambahkan Kejadian</a></li>
+      <li><a href="#update-event">Memperbarui Kejadian</a></li>
+      <li><a href="#delete-event">Menghapus Kejadian</a></li>
+    </ol>
+  </li>
+  <li><a href="#attendees">Tabel peserta</a>
+<ol>
+      <li><a href="#add-attendees">Menambahkan Peserta</a></li>
+    </ol>
+  </li>
+  <li><a href="#reminders">Tabel pengingat</a>
+<ol>
+      <li><a href="#add-reminders">Menambahkan Pengingat</a></li>
+    </ol>
+  </li>
+  <li><a href="#instances">Tabel Instances</a>
+  <ol>
+      <li><a href="#query-instances">Membuat query tabel Instance</a></li>
+  </ol></li>
+  <li><a href="#intents">Intent Kalender</a>
+  <ol>
+      <li><a href="#intent-insert">Menggunakan intent untuk menyisipkan kejadian</a></li>
+      <li><a href="#intent-edit">Menggunakan intent untuk mengedit kejadian</a></li>
+      <li><a href="#intent-view">Menggunakan intent untuk menampilkan data kalender</a></li>
+    </ol>
+  </li>
+
+  <li><a href="#sync-adapter">Adaptor Sinkronisasi</a></li>
+</ol>
+
+    <h2>Kelas-kelas utama</h2>
+    <ol>
+      <li>{@link android.provider.CalendarContract.Calendars}</li>
+      <li>{@link android.provider.CalendarContract.Events}</li>
+      <li>{@link android.provider.CalendarContract.Attendees}</li>
+      <li>{@link android.provider.CalendarContract.Reminders}</li>
+    </ol>
+</div>
+</div>
+
+<p>Penyedia Kalender adalah repository untuk kejadian kalender seorang pengguna. API
+Penyedia Kalender memungkinkan Anda melakukan query, menyisipkan, memperbarui, dan menghapus
+pada kalender, kejadian, peserta, pengingat, dan seterusnya.</p>
+
+
+<p>API Penyedia Kalender bisa digunakan oleh aplikasi dan adaptor sinkronisasi. Aturannya
+bervariasi menurut tipe program yang membuat panggilan. Dokumen ini
+terutama berfokus pada penggunaan API Penyedia Kalender sebagai sebuah aplikasi. Untuk
+pembahasan ragam adaptor sinkronisasi, lihat
+<a href="#sync-adapter">Adaptor Sinkronisasi</a>.</p>
+
+
+<p>Biasanya, untuk membaca atau menulis data kalender, manifes aplikasi harus
+berisi izin yang sesuai, yang dijelaskan dalam <a href="#manifest">Izin
+Pengguna</a>. Untuk mempermudah dilakukannya operasi umum,
+Penyedia Kalender menyediakan satu set intent, seperti dijelaskan dalam <a href="#intents">Intent
+Kalender</a>. Semua intent ini membawa pengguna ke aplikasi Kalender untuk menyisipkan, menampilkan,
+dan mengedit kejadian. Pengguna berinteraksi dengan aplikasi Kalender kemudian
+kembali ke aplikasi semula. Jadi, aplikasi Anda tidak perlu meminta izin,
+juga tidak perlu menyediakan antarmuka pengguna untuk menampilkan atau membuat kejadian.</p>
+
+<h2 id="overview">Dasar-Dasar</h2>
+
+<p><a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia konten</a> menyimpan data dan menjadikannya bisa diakses oleh
+aplikasi. Penyedia konten yang ditawarkan oleh platform Android (termasuk Penyedia Kalender) biasanya mengekspos data sebagai satu set tabel berdasarkan
+model database relasional, dengan tiap baris berupa record dan tiap kolom berupa data
+yang memiliki tipe dan arti tertentu. Melalui API Penyedia Kalender, aplikasi
+dan adaptor sinkronisasi bisa mendapatkan akses baca/tulis ke tabel-tabel database yang menyimpan
+data kalender seorang pengguna.</p>
+
+<p>Setiap penyedia konten membuka sebuah URI publik (yang dibungkus sebagai objek
+{@link android.net.Uri}
+) yang mengidentifikasikan set datanya secara unik.  Penyedia konten yang mengontrol
+ beberapa set data (beberapa tabel) mengekspos URI terpisah untuk tiap set.  Semua
+URI untuk penyedia diawali dengan string "content://".  String ini
+mengidentifikasi data sebagai dikontrol oleh penyedia konten. Penyedia Kalender
+mendefinisikan konstanta untuk URI masing-masing kelas (tabel). URI ini
+memiliki format <code><em>&lt;class&gt;</em>.CONTENT_URI</code>. Misalnya,
+{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}.</p>
+
+<p>Gambar 1 menampilkan representasi grafis model data Penyedia Kalender. Gambar ini menampilkan
+tabel dan bidang utama yang saling berkaitan.</p>
+
+<img src="{@docRoot}images/providers/datamodel.png" alt="Calendar Provider Data Model" />
+<p class="img-caption"><strong>Gambar 1.</strong> Model data Penyedia Kalender.</p>
+
+<p>Seorang pengguna bisa memiliki beberapa kalender, dan kalender yang berbeda bisa dikaitkan dengan tipe akun yang berbeda (Google Calendar, Exchange, dan seterusnya).</p>
+
+<p>{@link android.provider.CalendarContract} mendefinisikan model data dari informasi yang terkait dengan kalender dan kejadian. Data ini disimpan di sejumlah tabel, yang dicantumkan di bawah ini.</p>
+
+<table>
+  <tr>
+    <th>Tabel (Kelas)</th>
+    <th>Keterangan</th>
+  </tr>
+  <tr>
+    <td><p>{@link android.provider.CalendarContract.Calendars}</p></td>
+
+    <td>Tabel ini menyimpan
+informasi khusus kalender. Tiap baris dalam tabel ini berisi data untuk
+satu kalender, seperti nama, warna, informasi sinkronisasi, dan seterusnya.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.Events}</td>
+
+    <td>Tabel ini menyimpan
+informasi khusus kejadian. Tiap baris dalam tabel ini berisi informasi untuk satu
+kejadian&mdash;misalnya, judul kejadian, lokasi, waktu mulai, waktu
+selesai, dan seterusnya. Kejadian bisa terjadi satu kali atau bisa berulang beberapa kali. Peserta,
+pengingat, dan properti perluasan disimpan dalam tabel terpisah.
+Masing-masing memiliki sebuah {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}
+yang mengacu {@link android.provider.BaseColumns#_ID} dalam tabel Events.</td>
+
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.Instances}</td>
+
+    <td>Tabel ini menyimpan
+waktu mulai dan waktu selesai setiap bentuk kejadian. Tiap baris dalam tabel ini
+mewakili satu bentuk kejadian. Untuk kejadian satu kali ada pemetaan 1:1
+antara instance dan kejadian. Untuk kejadian berulang, beberapa baris akan dibuat
+secara otomatis yang sesuai dengan beberapa kejadian itu.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.Attendees}</td>
+
+    <td>Tabel ini menyimpan
+informasi peserta (tamu) kejadian. Tiap baris mewakili satu tamu
+kejadian. Ini menetapkan tipe tamu dan respons kehadiran tamu
+untuk kejadian.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.Reminders}</td>
+
+    <td>Tabel ini menyimpan
+data peringatan/pemberitahuan. Tiap baris mewakili satu peringatan untuk sebuah kejadian. Sebuah
+kejadian bisa memiliki beberapa pengingat. Jumlah maksimum pengingat per kejadian
+ditetapkan dalam
+{@link android.provider.CalendarContract.CalendarColumns#MAX_REMINDERS},
+yang diatur oleh adaptor sinkronisasi yang
+memiliki kalender yang diberikan. Pengingat ditetapkan dalam menit sebelum kejadian
+dan memiliki metode yang menentukan cara pengguna akan diperingatkan.</td>
+  </tr>
+
+</table>
+
+<p>API Penyedia Kalender didesain agar luwes dan tangguh. Sementara itu
+, Anda perlu memberikan pengalaman pengguna akhir yang baik dan
+melindungi integritas kalender dan datanya. Untuk mencapainya, berikut ini adalah
+beberapa hal yang harus diingat saat menggunakan API ini:</p>
+
+<ul>
+
+<li><strong>Menyisipkan, memperbarui, dan menampilkan kejadian kalender.</strong> Untuk menyisipkan, mengubah, dan membaca kejadian secara langsung dari Penyedia Kalender, Anda memerlukan <a href="#manifest">izin</a> yang sesuai. Akan tetapi, jika Anda tidak sedang membuat aplikasi atau adaptor sinkronisasi kalender berfitur lengkap, maka tidak perlu meminta izin. Sebagai gantinya, Anda bisa menggunakan intent yang didukung oleh aplikasi Kalender Android untuk menyerahkan operasi baca dan tulis ke aplikasi itu. Bila menggunakan intent, aplikasi Anda akan mengirim pengguna ke aplikasi Kalender untuk melakukan operasi yang diinginkan
+dalam sebuah formulir yang sudah diisi. Setelah operasi selesai, formulir dikembalikan ke aplikasi Anda.
+Dengan mendesain aplikasi untuk melakukan operasi umum melalui Kalender,
+Anda akan memberi pengguna sebuah antarmuka pengguna yang konsisten dan tangguh. Inilah
+pendekatan yang disarankan. Untuk informasi selengkapnya, lihat <a href="#intents">Intent
+Kalender</a>.</p>
+
+
+<li><strong>Adaptor sinkronisasi.</strong> Adaptor sinkronisasi menyinkronkan data kalender
+pada perangkat pengguna dengan server atau sumber data lain. Dalam tabel
+{@link android.provider.CalendarContract.Calendars} dan
+{@link android.provider.CalendarContract.Events},
+ada kolom yang dicadangkan untuk digunakan adaptor sinkronisasi.
+Penyedia dan aplikasi tidak boleh memodifikasinya. Sebenarnya, tabel-tabel itu tidak
+terlihat kecuali jika diakses sebagai adaptor sinkronisasi. Untuk informasi selengkapnya tentang
+adaptor sinkronisasi, lihat <a href="#sync-adapter">Adaptor Sinkronisasi</a>.</li>
+
+</ul>
+
+
+<h2 id="manifest">Izin Pengguna</h2>
+
+<p>Untuk membaca data kalender, aplikasi harus menyertakan izin {@link
+android.Manifest.permission#READ_CALENDAR} dalam file manifesnya. File
+harus menyertakan izin {@link android.Manifest.permission#WRITE_CALENDAR}
+untuk menghapus, menyisipkan, atau memperbarui data kalender:</p>
+
+<pre>
+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
+&lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;...&gt;
+    &lt;uses-sdk android:minSdkVersion=&quot;14&quot; /&gt;
+    &lt;uses-permission android:name=&quot;android.permission.READ_CALENDAR&quot; /&gt;
+    &lt;uses-permission android:name=&quot;android.permission.WRITE_CALENDAR&quot; /&gt;
+    ...
+&lt;/manifest&gt;
+</pre>
+
+
+<h2 id="calendar">Tabel Kalender</h2>
+
+<p>Tabel {@link android.provider.CalendarContract.Calendars} berisi data
+untuk tiap kalender. Kolom-kolom
+berikut ini bisa ditulisi oleh aplikasi maupun <a href="#sync-adapter">adaptor sinkronisasi</a>.
+Untuk mengetahui daftar lengkap bidang-bidang yang didukung, lihat
+acuan {@link android.provider.CalendarContract.Calendars}.</p>
+<table>
+  <tr>
+    <th>Konstanta</th>
+    <th>Keterangan</th>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.Calendars#NAME}</td>
+    <td>Nama kalender.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.Calendars#CALENDAR_DISPLAY_NAME}</td>
+    <td>Nama kalender ini yang ditampilkan kepada pengguna.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.Calendars#VISIBLE}</td>
+
+    <td>Sebuah boolean yang menunjukkan apakah kalender dipilih untuk ditampilkan. Nilai
+0 menunjukkan bahwa kejadian yang terkait dengan kalender ini tidak boleh
+ditampilkan.  Nilai 1 menunjukkan bahwa kejadian yang terkait dengan kalender ini harus
+ditampilkan. Nilai ini memengaruhi pembuatan baris dalam tabel {@link
+android.provider.CalendarContract.Instances}.</td>
+
+
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.CalendarColumns#SYNC_EVENTS}</td>
+
+    <td>Sebuah boolean yang menunjukkan apakah kalender harus disinkronkan dan apakah
+kejadiannya harus disimpan pada perangkat. Nilai 0 berarti jangan menyinkronkan kalender ini atau
+simpan kejadiannya pada perangkat.  Nilai 1 berarti menyinkronkan kejadian untuk kalender ini
+dan simpan kejadiannya pada perangkat.</td>
+  </tr>
+</table>
+
+<h3 id="query">Membuat query kalender</h3>
+
+<p>Berikut ini adalah contoh yang menampilkan cara mendapatkan kalender yang dimiliki oleh
+pengguna tertentu. Untuk memudahkan, dalam contoh ini, operasi query ditampilkan dalam
+thread antarmuka pengguna ("thread utama"). Dalam praktiknya, hal ini harus dilakukan dalam
+thread asinkron, sebagai ganti pada thread utama. Untuk diskusi selengkapnya, lihat
+<a href="{@docRoot}guide/components/loaders.html">Loader</a>. Jika Anda tidak sekadar
+membaca data melainkan memodifikasinya, lihat {@link android.content.AsyncQueryHandler}.
+</p>
+
+
+<pre>
+// Projection array. Creating indices for this array instead of doing
+// dynamic lookups improves performance.
+public static final String[] EVENT_PROJECTION = new String[] {
+    Calendars._ID,                           // 0
+    Calendars.ACCOUNT_NAME,                  // 1
+    Calendars.CALENDAR_DISPLAY_NAME,         // 2
+    Calendars.OWNER_ACCOUNT                  // 3
+};
+
+// The indices for the projection array above.
+private static final int PROJECTION_ID_INDEX = 0;
+private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1;
+private static final int PROJECTION_DISPLAY_NAME_INDEX = 2;
+private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;</pre>
+
+
+<div class="sidebox-wrapper"> <div class="sidebox"> <h3>Mengapa Anda harus menyertakan
+ACCOUNT_TYPE?</h3> <p>Jika Anda membuat query pada {@link
+android.provider.CalendarContract.Calendars#ACCOUNT_NAME
+Calendars.ACCOUNT_NAME}, Anda juga harus menyertakan
+{@link android.provider.CalendarContract.Calendars#ACCOUNT_TYPE Calendars.ACCOUNT_TYPE}
+dalam pemilihan. Itu karena akun yang bersangkutan
+hanya dianggap unik mengingat <code>ACCOUNT_NAME</code> dan
+<code>ACCOUNT_TYPE</code>-nya. <code>ACCOUNT_TYPE</code> adalah string yang sesuai dengan
+autentikator akun yang digunakan bila akun didaftarkan dengan
+{@link android.accounts.AccountManager}. Ada juga sebuah tipe akun khusus yang disebut {@link
+android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} untuk kalender
+yang tidak terkait dengan akun perangkat. Akun {@link
+android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} tidak
+disinkronkan.</p> </div> </div>
+
+
+<p> Di bagian berikutnya pada contoh ini, Anda akan membuat query. Pemilihan
+akan menetapkan kriteria untuk query. Dalam contoh ini, query mencari
+kalender yang memiliki <code>ACCOUNT_NAME</code>
+"sampleuser@google.com", <code>ACCOUNT_TYPE</code>
+"com.google", dan <code>OWNER_ACCOUNT</code>
+"sampleuser@google.com". Jika Anda ingin melihat semua kalender yang
+telah ditampilkan pengguna, bukan hanya kalender yang dimiliki pengguna, hilangkan <code>OWNER_ACCOUNT</code>.
+Query tersebut akan menghasilkan objek {@link android.database.Cursor}
+yang bisa Anda gunakan untuk menyusuri set hasil yang dikembalikan oleh
+query database. Untuk diskusi selengkapnya tentang penggunaan query dalam penyedia konten,
+lihat <a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Kalender</a>.</p>
+
+
+<pre>// Run query
+Cursor cur = null;
+ContentResolver cr = getContentResolver();
+Uri uri = Calendars.CONTENT_URI;
+String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND ("
+                        + Calendars.ACCOUNT_TYPE + " = ?) AND ("
+                        + Calendars.OWNER_ACCOUNT + " = ?))";
+String[] selectionArgs = new String[] {"sampleuser@gmail.com", "com.google",
+        "sampleuser@gmail.com"};
+// Submit the query and get a Cursor object back.
+cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);</pre>
+
+<p>Bagian berikutnya ini menggunakan kursor untuk merunut set hasil. Bagian ini menggunakan
+konstanta yang disiapkan pada awal contoh ini untuk menghasilkan nilai-nilai
+bagi tiap bidang.</p>
+
+<pre>// Use the cursor to step through the returned records
+while (cur.moveToNext()) {
+    long calID = 0;
+    String displayName = null;
+    String accountName = null;
+    String ownerName = null;
+
+    // Get the field values
+    calID = cur.getLong(PROJECTION_ID_INDEX);
+    displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
+    accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
+    ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);
+
+    // Do something with the values...
+
+   ...
+}
+</pre>
+
+<h3 id="modify-calendar">Memodifikasi kalender</h3>
+
+<p>Untuk melakukan pembaruan kalender, Anda bisa menyediakan {@link
+android.provider.BaseColumns#_ID} kalender itu baik sebagai ID yang ditambahkan ke
+URI
+
+({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()})
+atau sebagai item pemilihan pertama. Pemilihan
+harus diawali dengan <code>&quot;_id=?&quot;</code>, dan
+<code>selectionArg</code> pertama harus berupa {@link
+android.provider.BaseColumns#_ID} kalender.
+Anda juga bisa melakukan pembaruan dengan menuliskan kode ID dalam URI. Contoh ini mengubah
+nama tampilan kalender dengan pendekatan
+({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()})
+:</p>
+
+<pre>private static final String DEBUG_TAG = "MyActivity";
+...
+long calID = 2;
+ContentValues values = new ContentValues();
+// The new display name for the calendar
+values.put(Calendars.CALENDAR_DISPLAY_NAME, &quot;Trevor's Calendar&quot;);
+Uri updateUri = ContentUris.withAppendedId(Calendars.CONTENT_URI, calID);
+int rows = getContentResolver().update(updateUri, values, null, null);
+Log.i(DEBUG_TAG, &quot;Rows updated: &quot; + rows);</pre>
+
+<h3 id="insert-calendar">Menyisipkan kalender</h2>
+
+<p>Kalender didesain untuk dikelola terutama oleh sebuah adaptor sinkronisasi, sehingga Anda
+hanya boleh menyisipkan kalender baru sebagai adaptor sinkronisasi. Biasanya,
+aplikasi hanya bisa membuat perubahan semu pada kalender, misalnya mengubah nama tampilan. Jika
+perlu membuat sebuah kalender lokal, aplikasi bisa melakukannya dengan melakukan
+penyisipan kalender sebagai adaptor sinkronisasi, menggunakan {@link
+android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} dari {@link
+android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL}.
+{@link android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL}
+adalah sebuah tipe akun khusus untuk kalender yang tidak
+terkait dengan akun perangkat. Kalender tipe ini tidak disinkronkan dengan server. Untuk
+diskusi tentang adaptor sinkronisasi, lihat <a href="#sync-adapter">Adaptor Sinkronisasi</a>.</p>
+
+<h2 id="events">Tabel Events</h2>
+
+<p>Tabel {@link android.provider.CalendarContract.Events} berisi detail
+untuk tiap kejadian. Untuk menambah, memperbarui, atau menghapus kejadian, aplikasi harus
+menyertakan izin {@link android.Manifest.permission#WRITE_CALENDAR} dalam
+<a href="#manifest">file manifesnya</a>.</p>
+
+<p>Kolom-kolom Events berikut ini bisa ditulis oleh aplikasi maupun
+adaptor sinkronisasi. Untuk mengetahui daftar lengkap bidang-bidang yang didukung, lihat acuan {@link
+android.provider.CalendarContract.Events}.</p>
+
+<table>
+  <tr>
+    <th>Konstanta</th>
+    <th>Keterangan</th>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#CALENDAR_ID}</td>
+    <td>{@link android.provider.BaseColumns#_ID} kalender yang dimiliki kejadian.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#ORGANIZER}</td>
+    <td>Email pengatur (pemilik) kejadian.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#TITLE}</td>
+    <td>Judul kejadian.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION}</td>
+    <td>Tempat kejadian. </td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#DESCRIPTION}</td>
+    <td>Keterangan kejadian.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#DTSTART}</td>
+    <td>Waktu mulai kejadian dalam milidetik UTC sejak waktu patokan. </td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#DTEND}</td>
+    <td>Waktu selesai kejadian dalam milidetik UTC sejak waktu patokan. </td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_TIMEZONE}</td>
+    <td>Zona waktu kejadian.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_END_TIMEZONE}</td>
+    <td>Zona waktu untuk waktu selesai kejadian.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#DURATION}</td>
+
+    <td>Durasi kejadian dalam format <a href="http://tools.ietf.org/html/rfc5545#section-3.8.2.5">RFC5545</a>.
+Misalnya, nilai <code>&quot;PT1H&quot;</code> menyatakan bahwa kejadian
+akan berlangsung satu jam, dan nilai <code>&quot;P2W&quot;</code> menunjukkan
+durasi 2 minggu. </td>
+
+
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#ALL_DAY}</td>
+
+    <td>Nilai 1 menunjukkan kejadian ini memakan waktu sehari penuh, seperti yang didefinisikan oleh
+zona waktu lokal. Nilai 0 menunjukkan kejadian adalah kejadian biasa yang mungkin dimulai
+dan selesai pada sembarang waktu selama suatu hari.</td>
+
+
+  </tr>
+
+
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#RRULE}</td>
+
+    <td>Aturan perulangan untuk format kejadian. Misalnya,
+<code>&quot;FREQ=WEEKLY;COUNT=10;WKST=SU&quot;</code>. Anda bisa menemukan
+contoh selengkapnya <a href="http://tools.ietf.org/html/rfc5545#section-3.8.5.3">di sini</a>.</td>
+
+  </tr>
+
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#RDATE}</td>
+    <td>Tanggal perulangan kejadian.
+    Anda biasanya menggunakan {@link android.provider.CalendarContract.EventsColumns#RDATE}
+    bersama dengan {@link android.provider.CalendarContract.EventsColumns#RRULE}
+    untuk mendefinisikan satu set agregat
+kejadian berulang. Untuk diskusi selengkapnya, lihat <a href="http://tools.ietf.org/html/rfc5545#section-3.8.5.2">Spesifikasi RFC5545</a>.</td>
+</tr>
+
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#AVAILABILITY}</td>
+
+    <td>Jika kejadian ini dihitung sebagai waktu sibuk atau waktu bebas yang bisa
+dijadwalkan. </td>
+
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_MODIFY}</td>
+    <td>Apakah tamu bisa memodifikasi kejadian atau tidak. </td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_INVITE_OTHERS}</td>
+    <td>Apakah tamu bisa mengundang tamu lain atau tidak. </td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_SEE_GUESTS}</td>
+    <td>Apakah tamu bisa membaca daftar peserta atau tidak.</td>
+  </tr>
+</table>
+
+<h3 id="add-event">Menambahkan Kejadian</h3>
+
+<p>Bila aplikasi Anda menyisipkan kejadian baru, sebaiknya Anda menggunakan
+Intent {@link android.content.Intent#ACTION_INSERT INSERT}, seperti dijelaskan dalam <a href="#intent-insert">Menggunakan intent untuk menyisipkan kejadian</a>. Akan tetapi, jika
+perlu, Anda bisa menyisipkan kejadian secara langsung. Bagian ini menjelaskan
+caranya.</p>
+
+
+<p>Berikut ini adalah aturan untuk menyisipkan kejadian baru: </p>
+<ul>
+
+  <li>Anda harus menyertakan {@link
+android.provider.CalendarContract.EventsColumns#CALENDAR_ID} dan {@link
+android.provider.CalendarContract.EventsColumns#DTSTART}.</li>
+
+<li>Anda harus menyertakan {@link
+android.provider.CalendarContract.EventsColumns#EVENT_TIMEZONE}. Untuk mendapatkan daftar
+ID zona waktu yang diinstal pada sistem, gunakan {@link
+java.util.TimeZone#getAvailableIDs()}. Perhatikan bahwa aturan ini tidak berlaku jika
+Anda menyisipkan kejadian melalui Intent {@link
+android.content.Intent#ACTION_INSERT INSERT}, yang dijelaskan dalam <a href="#intent-insert">Menggunakan intent untuk menyisipkan kejadian</a>&mdash;dalam
+skenario itu, sebuah zona waktu default akan diberikan.</li>
+
+  <li>Untuk kejadian tidak-berulang, Anda harus menyertakan {@link
+android.provider.CalendarContract.EventsColumns#DTEND}. </li>
+
+
+  <li>Untuk kejadian berulang, Anda harus menyertakan sebuah {@link
+android.provider.CalendarContract.EventsColumns#DURATION} selain {@link
+android.provider.CalendarContract.EventsColumns#RRULE} atau {@link
+android.provider.CalendarContract.EventsColumns#RDATE}. Perhatikan bahwa aturan ini tidak berlaku jika
+Anda menyisipkan kejadian melalui Intent {@link
+android.content.Intent#ACTION_INSERT INSERT}, yang dijelaskan dalam <a href="#intent-insert">Menggunakan intent untuk menyisipkan kejadian</a>&mdash;dalam
+skenario itu, Anda bisa menggunakan {@link
+android.provider.CalendarContract.EventsColumns#RRULE} bersama {@link android.provider.CalendarContract.EventsColumns#DTSTART} dan {@link android.provider.CalendarContract.EventsColumns#DTEND}, dan aplikasi Calendar
+akan mengubahnya menjadi durasi secara otomatis.</li>
+
+</ul>
+
+<p>Berikut ini adalah contoh penyisipan kejadian. Penyisipan ini dilakukan dalam thread UI
+demi kemudahan. Dalam praktiknya, penyisipan dan pembaruan harus dilakukan di
+thread asinkron untuk memindahkan tindakan ke dalam thread latar belakang. Untuk
+informasi selengkapnya, lihat {@link android.content.AsyncQueryHandler}.</p>
+
+
+<pre>
+long calID = 3;
+long startMillis = 0;
+long endMillis = 0;
+Calendar beginTime = Calendar.getInstance();
+beginTime.set(2012, 9, 14, 7, 30);
+startMillis = beginTime.getTimeInMillis();
+Calendar endTime = Calendar.getInstance();
+endTime.set(2012, 9, 14, 8, 45);
+endMillis = endTime.getTimeInMillis();
+...
+
+ContentResolver cr = getContentResolver();
+ContentValues values = new ContentValues();
+values.put(Events.DTSTART, startMillis);
+values.put(Events.DTEND, endMillis);
+values.put(Events.TITLE, &quot;Jazzercise&quot;);
+values.put(Events.DESCRIPTION, &quot;Group workout&quot;);
+values.put(Events.CALENDAR_ID, calID);
+values.put(Events.EVENT_TIMEZONE, "America/Los_Angeles");
+Uri uri = cr.insert(Events.CONTENT_URI, values);
+
+// get the event ID that is the last element in the Uri
+long eventID = Long.parseLong(uri.getLastPathSegment());
+//
+// ... do something with event ID
+//
+//</pre>
+
+<p class="note"><strong>Catatan:</strong> Perhatikan cara contoh ini menangkap ID kejadian
+setelah kejadian dibuat. Inilah cara termudah untuk mendapatkan ID kejadian. Anda akan sering
+memerlukan ID kejadian untuk melakukan operasi kalender lainnya&mdash;misalnya, untuk menambahkan
+peserta atau pengingat ke kejadian.</p>
+
+
+<h3 id="update-event">Memperbarui Kejadian</h3>
+
+<p>Bila aplikasi Anda ingin memperbolehkan pengguna mengedit kejadian, sebaiknya
+gunakan Intent {@link android.content.Intent#ACTION_EDIT EDIT}, seperti
+dijelaskan dalam <a href="#intent-edit">Menggunakan intent untuk mengedit kejadian</a>.
+Akan tetapi, jika perlu, Anda bisa mengedit kejadian secara langsung. Untuk melakukan pembaruan
+suatu kejadian, Anda bisa memberikan <code>_ID</code>
+kejadian itu sebagai ID yang ditambahkan ke URI ({@link
+android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()})
+atau sebagai item pemilihan pertama.
+Pemilihan harus dimulai dengan <code>&quot;_id=?&quot;</code>, dan
+<code>selectionArg</code> yang pertama harus berupa <code>_ID</code> kejadian. Anda juga bisa
+melakukan pembaruan dengan menggunakan pemilihan tanpa ID. Berikut ini adalah contoh pembaruan
+kejadian. Contoh ini mengubah judul kejadian dengan pendekatan
+{@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}
+:</p>
+
+
+<pre>private static final String DEBUG_TAG = "MyActivity";
+...
+long eventID = 188;
+...
+ContentResolver cr = getContentResolver();
+ContentValues values = new ContentValues();
+Uri updateUri = null;
+// The new title for the event
+values.put(Events.TITLE, &quot;Kickboxing&quot;);
+updateUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
+int rows = getContentResolver().update(updateUri, values, null, null);
+Log.i(DEBUG_TAG, &quot;Rows updated: &quot; + rows);  </pre>
+
+<h3 id="delete-event">Menghapus Kejadian</h3>
+
+<p>Anda bisa menghapus kejadian dengan {@link
+android.provider.BaseColumns#_ID} sebagai ID yang ditambahkan pada URI, atau dengan
+pemilihan standar. Jika Anda menggunakan ID yang ditambahkan, Anda tidak bisa melakukan pemilihan.
+Ada dua versi penghapusan: sebagai aplikasi dan sebagai adaptor sinkronisasi. Penghapusan
+aplikasi mengatur kolom yang <em>dihapus</em> ke 1. Flag ini yang memberi tahu
+adaptor sinkronisasi bahwa baris telah dihapus dan bahwa penghapusan ini harus
+diberitahukan ke server. Penghapusan adaptor sinkronisasi menghapus kejadian dari
+database bersama semua data terkaitnya. Berikut ini adalah contoh aplikasi
+yang menghapus kejadian melalui {@link android.provider.BaseColumns#_ID}-nya:</p>
+
+
+<pre>private static final String DEBUG_TAG = "MyActivity";
+...
+long eventID = 201;
+...
+ContentResolver cr = getContentResolver();
+ContentValues values = new ContentValues();
+Uri deleteUri = null;
+deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
+int rows = getContentResolver().delete(deleteUri, null, null);
+Log.i(DEBUG_TAG, &quot;Rows deleted: &quot; + rows);
+</pre>
+
+<h2 id="attendees">Tabel Peserta</h2>
+
+<p>Tiap baris tabel {@link android.provider.CalendarContract.Attendees}
+mewakili satu peserta atau tamu dari sebuah kejadian. Memanggil
+{@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()}
+akan menghasilkan daftar peserta untuk
+kejadian dengan {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} yang diberikan.
+{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} ini
+harus cocok dengan {@link
+android.provider.BaseColumns#_ID} kejadian tertentu.</p>
+
+<p>Tabel berikut mencantumkan
+bidang-bidang yang bisa ditulis. Saat menyisipkan peserta baru, Anda harus menyertakan semuanya
+kecuali <code>ATTENDEE_NAME</code>.
+</p>
+
+
+<table>
+  <tr>
+    <th>Konstanta</th>
+    <th>Keterangan</th>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}</td>
+    <td>ID kejadian.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_NAME}</td>
+    <td>Nama peserta.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_EMAIL}</td>
+    <td>Alamat email peserta.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_RELATIONSHIP}</td>
+    <td><p>Hubungan peserta dengan kejadian. Salah satu dari:</p>
+      <ul>
+        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_ATTENDEE}</li>
+        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_NONE}</li>
+        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_ORGANIZER}</li>
+        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_PERFORMER}</li>
+        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_SPEAKER}</li>
+    </ul>
+    </td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_TYPE}</td>
+    <td><p>Tipe peserta. Salah satu dari: </p>
+      <ul>
+        <li>{@link android.provider.CalendarContract.AttendeesColumns#TYPE_REQUIRED}</li>
+        <li>{@link android.provider.CalendarContract.AttendeesColumns#TYPE_OPTIONAL}</li>
+    </ul></td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS}</td>
+    <td><p>Status kehadiran peserta. Salah satu dari:</p>
+      <ul>
+        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_ACCEPTED}</li>
+        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_DECLINED}</li>
+        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_INVITED}</li>
+        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_NONE}</li>
+        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_TENTATIVE}</li>
+    </ul></td>
+  </tr>
+</table>
+
+<h3 id="add-attendees">Menambahkan Peserta</h3>
+
+<p>Berikut ini adalah contoh yang menambahkan satu peserta ke kejadian. Perhatikan bahwa
+{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}
+diperlukan:</p>
+
+<pre>
+long eventID = 202;
+...
+ContentResolver cr = getContentResolver();
+ContentValues values = new ContentValues();
+values.put(Attendees.ATTENDEE_NAME, &quot;Trevor&quot;);
+values.put(Attendees.ATTENDEE_EMAIL, &quot;trevor@example.com&quot;);
+values.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
+values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_OPTIONAL);
+values.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_INVITED);
+values.put(Attendees.EVENT_ID, eventID);
+Uri uri = cr.insert(Attendees.CONTENT_URI, values);
+</pre>
+
+<h2 id="reminders">Tabel Pengingat</h2>
+
+<p>Tiap baris tabel {@link android.provider.CalendarContract.Reminders}
+mewakili satu pengingat untuk sebuah kejadian. Memanggil
+{@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} akan menghasilkan daftar pengingat untuk
+kejadian dengan
+{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} yang diberikan.</p>
+
+
+<p>Tabel berikut mencantumkan bidang-bidang yang bisa ditulis untuk pengingat. Semua bidang harus
+disertakan saat menyisipkan pengingat baru. Perhatikan bahwa adaptor sinkronisasi menetapkan
+tipe pengingat yang didukungnya dalam tabel {@link
+android.provider.CalendarContract.Calendars}. Lihat
+{@link android.provider.CalendarContract.CalendarColumns#ALLOWED_REMINDERS}
+untuk detailnya.</p>
+
+
+<table>
+  <tr>
+    <th>Konstanta</th>
+    <th>Keterangan</th>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.RemindersColumns#EVENT_ID}</td>
+    <td>ID kejadian.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.RemindersColumns#MINUTES}</td>
+    <td>Menit yang ditunggu untuk memicu kejadian pengingat.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.RemindersColumns#METHOD}</td>
+    <td><p>Metode alarm, seperti yang diatur pada server. Salah satu dari:</p>
+      <ul>
+        <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_ALERT}</li>
+        <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_DEFAULT}</li>
+        <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_EMAIL}</li>
+        <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_SMS}</li>
+    </ul></td>
+  </tr>
+</table>
+
+<h3 id="add-reminders">Menambahkan Pengingat</h3>
+
+<p>Contoh ini menambahkan pengingat ke kejadian. Pengingat dipicu 15
+menit sebelum kejadian.</p>
+<pre>
+long eventID = 221;
+...
+ContentResolver cr = getContentResolver();
+ContentValues values = new ContentValues();
+values.put(Reminders.MINUTES, 15);
+values.put(Reminders.EVENT_ID, eventID);
+values.put(Reminders.METHOD, Reminders.METHOD_ALERT);
+Uri uri = cr.insert(Reminders.CONTENT_URI, values);</pre>
+
+<h2 id="instances">Tabel Instances</h2>
+
+<p>Tabel
+{@link android.provider.CalendarContract.Instances} menyimpan
+waktu mulai dan waktu selesai kejadian. Tiap baris dalam tabel ini
+mewakili satu bentuk kejadian. Tabel instance tidak bisa ditulis dan hanya
+menyediakan sebuah cara untuk membuat query kejadian. </p>
+
+<p>Tabel berikut mencantumkan beberapa bidang yang bisa Anda query untuk suatu instance. Perhatikan
+bahwa zona waktu didefinisikan oleh
+{@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_TYPE}
+dan
+{@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_INSTANCES}.</p>
+
+
+<table>
+  <tr>
+    <th>Konstanta</th>
+    <th>Keterangan</th>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.Instances#BEGIN}</td>
+    <td>Waktu mulai instance, dalam milidetik UTC.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.Instances#END}</td>
+    <td>Waktu selesai instance, dalam milidetik UTC.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.Instances#END_DAY}</td>
+
+    <td>Hari selesai Julian dari instance, relatif terhadap
+zona waktu Kalender.
+
+</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.Instances#END_MINUTE}</td>
+
+    <td>Menit selesai dari instance yang diukur dari tengah malam di zona waktu
+Kalender.</td>
+
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.Instances#EVENT_ID}</td>
+    <td>Kejadian <code>_ID</code> untuk instance ini.</td>
+  </tr>
+    <tr>
+    <td>{@link android.provider.CalendarContract.Instances#START_DAY}</td>
+    <td>Hari mulai Julian dari instance, relatif terhadap zona waktu Kalender.
+ </td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.Instances#START_MINUTE}</td>
+
+    <td>Menit mulai dari instance yang diukur dari tengah malam, relatif terhadap
+zona waktu Kalender.
+</td>
+
+  </tr>
+
+</table>
+
+<h3 id="query-instances">Membuat query tabel Instance</h3>
+
+<p>Untuk membuat query tabel Instances, Anda perlu menetapkan rentang waktu query
+dalam URI. Dalam contoh ini, {@link android.provider.CalendarContract.Instances}
+mendapatkan akses ke bidang {@link
+android.provider.CalendarContract.EventsColumns#TITLE} melalui
+implementasi antarmuka {@link android.provider.CalendarContract.EventsColumns}-nya.
+Dengan kata lain, {@link
+android.provider.CalendarContract.EventsColumns#TITLE} dihasilkan melalui
+tampilan database, bukan melalui query terhadap tabel {@link
+android.provider.CalendarContract.Instances} mentah.</p>
+
+<pre>
+private static final String DEBUG_TAG = "MyActivity";
+public static final String[] INSTANCE_PROJECTION = new String[] {
+    Instances.EVENT_ID,      // 0
+    Instances.BEGIN,         // 1
+    Instances.TITLE          // 2
+  };
+
+// The indices for the projection array above.
+private static final int PROJECTION_ID_INDEX = 0;
+private static final int PROJECTION_BEGIN_INDEX = 1;
+private static final int PROJECTION_TITLE_INDEX = 2;
+...
+
+// Specify the date range you want to search for recurring
+// event instances
+Calendar beginTime = Calendar.getInstance();
+beginTime.set(2011, 9, 23, 8, 0);
+long startMillis = beginTime.getTimeInMillis();
+Calendar endTime = Calendar.getInstance();
+endTime.set(2011, 10, 24, 8, 0);
+long endMillis = endTime.getTimeInMillis();
+
+Cursor cur = null;
+ContentResolver cr = getContentResolver();
+
+// The ID of the recurring event whose instances you are searching
+// for in the Instances table
+String selection = Instances.EVENT_ID + " = ?";
+String[] selectionArgs = new String[] {"207"};
+
+// Construct the query with the desired date range.
+Uri.Builder builder = Instances.CONTENT_URI.buildUpon();
+ContentUris.appendId(builder, startMillis);
+ContentUris.appendId(builder, endMillis);
+
+// Submit the query
+cur =  cr.query(builder.build(),
+    INSTANCE_PROJECTION,
+    selection,
+    selectionArgs,
+    null);
+
+while (cur.moveToNext()) {
+    String title = null;
+    long eventID = 0;
+    long beginVal = 0;
+
+    // Get the field values
+    eventID = cur.getLong(PROJECTION_ID_INDEX);
+    beginVal = cur.getLong(PROJECTION_BEGIN_INDEX);
+    title = cur.getString(PROJECTION_TITLE_INDEX);
+
+    // Do something with the values.
+    Log.i(DEBUG_TAG, "Event:  " + title);
+    Calendar calendar = Calendar.getInstance();
+    calendar.setTimeInMillis(beginVal);
+    DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
+    Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime()));
+    }
+ }</pre>
+
+<h2 id="intents">Intent Kalender</h2>
+<p>Aplikasi Anda tidak memerlukan <a href="#manifest">izin</a> untuk membaca dan menulis data kalender. Sebagai gantinya, aplikasi bisa menggunakan intent yang didukung oleh aplikasi Kalender Android untuk menyerahkan operasi baca dan tulis ke aplikasi itu. Tabel berikut mencantumkan intent yang didukung oleh Penyedia Kalender:</p>
+<table>
+  <tr>
+    <th>Tindakan</th>
+    <th>URI</th>
+
+    <th>Keterangan</th>
+    <th>Ekstra</th>
+  </tr>
+  <tr>
+    <td><br>
+    {@link android.content.Intent#ACTION_VIEW VIEW} <br></td>
+    <td><p><code>content://com.android.calendar/time/&lt;ms_since_epoch&gt;</code></p>
+    Anda juga bisa mengacu ke URI dengan
+{@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI}.
+Untuk contoh yang menggunakan intent ini, lihat <a href="{@docRoot}guide/topics/providers/calendar-provider.html#intent-view">Menggunakan intent untuk menampilkan data kalender</a>.
+
+    </td>
+    <td>Membuka kalender pada waktu yang ditetapkan oleh <code>&lt;ms_since_epoch&gt;</code>.</td>
+    <td>Tidak ada.</td>
+  </tr>
+  <tr>
+    <td><p>{@link android.content.Intent#ACTION_VIEW VIEW} </p>
+
+     </td>
+    <td><p><code>content://com.android.calendar/events/&lt;event_id&gt;</code></p>
+
+    Anda juga bisa mengacu ke URI dengan
+{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}.
+Untuk contoh yang menggunakan intent ini, lihat <a href="{@docRoot}guide/topics/providers/calendar-provider.html#intent-view">Menggunakan intent untuk menampilkan data kalender</a>.
+
+    </td>
+    <td>Menampilkan kejadian yang ditetapkan oleh <code>&lt;event_id&gt;</code>.</td>
+
+    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME}<br>
+      <br>
+      <br>
+    {@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME}</td>
+  </tr>
+
+  <tr>
+    <td>{@link android.content.Intent#ACTION_EDIT EDIT} </td>
+    <td><p><code>content://com.android.calendar/events/&lt;event_id&gt;</code></p>
+
+  Anda juga bisa mengacu ke URI dengan
+{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}.
+Untuk contoh penggunaan intent ini, lihat <a href="{@docRoot}guide/topics/providers/calendar-provider.html#intent-edit">Menggunakan intent untuk mengedit kejadian</a>.
+
+
+    </td>
+    <td>Mengedit kejadian yang ditetapkan oleh <code>&lt;event_id&gt;</code>.</td>
+
+    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME}<br>
+      <br>
+      <br>
+    {@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME}</td>
+  </tr>
+
+  <tr>
+    <td>{@link android.content.Intent#ACTION_EDIT EDIT} <br>
+    <br>
+    {@link android.content.Intent#ACTION_INSERT INSERT} </td>
+    <td><p><code>content://com.android.calendar/events</code></p>
+
+   Anda juga bisa mengacu ke URI dengan
+{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}.
+Untuk contoh penggunaan intent ini, lihat <a href="{@docRoot}guide/topics/providers/calendar-provider.html#intent-insert">Menggunakan intent untuk menyisipkan kejadian</a>.
+
+    </td>
+
+    <td>Membuat sebuah kejadian.</td>
+    <td>Ekstra apa saja yang tercantum dalam tabel di bawah.</td>
+  </tr>
+</table>
+
+<p>Tabel berikut mencantumkan ekstra intent yang didukung oleh Penyedia Kalender:
+</p>
+<table>
+  <tr>
+    <th>Ekstra Intent</th>
+    <th>Keterangan</th>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#TITLE Events.TITLE}</td>
+    <td>Nama kejadian.</td>
+  </tr>
+  <tr>
+
+    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME
+CalendarContract.EXTRA_EVENT_BEGIN_TIME}</td>
+    <td>Waktu mulai kejadian dalam milidetik sejak waktu patokan.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME
+CalendarContract.EXTRA_EVENT_END_TIME}</td>
+
+    <td>Waktu selesai kejadian dalam milidetik sejak waktu patokan.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_ALL_DAY
+CalendarContract.EXTRA_EVENT_ALL_DAY}</td>
+
+    <td>Sebuah boolean yang menunjukkan bahwa kejadian sehari penuh. Nilai bisa
+<code>true</code> atau <code>false</code>.</td> </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION
+Events.EVENT_LOCATION}</td>
+
+    <td>Lokasi kejadian.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#DESCRIPTION
+Events.DESCRIPTION}</td>
+
+    <td>Keterangan kejadian.</td>
+  </tr>
+  <tr>
+    <td>
+    {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL}</td>
+    <td>Alamat email mereka yang harus diundang berupa daftar yang dipisahkan koma.</td>
+  </tr>
+  <tr>
+    <td>
+    {@link android.provider.CalendarContract.EventsColumns#RRULE Events.RRULE}</td>
+    <td>Aturan perulangan kejadian.</td>
+  </tr>
+  <tr>
+    <td>
+    {@link android.provider.CalendarContract.EventsColumns#ACCESS_LEVEL
+Events.ACCESS_LEVEL}</td>
+
+    <td>Apakah kejadian bersifat privat atau publik.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.CalendarContract.EventsColumns#AVAILABILITY
+Events.AVAILABILITY}</td>
+
+    <td>Jika kejadian ini dihitung sebagai waktu sibuk atau waktu bebas yang bisa dijadwalkan.</td>
+
+</table>
+<p>Bagian berikut menjelaskan cara menggunakan semua intent ini.</p>
+
+
+<h3 id="intent-insert">Menggunakan intent untuk menyisipkan kejadian</h3>
+
+<p>Penggunaan Intent {@link android.content.Intent#ACTION_INSERT INSERT}
+akan memungkinkan aplikasi Anda menyerahkan tugas penyisipan kejadian ke Kalender itu sendiri.
+Dengan pendekatan ini, aplikasi Anda bahkan tidak perlu menyertakan izin {@link
+android.Manifest.permission#WRITE_CALENDAR} dalam <a href="#manifest">file manifesnya</a>.</p>
+
+
+<p>Bila pengguna menjalankan aplikasi yang menggunakan pendekatan ini, aplikasi akan mengirim
+izin ke Kalender untuk menyelesaikan penambahan kejadian. Intent {@link
+android.content.Intent#ACTION_INSERT INSERT} menggunakan bidang-bidang ekstra
+untuk mengisi formulir lebih dahulu dengan detail kejadian dalam Kalender. Pengguna nanti bisa
+membatalkan kejadian, mengedit formulir sebagaimana diperlukan, atau menyimpan kejadian ke
+kalender mereka.</p>
+
+
+
+<p>Berikut ini adalah cuplikan kode yang menjadwalkan kejadian pada tanggal 19 Januari 2012, yang berjalan
+dari 7:30 pagi hingga 8:30 pagi Perhatikan hal-hal berikut tentang cuplikan kode ini:</p>
+
+<ul>
+  <li>Cuplikan kode ini menetapkan {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}
+  sebagai URI-nya.</li>
+
+  <li>Cuplikan kode ini menggunakan bidang-bidang ekstra {@link
+android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME
+CalendarContract.EXTRA_EVENT_BEGIN_TIME} dan {@link
+android.provider.CalendarContract#EXTRA_EVENT_END_TIME
+CalendarContract.EXTRA_EVENT_END_TIME} untuk mengisi dahulu formulir
+dengan waktu kejadian. Nilai-nilai untuk waktu ini harus dalam milidetik UTC
+sejak waktu patokan.</li>
+
+  <li>Cuplikan kode ini menggunakan bidang ekstra {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL}
+untuk memberikan daftar undangan yang dipisah koma, yang ditetapkan melalui alamat email.</li>
+
+</ul>
+<pre>
+Calendar beginTime = Calendar.getInstance();
+beginTime.set(2012, 0, 19, 7, 30);
+Calendar endTime = Calendar.getInstance();
+endTime.set(2012, 0, 19, 8, 30);
+Intent intent = new Intent(Intent.ACTION_INSERT)
+        .setData(Events.CONTENT_URI)
+        .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis())
+        .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis())
+        .putExtra(Events.TITLE, &quot;Yoga&quot;)
+        .putExtra(Events.DESCRIPTION, &quot;Group class&quot;)
+        .putExtra(Events.EVENT_LOCATION, &quot;The gym&quot;)
+        .putExtra(Events.AVAILABILITY, Events.AVAILABILITY_BUSY)
+        .putExtra(Intent.EXTRA_EMAIL, &quot;rowan@example.com,trevor@example.com&quot;);
+startActivity(intent);
+</pre>
+
+<h3 id="intent-edit">Menggunakan intent untuk mengedit kejadian</h3>
+
+<p>Anda bisa memperbarui kejadian secara langsung, seperti dijelaskan dalam <a href="#update-event">Memperbarui kejadian</a>. Namun penggunaan Intent {@link
+android.content.Intent#ACTION_EDIT EDIT} memungkinkan aplikasi yang
+tidak memiliki izin untuk menyerahkan pengeditan kejadian ke aplikasi Kalender.
+Bila pengguna selesai mengedit kejadian dalam Kalender, pengguna akan dikembalikan ke
+aplikasi semula.</p> <p>Berikut ini adalah contoh intent yang mengatur
+judul baru bagi kejadian yang ditetapkan dan memungkinkan pengguna mengedit kejadian dalam Kalender.</p>
+
+
+<pre>long eventID = 208;
+Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
+Intent intent = new Intent(Intent.ACTION_EDIT)
+    .setData(uri)
+    .putExtra(Events.TITLE, &quot;My New Title&quot;);
+startActivity(intent);</pre>
+
+<h3 id="intent-view">Menggunakan intent untuk menampilkan data kalender</h3>
+<p>Penyedia Kalender menyediakan dua cara menggunakan Intent {@link android.content.Intent#ACTION_VIEW VIEW}:</p>
+<ul>
+  <li>Untuk membuka Kalender pada tanggal tertentu.</li>
+  <li>Untuk menampilkan sebuah kejadian.</li>
+
+</ul>
+<p>Berikut ini adalah contoh yang menampilkan cara membuka Kalender pada tanggal tertentu:</p>
+<pre>// A date-time specified in milliseconds since the epoch.
+long startMillis;
+...
+Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
+builder.appendPath(&quot;time&quot;);
+ContentUris.appendId(builder, startMillis);
+Intent intent = new Intent(Intent.ACTION_VIEW)
+    .setData(builder.build());
+startActivity(intent);</pre>
+
+<p>Berikut ini adalah contoh yang menampilkan cara membuka kejadian untuk menampilkan:</p>
+<pre>long eventID = 208;
+...
+Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
+Intent intent = new Intent(Intent.ACTION_VIEW)
+   .setData(uri);
+startActivity(intent);
+</pre>
+
+
+<h2 id="sync-adapter">Adaptor Sinkronisasi</h2>
+
+
+<p>Hanya ada perbedaan kecil dalam cara aplikasi dan adaptor sinkronisasi
+mengakses Penyedia Kalender:</p>
+
+<ul>
+  <li>Adaptor sinkronisasi perlu menetapkan bahwa dirinya sebuah adaptor sinkronisasi dengan mengatur {@link android.provider.CalendarContract#CALLER_IS_SYNCADAPTER} ke <code>true</code>.</li>
+
+
+  <li>Adaptor sinkronisasi perlu memberikan {@link
+android.provider.CalendarContract.SyncColumns#ACCOUNT_NAME} dan {@link
+android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} sebagai parameter query dalam URI. </li>
+
+  <li>Adaptor sinkronisasi memiliki akses tulis ke lebih banyak kolom daripada aplikasi atau widget.
+  Misalnya, aplikasi hanya bisa mengubah sedikit karakteristik kalender,
+  misalnya nama, nama tampilan, pengaturan visibilitas, dan apakah kalender
+  disinkronkan atau tidak. Sebagai perbandingan, adaptor sinkronisasi bisa mengakses bukan hanya kolom-kolom itu, namun banyak kolom lainnya,
+  misalnya warna kalender, zona waktu, tingkat akses, lokasi, dan seterusnya.
+Akan tetapi, adaptor sinkronisasi dibatasi pada <code>ACCOUNT_NAME</code> dan
+<code>ACCOUNT_TYPE</code> yang ditetapkannya.</li> </ul>
+
+<p>Berikut ini adalah metode pembantu yang bisa Anda gunakan untuk menghasilkan URI bagi penggunaan dengan adaptor sinkronisasi:</p>
+<pre> static Uri asSyncAdapter(Uri uri, String account, String accountType) {
+    return uri.buildUpon()
+        .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,&quot;true&quot;)
+        .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
+        .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
+ }
+</pre>
+<p>Untuk contoh implementasi adaptor sinkronisasi (yang tidak terkait secara khusus dengan Kalender), lihat
+<a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">SampleSyncAdapter</a>.
diff --git a/docs/html-intl/intl/id/guide/topics/providers/contacts-provider.jd b/docs/html-intl/intl/id/guide/topics/providers/contacts-provider.jd
new file mode 100644
index 0000000..994c56b
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/providers/contacts-provider.jd
@@ -0,0 +1,2356 @@
+page.title=Penyedia Kontak
+@jd:body
+<div id="qv-wrapper">
+<div id="qv">
+<h2>Tampilan Cepat</h2>
+<ul>
+    <li>Repository informasi Android tentang orang.</li>
+    <li>
+        Sinkronisasi dengan web.
+    </li>
+    <li>
+        Mengintegrasikan data aliran sosial.
+    </li>
+</ul>
+<h2>Dalam dokumen ini</h2>
+<ol>
+    <li>
+        <a href="#InformationTypes">Organisasi Penyedia Kontak</a>
+    </li>
+    <li>
+        <a href="#RawContactBasics">Kontak mentah</a>
+    </li>
+    <li>
+        <a href="#DataBasics">Data</a>
+    </li>
+    <li>
+        <a href="#ContactBasics">Kontak</a>
+    </li>
+    <li>
+        <a href="#Sources">Data Dari Adaptor Sinkronisasi</a>
+    </li>
+    <li>
+        <a href="#Permissions">Izin yang Diperlukan</a>
+    </li>
+    <li>
+        <a href="#UserProfile">Profil Pengguna</a>
+    </li>
+    <li>
+        <a href="#ContactsProviderMetadata">Metadata Penyedia Kontak</a>
+    </li>
+    <li>
+        <a href="#Access">Akses Penyedia Kontak</a>
+    <li>
+    </li>
+    <li>
+        <a href="#SyncAdapters">Adaptor Sinkronisasi Penyedia Kontak</a>
+    </li>
+    <li>
+        <a href="#SocialStream">Data Aliran Sosial</a>
+    </li>
+    <li>
+        <a href="#AdditionalFeatures">Fitur Tambahan Penyedia Kontak</a>
+    </li>
+</ol>
+<h2>Kelas-kelas utama</h2>
+<ol>
+    <li>{@link android.provider.ContactsContract.Contacts}</li>
+    <li>{@link android.provider.ContactsContract.RawContacts}</li>
+    <li>{@link android.provider.ContactsContract.Data}</li>
+    <li>{@code android.provider.ContactsContract.StreamItems}</li>
+</ol>
+<h2>Contoh-Contoh Terkait</h2>
+<ol>
+    <li>
+        <a href="{@docRoot}resources/samples/ContactManager/index.html">
+        Contact Manager
+        </a>
+    </li>
+    <li>
+        <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">
+        Contoh Adaptor Sinkronisasi</a>
+    </li>
+</ol>
+<h2>Lihat Juga</h2>
+<ol>
+    <li>
+        <a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
+        Dasar-Dasar Penyedia Konten
+        </a>
+    </li>
+</ol>
+</div>
+</div>
+<p>
+    Penyedia Kontak adalah komponen Android yang tangguh dan fleksibel dalam mengelola
+ repository data pusat tentang orang di perangkat. Penyedia Kontak adalah sumber data
+ yang Anda lihat dalam aplikasi kontak perangkat, dan Anda juga bisa mengakses datanya dalam aplikasi
+    Anda sendiri serta mentransfer data antara perangkat dan layanan online. Penyedia mengakomodasi
+    berbagai sumber data dan mencoba mengelola data sebanyak mungkin untuk setiap orang, sehingga
+   organisasinya menjadi kompleks. Karena itu, API penyedia menyertakan
+    satu set kelas kontrak dan antarmuka ekstensif yang membantu pengambilan dan
+    modifikasi data.
+</p>
+<p>
+    Panduan ini menjelaskan hal-hal berikut:
+</p>
+    <ul>
+        <li>
+            Struktur penyedia dasar.
+        </li>
+        <li>
+            Cara mengambil data dari penyedia.
+        </li>
+        <li>
+            Cara memodifikasi data di penyedia.
+        </li>
+        <li>
+            Cara menulis adaptor sinkronisasi untuk menyinkronkan data dari server Anda ke
+            Penyedia Kontak.
+        </li>
+    </ul>
+<p>
+    Panduan ini beranggapan bahwa Anda mengetahui dasar-dasar penyedia konten Android. Untuk mengetahui selengkapnya
+    tentang penyedia konten Android, bacalah
+    panduan<a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
+    Dasar-Dasar Penyedia Konten</a>. Contoh aplikasi
+    <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">Sample Sync Adapter</a>
+    adalah contoh penggunaan adaptor sinkronisasi untuk mentransfer data antara Penyedia Kontak
+    dan contoh aplikasi yang memiliki host di Google Web Services.
+</p>
+<h2 id="InformationTypes">Organisasi Penyedia Kontak</h2>
+<p>
+    Penyedia Kontak adalah komponen penyedia konten Android. Komponen ini memelihara tiga tipe
+    data tentang seseorang, masing-masing disesuaikan dengan tabel yang ditawarkan oleh penyedia, seperti
+    yang terlihat dalam gambar 1:
+</p>
+<img src="{@docRoot}images/providers/contacts_structure.png" alt="" height="364" id="figure1" />
+<p class="img-caption">
+  <strong>Gambar 1.</strong> Struktur tabel Penyedia Kontak.
+</p>
+<p>
+    Ketiga tabel disebut secara umum menurut nama kelas kontrak. Kelas
+    mendefinisikan konstanta untuk URI konten, nama kolom, dan nilai kolom yang digunakan oleh tabel-tabel:
+</p>
+<dl>
+    <dt>
+        Tabel {@link android.provider.ContactsContract.Contacts}
+    </dt>
+    <dd>
+        Baris mewakili orang yang berbeda, berdasarkan agregrasi baris kontak mentah.
+    </dd>
+    <dt>
+        Tabel {@link android.provider.ContactsContract.RawContacts}
+    </dt>
+    <dd>
+        Baris berisi rangkuman data seseorang, untuk tipe dan akun pengguna tertentu.
+    </dd>
+    <dt>
+        Tabel {@link android.provider.ContactsContract.Data}
+    </dt>
+    <dd>
+        Baris berisi data untuk kontak mentah, seperti alamat email atau nomor telepon.
+    </dd>
+</dl>
+<p>
+    Tabel lain yang diwakili oleh kelas kontrak dalam {@link android.provider.ContactsContract}
+    adalah tabel tambahan yang digunakan Penyedia Kontak untuk mengelola operasinya atau mendukung
+    fungsi tertentu dalam kontak atau aplikasi telepon perangkat.
+</p>
+<h2 id="RawContactBasics">Kontak mentah</h2>
+<p>
+    Kontak mentah mewakili data seseorang yang berasal dari satu tipe akun dan nama
+  akun. Karena Penyedia Kontak memungkinkan lebih dari satu layanan online sebagai sumber
+    data untuk satu orang, Penyedia Kontak memungkinkan multikontak mentah untuk orang yang sama.
+    Multikontak mentah juga memungkinkan seorang pengguna mengombinasikan data seseorang dari lebih dari satu akun
+    bertipe akun yang sama.
+</p>
+<p>
+    Sebagian besar data untuk kontak mentah tidak disimpan dalam
+    tabel {@link android.provider.ContactsContract.RawContacts}. Sebagai gantinya, data tersebut disimpan dalam satu atau beberapa baris
+    dalam tabel {@link android.provider.ContactsContract.Data}. Setiap baris data memiliki kolom
+    {@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID Data.RAW_CONTACT_ID} yang
+    berisi nilai {@code android.provider.BaseColumns#_ID RawContacts._ID} dari
+    baris {@link android.provider.ContactsContract.RawContacts} induknya.
+</p>
+<h3 id="RawContactsColumns">Kolom-kolom kontak mentah yang penting</h3>
+<p>
+    Kolom-kolom penting dalam tabel {@link android.provider.ContactsContract.RawContacts}
+    tercantum pada tabel 1. Bacalah catatan yang diberikan setelah tabel:
+</p>
+<p class="table-caption" id="table1">
+    <strong>Tabel 1.</strong> Kolom-kolom kontak mentah yang penting.
+</p>
+<table>
+    <tr>
+        <th scope="col">Nama kolom</th>
+        <th scope="col">Kegunaan</th>
+        <th scope="col">Catatan</th>
+    </tr>
+    <tr>
+        <td>
+            {@link android.provider.ContactsContract.SyncColumns#ACCOUNT_NAME}
+        </td>
+        <td>
+            Nama akun untuk tipe akun yang merupakan sumber kontak mentah ini.
+            Misalnya, nama akun dari akun Google adalah salah satu alamat Gmail
+   pemilik perangkat. Lihat entri berikutnya untuk
+            {@link android.provider.ContactsContract.SyncColumns#ACCOUNT_TYPE} untuk informasi
+            selengkapnya.
+        </td>
+        <td>
+            Format nama ini khusus untuk tipe akun ini. Format ini tidak
+            harus alamat email.
+        </td>
+    </tr>
+    <tr>
+        <td>
+            {@link android.provider.ContactsContract.SyncColumns#ACCOUNT_TYPE}
+        </td>
+        <td>
+            Tipe akun yang merupakan sumber kontak mentah ini. Misalnya, tipe
+           akun dari akun Google adalah <code>com.google</code>. Selalu batasi tipe akun Anda
+            dengan identifier domain untuk domain yang Anda miliki atau kontrol. Hal ini akan memastikan bahwa tipe
+            akun Anda bersifat unik.
+        </td>
+        <td>
+            Tipe akun yang menawarkan data kontak biasanya memiliki adaptor sinkronisasi terkait yang
+            menyinkronkan dengan Penyedia Kontak.
+    </tr>
+    <tr>
+        <td>
+            {@link android.provider.ContactsContract.RawContactsColumns#DELETED}
+        </td>
+        <td>
+            Flag "deleted" untuk kontak mentah.
+        </td>
+        <td>
+            Flag ini memungkinkan Penyedia Kontak memelihara baris secara internal hingga adaptor
+            sinkronisasi bisa menghapus baris dari server mereka dan akhirnya menghapus baris
+            dari repository.
+        </td>
+    </tr>
+</table>
+<h4>Catatan</h4>
+<p>
+    Berikut ini adalah catatan penting tentang
+    tabel {@link android.provider.ContactsContract.RawContacts}:
+</p>
+<ul>
+    <li>
+        Nama kontak mentah tidak disimpan di barisnya dalam
+        {@link android.provider.ContactsContract.RawContacts}. Sebagai gantinya, nama tersebut disimpan dalam
+         tabel {@link android.provider.ContactsContract.Data}, pada
+        baris {@link android.provider.ContactsContract.CommonDataKinds.StructuredName}. Kontak mentah
+        hanya memiliki satu baris dari tipe ini dalam tabel {@link android.provider.ContactsContract.Data}.
+    </li>
+    <li>
+        <strong>Perhatian:</strong> Untuk menggunakan data akun sendiri dalam baris kontak mentah, akun harus
+        didaftarkan lebih dahulu dengan {@link android.accounts.AccountManager}. Caranya, mintalah
+        pengguna untuk menambahkan tipe akun dan nama akun ke dalam daftar akun. Jika Anda tidak
+        melakukannya, Penyedia Kontak secara otomatis akan menghapus baris kontak mentah Anda.
+        <p>
+            Misalnya, Anda menginginkan aplikasi memelihara data kontak untuk layanan berbasis web
+            dengan domain {@code com.example.dataservice}, dan akun pengguna untuk layanan Anda
+            adalah {@code becky.sharp@dataservice.example.com}, pengguna harus menambahkan lebih dahulu "type"
+            akun ({@code com.example.dataservice}) dan "name" akun
+            ({@code becky.smart@dataservice.example.com}) sebelum aplikasi Anda bisa menambahkan baris kontak mentah.
+            Anda bisa menjelaskan ketentuan ini kepada pengguna dalam dokumentasi, atau meminta
+            pengguna untuk menambahkan tipe dan nama, atau keduanya. Tipe akun dan nama akun
+            dijelaskan lebih detail di bagian berikutnya.
+    </li>
+</ul>
+<h3 id="RawContactsExample">Sumber data kontak mentah</h3>
+<p>
+    Untuk memahami cara kerja kontak mentah, perhatikan pengguna "Emily Dickinson" yang mendefinisikan
+    tiga akun pengguna berikut pada perangkatnya:
+</p>
+<ul>
+    <li><code>emily.dickinson@gmail.com</code></li>
+    <li><code>emilyd@gmail.com</code></li>
+    <li>Akun Twitter "belle_of_amherst"</li>
+</ul>
+<p>
+    Pengguna ini telah mengaktifkan <em>Sync Contacts</em> untuk ketiga akun dalam pengaturan
+    <em>Accounts</em>.
+</p>
+<p>
+    Anggaplah Emily Dickinson membuka jendela browser, masuk ke Gmail sebagai
+    <code>emily.dickinson@gmail.com</code>, membuka
+    Contacts, dan menambahkan "Thomas Higginson". Kemudian, ia masuk ke Gmail sebagai
+    <code>emilyd@gmail.com</code> dan mengirimkan email kepada "Thomas Higginson", yang
+    menambahkan Thomas secara otomatis sebagai kontak. Ia juga mengikuti "colonel_tom" (ID Twitter Thomas Higginson) di
+    Twitter.
+</p>
+<p>
+    Penyedia Kontak membuat tiga kontak mentah akibat pekerjaan ini:
+</p>
+<ol>
+    <li>
+        Kontak mentah untuk "Thomas Higginson" yang dikaitkan dengan <code>emily.dickinson@gmail.com</code>.
+        Tipe akun penggunanya adalah Google.
+    </li>
+    <li>
+        Kontak mentah kedua untuk "Thomas Higginson" yang dikaitkan dengan <code>emilyd@gmail.com</code>.
+        Tipe akun pengguna juga Google. Ada kontak mentah kedua
+       meskipun nama tersebut identik dengan nama sebelumnya karena orang bersangkutan ditambahkan untuk
+        akun pengguna yang berbeda.
+    </li>
+    <li>
+        Kontak mentah ketiga untuk "Thomas Higginson" yang dikaitkan dengan "belle_of_amherst". Tipe
+        akun penggunanya adalah Twitter.
+    </li>
+</ol>
+<h2 id="DataBasics">Data</h2>
+<p>
+    Seperti yang telah disebutkan, data untuk kontak mentah disimpan dalam
+    baris {@link android.provider.ContactsContract.Data} yang ditautkan dengan nilai
+    <code>_ID</code> kontak mentah. Cara ini memungkinkan satu kontak mentah memiliki beberapa instance tipe data
+    yang sama dengan alamat email atau nomor telepon. Misalnya, jika
+    "Thomas Higginson" untuk {@code emilyd@gmail.com} (baris kontak mentah untuk Thomas Higginson
+   yang dikaitkan dengan akun Google <code>emilyd@gmail.com</code>) memiliki alamat email rumah
+    <code>thigg@gmail.com</code> dan alamat email kerja
+    <code>thomas.higginson@gmail.com</code>, Penyedia Kontak akan menyimpan dua baris alamat
+    email dan menautkan keduanya ke kontak mentah.
+</p>
+<p>
+    Perhatikan bahwa tipe data yang berbeda disimpan dalam satu tabel ini. Baris-baris nama tampilan,
+    nomor telepon, email, alamat surat, foto, dan data situs web semuanya bisa ditemukan dalam
+    tabel {@link android.provider.ContactsContract.Data}. Untuk membantu mengelola ini,
+    tabel {@link android.provider.ContactsContract.Data} memiliki beberapa kolom dengan nama deskriptif,
+    dalam kolom lain dengan nama generik. Konten kolom bernama deskriptif memiliki arti yang sama
+    terlepas dari tipe data dalam barisnya, sedangkan konten kolom bernama generik memiliki
+    arti yang berbeda-beda sesuai dengan tipe data.
+</p>
+<h3 id="DescriptiveColumns">Nama kolom deskriptif</h3>
+<p>
+    Beberapa contoh nama kolom deskriptif adalah:
+</p>
+<dl>
+    <dt>
+        {@link android.provider.ContactsContract.Data#RAW_CONTACT_ID}
+    </dt>
+    <dd>
+        Nilai kolom <code>_ID</code> kontak mentah untuk data ini.
+    </dd>
+    <dt>
+        {@link android.provider.ContactsContract.Data#MIMETYPE}
+    </dt>
+    <dd>
+        Tipe data yang disimpan dalam baris ini, dinyatakan berupa tipe MIME custom. Penyedia Kontak
+        menggunakan tipe MIME yang didefinisikan dalam subkelas
+        {@link android.provider.ContactsContract.CommonDataKinds}. Tipe MIME ini adalah sumber terbuka,
+        dan bisa digunakan oleh setiap aplikasi atau adaptor sinkronisasi yang bisa digunakan bersama Penyedia Kontak.
+    </dd>
+    <dt>
+        {@link android.provider.ContactsContract.DataColumns#IS_PRIMARY}
+    </dt>
+    <dd>
+        Jika tipe baris data ini bisa terjadi lebih dari satu kali untuk suatu kontak mentah,
+        kolom {@link android.provider.ContactsContract.DataColumns#IS_PRIMARY}
+        menandai baris data yang berisi data utama untuk tipe itu. Misalnya, jika
+        pengguna menekan lama sebuah nomor telepon untuk kontak dan memilih <strong>Set default</strong>,
+       maka baris {@link android.provider.ContactsContract.Data} yang berisi angka itu
+        mengatur kolom {@link android.provider.ContactsContract.DataColumns#IS_PRIMARY}-nya ke suatu
+        nilai bukan nol.
+    </dd>
+</dl>
+<h3 id="GenericColumns">Nama kolom generik</h3>
+<p>
+    Ada 15 kolom generik bernama <code>DATA1</code> hingga
+    <code>DATA15</code> yang tersedia secara umum dan empat kolom generik
+    tambahan <code>SYNC1</code> hingga <code>SYNC4</code> yang harus digunakan hanya oleh adaptor
+    sinkronisasi. Konstanta nama kolom generik selalu berfungsi, terlepas dari tipe
+    data dalam baris .
+</p>
+<p>
+    Kolom <code>DATA1</code> diindeks.  Penyedia Kontak selalu menggunakan kolom ini untuk
+    data yang diharapkan penyedia akan menjadi target yang paling sering dari suatu query. Misalnya,
+    dalam baris email, kolom ini berisi alamat email sebenarnya.
+</p>
+<p>
+    Sesuai konvensi, kolom <code>DATA15</code> dicadangkan untuk menyimpan data Binary Large Object
+    (BLOB) seperti thumbnail foto.
+</p>
+<h3 id="TypeSpecificNames">Nama kolom bertipe spesifik</h3>
+<p>
+    Guna memudahkan pekerjaan dengan kolom untuk tipe baris tertentu, Penyedia Kontak
+    juga menyediakan konstanta nama kolom bertipe spesifik, yang didefinisikan dalam subkelas
+    {@link android.provider.ContactsContract.CommonDataKinds}. Konstanta cuma memberikan nama
+    konstanta yang berbeda ke nama kolom yang sama, yang membantu Anda mengakses data dalam baris
+    bertipe spesifik.
+</p>
+<p>
+    Misalnya, kelas {@link android.provider.ContactsContract.CommonDataKinds.Email} mendefinisikan
+    konstanta nama kolom bertipe spesifik untuk baris {@link android.provider.ContactsContract.Data}
+    yang memiliki tipe MIME
+    {@link android.provider.ContactsContract.CommonDataKinds.Email#CONTENT_ITEM_TYPE
+    Email.CONTENT_ITEM_TYPE}. Kelas ini berisi konstanta
+    {@link android.provider.ContactsContract.CommonDataKinds.Email#ADDRESS} untuk kolom
+    alamat email. Nilai sesungguhnya dari
+    {@link android.provider.ContactsContract.CommonDataKinds.Email#ADDRESS} adalah "data1", yang
+    sama dengan nama generik kolom.
+</p>
+<p class="caution">
+    <strong>Perhatian:</strong> Jangan tambahkan data custom Anda sendiri ke
+    tabel {@link android.provider.ContactsContract.Data} dengan menggunakan baris yang memiliki salah satu
+    tipe MIME yang telah didefinisikan penyedia. Jika melakukannya, Anda bisa kehilangan data atau menyebabkan penyedia
+    gagal berfungsi. Misalnya, Anda seharusnya tidak menambahkan baris bertipe MIME
+    {@link android.provider.ContactsContract.CommonDataKinds.Email#CONTENT_ITEM_TYPE
+    Email.CONTENT_ITEM_TYPE} yang berisi nama pengguna sebagai ganti alamat email dalam
+    kolom <code>DATA1</code>. Jika Anda menggunakan tipe MIME custom sendiri untuk baris bersangkutan, maka Anda bebas
+    untuk mendefinisikan nama kolom bertipe spesifik dan menggunakan kolom sekehendak Anda.
+</p>
+<p>
+    Gambar 2 menampilkan cara kolom deskriptif dan kolom data muncul dalam
+    baris {@link android.provider.ContactsContract.Data}, dan cara nama kolom bertipe spesifik "melapisi"
+    nama kolom generik
+</p>
+<img src="{@docRoot}images/providers/data_columns.png" alt="How type-specific column names map to generic column names" height="311" id="figure2" />
+<p class="img-caption">
+  <strong>Gambar 2.</strong> Nama kolom bertipe spesifik dan nama kolom generik.
+</p>
+<h3 id="ColumnMaps">Kelas nama kolom bertipe spesifik</h3>
+<p>
+    Tabel 2 berisi daftar kelas nama kolom bertipe spesifik yang paling umum digunakan:
+</p>
+<p class="table-caption" id="table2">
+  <strong>Tabel 2.</strong> Kelas nama kolom bertipe spesifik</p>
+<table>
+  <tr>
+    <th scope="col">Kelas pemetaan</th>
+    <th scope="col">Tipe data</th>
+    <th scope="col">Catatan</th>
+  </tr>
+  <tr>
+    <td>{@link android.provider.ContactsContract.CommonDataKinds.StructuredName}</td>
+    <td>Data nama untuk kontak mentah yang dikaitkan dengan baris data ini.</td>
+    <td>Kontak mentah hanya memiliki salah satu baris ini.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.ContactsContract.CommonDataKinds.Photo}</td>
+    <td>Foto utama untuk kontak mentah yang dikaitkan dengan baris data ini.</td>
+    <td>Kontak mentah hanya memiliki salah satu baris ini.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.ContactsContract.CommonDataKinds.Email}</td>
+    <td>Alamat email untuk kontak mentah yang dikaitkan dengan baris data ini.</td>
+    <td>Kontak mentah bisa memiliki beberapa alamat email.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.ContactsContract.CommonDataKinds.StructuredPostal}</td>
+    <td>Alamat pos untuk kontak mentah yang dikaitkan dengan baris data ini.</td>
+    <td>Kontak mentah bisa memiliki beberapa alamat email.</td>
+  </tr>
+  <tr>
+    <td>{@link android.provider.ContactsContract.CommonDataKinds.GroupMembership}</td>
+    <td>Identifier yang menautkan kontak mentah ke salah satu grup dalam Penyedia Kontak.</td>
+    <td>
+        Grup adalah fitur opsional pada tipe akun dan nama akun. Grup dijelaskan
+       lebih detail di bagian <a href="#Groups">Grup kontak</a>.
+    </td>
+  </tr>
+</table>
+<h3 id="ContactBasics">Kontak</h3>
+<p>
+    Penyedia Kontak mengombinasikan baris kontak mentah di semua tipe akun dan nama akun
+    untuk membentuk <strong>kontak</strong>. Hal ini memudahkan menampilkan dan memodifikasi semua data
+    yang telah dikumpulkan pengguna untuk seseorang. Penyedia Kontak mengelola pembuatan baris
+    kontak baru, dan agregasi kontak mentah dengan baris kontak yang ada. Baik aplikasi maupun adaptor sinkronisasi
+    tidak boleh menambahkan kontak dan sebagian kolom dalam baris kontak yang bersifat hanya baca.
+</p>
+<p class="note">
+    <strong>Catatan:</strong> Jika Anda mencoba menambahkan kontak ke Penyedia Kontak dengan
+    {@link android.content.ContentResolver#insert(Uri,ContentValues) insert()}, Anda akan mendapatkan
+    eksepsi {@link java.lang.UnsupportedOperationException}. Jika Anda mencoba memperbarui sebuah kolom
+   yang tercantum sebagai "hanya-baca", pembaruan akan diabaikan.
+</p>
+<p>
+    Penyedia Kontak membuat kontak baru untuk merespons penambahan kontak mentah baru
+    yang tidak cocok dengan kontak yang ada. Penyedia juga melakukan ini jika data
+    kontak mentah yang ada berubah sehingga tidak lagi cocok dengan kontak yang
+    sebelumnya dihubungkan. Jika aplikasi atau adaptor sinkronisasi membuat kontak mentah baru yang
+    <em>memang</em> cocok dengan kontak yang ada, kontak mentah baru akan diagregasikan ke kontak
+    yang ada.
+</p>
+<p>
+    Penyedia Kontak menautkan baris kontak ke baris kontak mentahnya dengan kolom
+    <code>_ID</code> dari baris kontak dalam tabel {@link android.provider.ContactsContract.Contacts Contacts}.
+ Kolom <code>CONTACT_ID</code> tabel kontak mentah
+    {@link android.provider.ContactsContract.RawContacts} berisi nilai <code>_ID</code> untuk
+    baris kontak yang dikaitkan dengan tiap baris kontak mentah.
+</p>
+<p>
+    Tabel {@link android.provider.ContactsContract.Contacts} juga memiliki kolom
+    {@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} yang merupakan
+    tautan "permanen" ke baris kontak. Karena memelihara kontak
+    secara otomatis, Penyedia Kontak bisa mengubah nilai {@code android.provider.BaseColumns#_ID} baris kontak
+    untuk merespons agregasi atau sinkronisasi. Sekalipun ini terjadi, URI konten
+    {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} yang dikombinasikan dengan
+    {@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} kontak akan tetap
+    menunjuk ke baris kontak itu, sehingga Anda bisa menggunakan
+    {@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY}
+   untuk memelihara tautan ke kontak "favorit", dan seterusnya. Kolom ini memiliki formatnya sendiri, yang
+    tidak terkait dengan format kolom {@code android.provider.BaseColumns#_ID}.
+</p>
+<p>
+    Gambar 3 menampilkan cara ketiga tabel utama terkait satu sama lain.
+</p>
+<img src="{@docRoot}images/providers/contacts_tables.png" alt="Contacts provider main tables" height="514" id="figure4" />
+<p class="img-caption">
+  <strong>Gambar 3.</strong> Hubungan tabel Contacts, Raw Contacts, dan Details.
+</p>
+<h2 id="Sources">Data Dari Adaptor Sinkronisasi</h2>
+<p>
+    Pengguna memasukkan data kontak secara langsung ke dalam perangkat, namun data juga mengalir masuk ke Penyedia Kontak
+    dari layanan web melalui <strong>adaptor sinkronisasi</strong>, yang mengotomatiskan
+    transfer data antara perangkat dan layanan. Adaptor sinkronisasi berjalan di latar belakang
+    di bawah kontrol sistem, dan memanggil metode {@link android.content.ContentResolver}
+   untuk mengelola data.
+</p>
+<p>
+    Di Android, layanan web yang digunakan adaptor sinkronisasi diidentifikasi melalui tipe akun.
+    Setiap adaptor sinkronisasi bekerja dengan satu tipe akun, tetapi bisa mendukung beberapa nama akun untuk
+    tipe itu. Tipe akun dan nama akun dijelaskan secara singkat di bagian
+    <a href="#RawContactsExample">Sumber data kontak mentah</a>. Definisi berikut menyediakan
+    detail selengkapnya, dan menjelaskan cara tipe dan nama akun berkaitan dengan adaptor sinkronisasi dan layanan.
+</p>
+<dl>
+    <dt>
+        Tipe akun
+    </dt>
+    <dd>
+        Mengidentifikasi layanan tempat pengguna menyimpan data. Sering kali, pengguna harus
+        mengautentikasi diri dengan layanan. Misalnya, Google Contacts adalah tipe akun, yang diidentifikasi
+        dengan kode <code>google.com</code>. Nilai ini sesuai dengan tipe akun yang digunakan oleh
+        {@link android.accounts.AccountManager}.
+    </dd>
+    <dt>
+        Nama akun
+    </dt>
+    <dd>
+        Mengidentifikasi akun atau login tertentu untuk suatu tipe akun. Akun Google Contacts
+        sama dengan akun Google, yang memiliki alamat email sebagai nama akun.
+        Layanan lain mungkin menggunakan nama pengguna satu-kata atau identitas berupa angka.
+    </dd>
+</dl>
+<p>
+    Tipe akun tidak harus unik. Pengguna boleh mengonfigurasi beberapa akun Google Contacts
+    dan mengunduh data ke Penyedia Kontak; ini mungkin terjadi jika pengguna memiliki satu set
+    kontak pribadi untuk satu nama akun pribadi, dan satu set lagi untuk pekerjaan. Nama akun
+    biasanya unik. Bersama-sama, keduanya mengidentifikasi aliran data tertentu antara Penyedia Kontak dan
+    layanan eksternal.
+</p>
+<p>
+    Jika Anda ingin mentransfer data layanan ke Penyedia Kontak, Anda perlu menulis
+    adaptor sinkronisasi sendiri. Hal ini dijelaskan lebih detail di bagian
+    <a href="#SyncAdapters">Adaptor Sinkronisasi Penyedia Kontak</a>.
+</p>
+<p>
+    Gambar 4 menampilkan cara Penyedia Kontak dimasukkan ke dalam aliran data
+    tentang orang. Dalam kotak bertanda "sync adapters", setiap adaptor diberi label menurut tipe akunnya.
+</p>
+<img src="{@docRoot}images/providers/ContactsDataFlow.png" alt="Flow of data about people" height="252" id="figure5" />
+<p class="img-caption">
+  <strong>Gambar 4.</strong> Aliran data Penyedia Kontak.
+</p>
+<h2 id="Permissions">Izin yang Diperlukan</h2>
+<p>
+    Aplikasi yang ingin mengakses Penyedia Kontak harus meminta izin
+   berikut:
+</p>
+<dl>
+    <dt>Akses baca ke satu atau beberapa tabel</dt>
+    <dd>
+        {@link android.Manifest.permission#READ_CONTACTS}, yang ditetapkan dalam
+        <code>AndroidManifest.xml</code> dengan elemen
+        <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">
+        &lt;uses-permission&gt;</a></code> sebagai
+        <code>&lt;uses-permission android:name="android.permission.READ_CONTACTS"&gt;</code>.
+    </dd>
+    <dt>Akses tulis ke satu atau beberapa tabel</dt>
+    <dd>
+        {@link android.Manifest.permission#WRITE_CONTACTS}, yang ditetapkan dalam
+        <code>AndroidManifest.xml</code> dengan elemen
+        <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">
+        &lt;uses-permission&gt;</a></code> sebagai
+        <code>&lt;uses-permission android:name="android.permission.WRITE_CONTACTS"&gt;</code>.
+    </dd>
+</dl>
+<p>
+    Izin ini tidak diperluas ke data profil pengguna. Profil pengguna dan izin
+   yang diperlukan dibahas di bagian berikut,
+    <a href="#UserProfile">Profil Pengguna</a>.
+</p>
+<p>
+    Ingatlah bahwa data kontak pengguna bersifat pribadi dan sensitif. Pengguna mempersoalkan
+    privasinya, sehingga tidak ingin aplikasi mengumpulkan data tentang diri atau kontak mereka.
+    Jika alasan Anda memerlukan izin untuk mengakses data kontak tidak jelas, pengguna mungkin memberi
+    aplikasi Anda peringkat rendah atau langsung menolak menginstalnya.
+</p>
+<h2 id="UserProfile">Profil Pengguna</h2>
+<p>
+    Tabel {@link android.provider.ContactsContract.Contacts} berisi satu baris yang berisi
+    data profil untuk pengguna perangkat. Data ini menjelaskan data perangkat  <code>user</code> bukannya
+    salah satu kontak pengguna. Baris kontak profil ditautkan ke baris
+     kontak mentah untuk setiap sistem yang menggunakan profil.
+    Setiap baris kontak mentah profil bisa memiliki beberapa baris data. Konstanta untuk mengakses profil
+    pengguna tersedia dalam kelas {@link android.provider.ContactsContract.Profile}.
+</p>
+<p>
+    Akses ke profil pengguna memerlukan izin khusus. Selain itu, izin
+    {@link android.Manifest.permission#READ_CONTACTS} dan
+    {@link android.Manifest.permission#WRITE_CONTACTS} diperlukan untuk membaca dan menulis, akses
+    ke profil pengguna memerlukan masing-masing izin {@code android.Manifest.permission#READ_PROFILE} dan
+    {@code android.Manifest.permission#WRITE_PROFILE} untuk akses baca dan tulis.
+
+</p>
+<p>
+    Ingatlah bahwa Anda harus mempertimbangkan profil pengguna bersifat sensitif. Izin
+    {@code android.Manifest.permission#READ_PROFILE} memungkinkan Anda mengakses data yang mengidentifikasi secara pribadi
+    pengguna perangkat. Pastikan memberi tahu pengguna alasan
+    Anda memerlukan izin akses profil pengguna dalam keterangan aplikasi Anda.
+</p>
+<p>
+    Untuk mengambil baris kontak berisi profil pengguna,
+    panggil {@link android.content.ContentResolver#query(Uri,String[], String, String[], String)
+    ContentResolver.query()}. Atur URI konten ke
+    {@link android.provider.ContactsContract.Profile#CONTENT_URI} dan jangan sediakan
+    kriteria pemilihan apa pun. Anda juga bisa menggunakan URI konten ini sebagai URI dasar untuk mengambil kontak
+    mentah atau data untuk profil. Misalnya, cuplikan kode ini mengambil data untuk profil:
+</p>
+<pre>
+// Sets the columns to retrieve for the user profile
+mProjection = new String[]
+    {
+        Profile._ID,
+        Profile.DISPLAY_NAME_PRIMARY,
+        Profile.LOOKUP_KEY,
+        Profile.PHOTO_THUMBNAIL_URI
+    };
+
+// Retrieves the profile from the Contacts Provider
+mProfileCursor =
+        getContentResolver().query(
+                Profile.CONTENT_URI,
+                mProjection ,
+                null,
+                null,
+                null);
+</pre>
+<p class="note">
+    <strong>Catatan:</strong> Jika Anda mengambil beberapa baris kontak, dan ingin menentukan apakah salah satu baris
+    adalah profil pengguna, uji
+    kolom {@link android.provider.ContactsContract.ContactsColumns#IS_USER_PROFILE} pada baris tersebut. Kolom ini
+    diatur ke "1" jika kontak adalah profil pengguna.
+</p>
+<h2 id="ContactsProviderMetadata">Metadata Penyedia Kontak</h2>
+<p>
+    Penyedia Kontak mengelola data yang mencatat status data kontak dalam
+    repository. Metadata repository ini disimpan di berbagai tempat, termasuk baris-baris tabel
+    Raw Contacts, Data, dan Contacts,
+    tabel {@link android.provider.ContactsContract.Settings}, dan
+    tabel {@link android.provider.ContactsContract.SyncState}. Tabel berikut menampilkan
+    efek setiap potongan metadata ini:
+</p>
+<p class="table-caption" id="table3">
+  <strong>Tabel 3.</strong> Metadata di Penyedia Kontak</p>
+<table>
+    <tr>
+        <th scope="col">Tabel</th>
+        <th scope="col">Kolom</th>
+        <th scope="col">Nilai</th>
+        <th scope="col">Arti</th>
+    </tr>
+    <tr>
+        <td rowspan="2">{@link android.provider.ContactsContract.RawContacts}</td>
+        <td rowspan="2">{@link android.provider.ContactsContract.SyncColumns#DIRTY}</td>
+        <td>"0" - tidak berubah sejak sinkronisasi terakhir.</td>
+        <td rowspan="2">
+            Menandai kontak mentah yang berubah pada perangkat dan telah disinkronkan kembali ke
+           server. Nilai diatur secara otomatis oleh Penyedia Kontak bila aplikasi
+            Android memperbarui baris.
+            <p>
+                Adaptor sinkronisasi yang memodifikasi kontak mentah atau tabel data harus selalu menambahkan
+                string {@link android.provider.ContactsContract#CALLER_IS_SYNCADAPTER} ke
+                URI konten yang digunakannya. Ini mencegah penyedia menandai baris sebagai kotor.
+                Sebaliknya, modifikasi oleh adaptor sinkronisasi tampak seperti modifikasi lokal dan
+                dikirim ke server, meskipun server adalah sumber modifikasi.
+            </p>
+        </td>
+    </tr>
+    <tr>
+            <td>"1" - berubah sejak sinkronisasi terakhir, harus disinkronkan kembali ke server.</td>
+    </tr>
+    <tr>
+        <td>{@link android.provider.ContactsContract.RawContacts}</td>
+        <td>{@link android.provider.ContactsContract.SyncColumns#VERSION}</td>
+        <td>Nomor versi baris ini.</td>
+        <td>
+            Penyedia Kontak menambahkan nilai ini secara otomatis bila baris atau
+            data terkaitnya berubah.
+        </td>
+    </tr>
+    <tr>
+        <td>{@link android.provider.ContactsContract.Data}</td>
+        <td>{@link android.provider.ContactsContract.DataColumns#DATA_VERSION}</td>
+        <td>Nomor versi baris ini.</td>
+        <td>
+            Penyedia Kontak menambahkan nilai ini secara otomatis bila baris data
+            berubah.
+        </td>
+    </tr>
+    <tr>
+        <td>{@link android.provider.ContactsContract.RawContacts}</td>
+        <td>{@link android.provider.ContactsContract.SyncColumns#SOURCE_ID}</td>
+        <td>
+            Nilai string yang mengidentifikasi secara unik kontak mentah ini ke akun tempat
+            kontak dibuat.
+        </td>
+        <td>
+            Bila adaptor sinkronisasi membuat kontak mentah baru, kolom ini harus diatur ke
+            ID unik server untuk kontak mentah itu. Bila aplikasi Android membuat kontak mentah
+            baru, aplikasi harus membiarkan kolom ini kosong. Ini mengisyaratkan pada adaptor
+            sinkronisasi bahwa adaptor harus membuat kontak mentah baru pada server, dan mendapatkan
+            nilai untuk {@link android.provider.ContactsContract.SyncColumns#SOURCE_ID}.
+            <p>
+                Khususnya, id sumber harus <strong>unik</strong> untuk setiap tipe
+                akun dan stabil di semua sinkronisasi:
+            </p>
+                <ul>
+                    <li>
+                        Unik: Setiap kontak mentah untuk satu akun harus memiliki id sumbernya sendiri. Jika Anda
+                        tidak memberlakukan aturan ini, masalah akan timbul dalam aplikasi kontak.
+                        Perhatikan bahwa dua kontak mentah untuk tipe akun yang <em>sama</em> boleh memiliki
+                       id sumber yang sama. Misalnya, kontak mentah "Thomas Higginson" untuk
+                        akun {@code emily.dickinson@gmail.com} boleh memiliki id sumber
+                        yang sama dengan kontak mentah "Thomas Higginson" untuk akun
+                        {@code emilyd@gmail.com}.
+                    </li>
+                    <li>
+                        Stabil: Id sumber adalah bagian tetap dari data layanan online untuk
+                        kontak mentah. Misalnya, jika pengguna membersihkan Contacts Storage dari
+                        pengaturan aplikasi dan menyinkronkan ulang, kontak mentah yang dipulihkan akan memiliki id sumber
+                        yang sama dengan sebelumnya. Jika Anda tidak memberlakukan hal ini, pintasan akan berhenti
+                        berfungsi.
+                    </li>
+                </ul>
+        </td>
+    </tr>
+    <tr>
+        <td rowspan="2">{@link android.provider.ContactsContract.Groups}</td>
+        <td rowspan="2">{@link android.provider.ContactsContract.GroupsColumns#GROUP_VISIBLE}</td>
+        <td>"0" - Kontak dalam grup ini tidak boleh terlihat dalam UI aplikasi Android.</td>
+        <td>
+            Kolom ini digunakan untuk kompatibilitas dengan server yang memungkinkan pengguna menyembunyikan kontak dalam
+            grup tertentu.
+        </td>
+    </tr>
+    <tr>
+        <td>"1" - Kontak dalam grup ini boleh terlihat dalam UI aplikasi.</td>
+    </tr>
+    <tr>
+        <td rowspan="2">{@link android.provider.ContactsContract.Settings}</td>
+        <td rowspan="2">
+            {@link android.provider.ContactsContract.SettingsColumns#UNGROUPED_VISIBLE}</td>
+        <td>
+            "0" - Untuk akun dan tipe akun ini, kontak yang bukan milik grup
+            tidak akan terlihat pada UI aplikasi Android.
+        </td>
+        <td rowspan="2">
+            Secara default, kontak tidak terlihat jika tidak satu pun kontak mentahnya milik grup
+            (Keanggotaan grup untuk kontak mentah ditandai oleh satu atau beberapa baris
+            {@link android.provider.ContactsContract.CommonDataKinds.GroupMembership}
+            dalam tabel {@link android.provider.ContactsContract.Data}).
+            Dengan mengatur flag ini dalam baris tabel {@link android.provider.ContactsContract.Settings}
+            untuk tipe akun dan akun, Anda bisa memaksakan kontak tanpa grup agar terlihat.
+            Satu kegunaan flag ini adalah menampilkan kontak dari server yang tidak menggunakan grup.
+        </td>
+    </tr>
+    <tr>
+        <td>
+            "1" - Untuk akun dan tipe akun ini, kontak yang bukan milik grup
+            akan terlihat pada UI aplikasi.
+        </td>
+
+    </tr>
+    <tr>
+        <td>{@link android.provider.ContactsContract.SyncState}</td>
+        <td>(semua)</td>
+        <td>
+            Gunakan tabel ini untuk menyimpan metadata bagi adaptor sinkronisasi Anda.
+        </td>
+        <td>
+            Dengan tabel ini, Anda bisa menyimpan status sinkronisasi dan data lain yang terkait dengan sinkronisasi secara persisten pada
+            perangkat.
+        </td>
+    </tr>
+</table>
+<h2 id="Access">Akses Penyedia Kontak</h2>
+<p>
+    Bagian ini menjelaskan panduan untuk mengakses data dari Penyedia Kontak, yang berfokus pada
+    hal-hal berikut:
+</p>
+<ul>
+    <li>
+        Query entitas.
+    </li>
+    <li>
+        Modifikasi batch.
+    </li>
+    <li>
+        Pengambilan dan modifikasi dengan intent.
+    </li>
+    <li>
+        Integritas data.
+    </li>
+</ul>
+<p>
+    Membuat modifikasi dari adaptor sinkronisasi juga secara lebih detail di bagian
+    <a href="#SyncAdapters">Adaptor Sinkronisasi Penyedia Kontak</a>.
+</p>
+<h3 id="Entities">Membuat query entitas</h3>
+<p>
+    Karena disusun secara hierarki, tabel-tabel Penyedia Kontak sering kali berguna untuk
+    mengambil baris dan semua baris "anak" yang ditautkan dengannya. Misalnya, untuk menampilkan
+    semua informasi untuk satu orang, Anda mungkin ingin mengambil semua
+    baris {@link android.provider.ContactsContract.RawContacts} untuk satu baris
+    {@link android.provider.ContactsContract.Contacts}, atau semua
+    baris {@link android.provider.ContactsContract.CommonDataKinds.Email} untuk satu baris
+    {@link android.provider.ContactsContract.RawContacts}. Untuk memudahkan hal ini, Penyedia Kontak
+    menawarkan konstruksi <strong>entitas</strong>, yang berfungsi seperti gabungan database di antara
+    tabel-tabel.
+</p>
+<p>
+    Entitas adalah seperti tabel yang terdiri atas kolom-kolom terpilih dari tabel induk dan tabel anaknya.
+    Bila membuat query sebuah entitas, Anda memberikan proyeksi dan kriteria pencarian berdasarkan kolom-kolom
+    yang tersedia dari entitas itu. Hasilnya adalah sebuah {@link android.database.Cursor} yang
+    berisi satu baris untuk setiap baris tabel anak yang diambil. Misalnya, jika Anda membuat query
+    {@link android.provider.ContactsContract.Contacts.Entity} untuk satu nama kontak
+    dan semua baris {@link android.provider.ContactsContract.CommonDataKinds.Email} untuk semua
+    kontak mentah bagi nama itu, Anda akan mendapatkan kembali {@link android.database.Cursor} berisi satu baris
+    untuk setiap baris {@link android.provider.ContactsContract.CommonDataKinds.Email}.
+</p>
+<p>
+    Entitas menyederhanakan query. Dengan entitas, Anda bisa mengambil semua data kontak untuk satu
+    kontak atau kontak mentah sekaligus, sebagai ganti harus membuat query tabel induk terlebih dahulu untuk mendapatkan
+    ID, lalu harus membuat query tabel anak dengan ID itu. Selain itu, Penyedia Kontak akan memproses
+    query terhadap entitas dalam satu transaksi, yang memastikan bahwa data yang diambil
+    konsisten secara internal.
+</p>
+<p class="note">
+    <strong>Catatan:</strong> Entitas biasanya tidak berisi semua kolom tabel induk dan
+    anak. Jika Anda mencoba menggunakan nama kolom yang tidak ada dalam daftar konstanta
+    nama kolom untuk entitas, Anda akan mendapatkan {@link java.lang.Exception}.
+</p>
+<p>
+    Cuplikan berikut menampilkan cara mengambil semua baris kontak mentah untuk sebuah kontak. Cuplikan ini
+    adalah bagian dari aplikasi lebih besar yang memiliki dua aktivitas, "main" dan "detail". Aktivitas utama
+    menampilkan daftar baris kontak; bila pengguna memilih satu baris, aktivitas akan mengirimkan ID-nya ke aktivitas
+    detail. Aktivitas detail menggunakan{@link android.provider.ContactsContract.Contacts.Entity}
+    untuk menampilkan semua baris data dari semua kontak mentah yang dikaitkan dengan kontak
+    terpilih.
+</p>
+<p>
+    Cuplikan ini diambil dari aktivitas "detail":
+</p>
+<pre>
+...
+    /*
+     * Appends the entity path to the URI. In the case of the Contacts Provider, the
+     * expected URI is content://com.google.contacts/#/entity (# is the ID value).
+     */
+    mContactUri = Uri.withAppendedPath(
+            mContactUri,
+            ContactsContract.Contacts.Entity.CONTENT_DIRECTORY);
+
+    // Initializes the loader identified by LOADER_ID.
+    getLoaderManager().initLoader(
+            LOADER_ID,  // The identifier of the loader to initialize
+            null,       // Arguments for the loader (in this case, none)
+            this);      // The context of the activity
+
+    // Creates a new cursor adapter to attach to the list view
+    mCursorAdapter = new SimpleCursorAdapter(
+            this,                        // the context of the activity
+            R.layout.detail_list_item,   // the view item containing the detail widgets
+            mCursor,                     // the backing cursor
+            mFromColumns,                // the columns in the cursor that provide the data
+            mToViews,                    // the views in the view item that display the data
+            0);                          // flags
+
+    // Sets the ListView's backing adapter.
+    mRawContactList.setAdapter(mCursorAdapter);
+...
+&#64;Override
+public Loader&lt;Cursor&gt; onCreateLoader(int id, Bundle args) {
+
+    /*
+     * Sets the columns to retrieve.
+     * RAW_CONTACT_ID is included to identify the raw contact associated with the data row.
+     * DATA1 contains the first column in the data row (usually the most important one).
+     * MIMETYPE indicates the type of data in the data row.
+     */
+    String[] projection =
+        {
+            ContactsContract.Contacts.Entity.RAW_CONTACT_ID,
+            ContactsContract.Contacts.Entity.DATA1,
+            ContactsContract.Contacts.Entity.MIMETYPE
+        };
+
+    /*
+     * Sorts the retrieved cursor by raw contact id, to keep all data rows for a single raw
+     * contact collated together.
+     */
+    String sortOrder =
+            ContactsContract.Contacts.Entity.RAW_CONTACT_ID +
+            " ASC";
+
+    /*
+     * Returns a new CursorLoader. The arguments are similar to
+     * ContentResolver.query(), except for the Context argument, which supplies the location of
+     * the ContentResolver to use.
+     */
+    return new CursorLoader(
+            getApplicationContext(),  // The activity's context
+            mContactUri,              // The entity content URI for a single contact
+            projection,               // The columns to retrieve
+            null,                     // Retrieve all the raw contacts and their data rows.
+            null,                     //
+            sortOrder);               // Sort by the raw contact ID.
+}
+</pre>
+<p>
+    Bila selesai dimuat, {@link android.app.LoaderManager} akan memicu callback ke
+    {@link android.app.LoaderManager.LoaderCallbacks#onLoadFinished(Loader, D)
+    onLoadFinished()}. Salah satu argumen masuk pada metode ini adalah
+    {@link android.database.Cursor} bersama hasil query. Dalam aplikasi Anda sendiri, Anda bisa memperoleh
+    data dari {@link android.database.Cursor} ini untuk menampilkannya atau menggunakannya lebih jauh.
+</p>
+<h3 id="Transactions">Modifikasi batch</h3>
+<p>
+    Bila memungkinkan, Anda harus menyisipkan, memperbarui, dan menghapus data dalam Penyedia Kontak dengan
+    "batch mode", dengan membuat {@link java.util.ArrayList} dari
+    objek-objek {@link android.content.ContentProviderOperation} dan memanggil
+    {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}. Karena
+    Penyedia Kontak menjalankan semua operasi dalam satu
+    {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()} transaksi,
+    modifikasi Anda tidak akan pernah meninggalkan repository kontak dalam keadaan
+    tidak konsisten. Modifikasi batch juga memudahkan penyisipan kontak mentah dan data detailnya
+    sekaligus.
+</p>
+<p class="note">
+    <strong>Catatan:</strong> Untuk memodifikasi <em>satu</em> kontak mentah, pertimbangkan untuk mengirim intent ke
+    aplikasi kontak perangkat daripada menangani modifikasi dalam aplikasi Anda.
+    Cara ini dijelaskan lebih detail di bagian
+    <a href="#Intents">Pengambilan dan modifikasi dengan intent</a>.
+</p>
+<h4>Yield point</h4>
+<p>
+    Modifikasi batch yang berisi operasi dalam jumlah besar bisa memblokir proses lain,
+    yang mengakibatkan pengalaman pengguna yang buruk secara keseluruhan. Untuk menata semua modifikasi yang ingin Anda
+    jalankan dalam sesedikit mungkin daftar terpisah, sambil mencegah modifikasi dari
+    memblokir sistem, Anda harus menetapkan <strong>yield point</strong> untuk satu atau beberapa operasi.
+    Yield point (titik hasil) adalah objek {@link android.content.ContentProviderOperation} yang mengatur
+    nilai {@link android.content.ContentProviderOperation#isYieldAllowed()}-nya ke
+    <code>true</code>. Bila menemui yield point, Penyedia Kontak akan menghentikan pekerjaannya untuk
+    membiarkan proses lain berjalan dan menutup transaksi saat ini. Bila dimulai lagi, penyedia akan
+    melanjutkan dengan operasi berikutnya di {@link java.util.ArrayList} dan memulai transaksi
+    baru.
+</p>
+<p>
+    Yield point memang menyebabkan lebih dari satu transaksi per panggilan ke
+    {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}. Karena
+    itu, Anda harus menetapkan yield point pada operasi terakhir untuk satu set baris terkait.
+    Misalnya, Anda harus menetapkan yield point pada operasi terakhir di satu set yang menambahkan
+    baris kontak mentah dan baris data terkait, atau operasi terakhir untuk satu set baris yang terkait
+    dengan satu kontak.
+</p>
+<p>
+    Yield point juga merupakan unit operasi atomis. Semua akses antara dua yield point bisa
+    saja berhasil atau gagal sebagai satu unit. Jika Anda mengatur yield point, operasi
+    atomis terkecil adalah seluruh batch operasi. Jika menggunakan yield point, Anda akan mencegah
+    operasi menurunkan kinerja sistem, sekaligus memastikan subset
+    operasi bersifat atomis.
+</p>
+<h4>Acuan balik modifikasi</h4>
+<p>
+    Saat Anda menyisipkan baris kontak mentah baru dan baris data terkaitnya sebagai satu set
+    objek {@link android.content.ContentProviderOperation}, Anda harus menautkan baris data ke
+    baris kontak mentah dengan memasukkan nilai
+    {@code android.provider.BaseColumns#_ID} kontak mentah sebagai
+    nilai {@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID}. Akan tetapi, nilai
+    ini tidak tersedia saat Anda membuat {@link android.content.ContentProviderOperation}
+    untuk baris data, karena Anda belum menerapkan
+    {@link android.content.ContentProviderOperation} untuk baris kontak mentah. Solusinya,
+     kelas {@link android.content.ContentProviderOperation.Builder} memiliki metode
+    {@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()}.
+    Metode ini memungkinkan Anda menyisipkan atau mengubah kolom dengan
+    hasil dari operasi sebelumnya.
+</p>
+<p>
+    Metode {@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()}
+    memiliki dua argumen:
+</p>
+    <dl>
+        <dt>
+            <code>key</code>
+        </dt>
+        <dd>
+            Kunci dari pasangan kunci-nilai. Nilai argumen ini harus berupa nama kolom
+            dalam tabel yang Anda modifikasi.
+        </dd>
+        <dt>
+            <code>previousResult</code>
+        </dt>
+        <dd>
+            Indeks berbasis 0 dari nilai pada larik
+            objek {@link android.content.ContentProviderResult} dari
+            {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}. Saat
+            operasi batch diterapkan, hasil tiap operasi akan disimpan dalam
+            larik hasil antara. Nilai <code>previousResult</code> adalah indeks
+            dari salah satu hasil ini, yang diambil dan disimpan bersama nilai <code>key</code>.
+ Cara ini memungkinkan Anda menyisipkan record kontak mentah baru dan mendapatkan kembali nilai
+            {@code android.provider.BaseColumns#_ID}-nya, lalu membuat "acuan balik" ke
+            nilai itu saat Anda menambahkan baris {@link android.provider.ContactsContract.Data}.
+            <p>
+                Seluruh larik hasil dibuat saat Anda memanggil
+                {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()} untuk pertama kali,
+                dengan ukuran setara dengan ukuran {@link java.util.ArrayList} dari
+                objek {@link android.content.ContentProviderOperation} yang Anda sediakan. Akan tetapi, semua
+                elemen dalam larik hasil diatur ke <code>null</code>, dan jika Anda mencoba
+                melakukan acuan balik ke hasil untuk operasi yang belum diterapkan,
+{@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()}
+                akan mengeluarkan {@link java.lang.Exception}.
+
+            </p>
+        </dd>
+    </dl>
+<p>
+    Cuplikan kode berikut menampilkan cara menyisipkan kontak mentah baru dan data secara batch. Cuplikan kode ini
+    menyertakan kode yang menetapkan yield point dan menggunakan acuan balik. Cuplikan kode ini adalah
+    versi perluasan dari metode<code>createContacEntry()</code>, yang merupakan bagian dari kelas
+    <code>ContactAdder</code> dalam
+    aplikasi contoh <code><a href="{@docRoot}resources/samples/ContactManager/index.html">
+    Contact Manager</a></code>.
+</p>
+<p>
+    Cuplikan pertama mengambil data kontak dari UI. Pada saat ini, pengguna sudah
+    memilih akun tempat kontak mentah baru harus ditambahkan.
+</p>
+<pre>
+// Creates a contact entry from the current UI values, using the currently-selected account.
+protected void createContactEntry() {
+    /*
+     * Gets values from the UI
+     */
+    String name = mContactNameEditText.getText().toString();
+    String phone = mContactPhoneEditText.getText().toString();
+    String email = mContactEmailEditText.getText().toString();
+
+    int phoneType = mContactPhoneTypes.get(
+            mContactPhoneTypeSpinner.getSelectedItemPosition());
+
+    int emailType = mContactEmailTypes.get(
+            mContactEmailTypeSpinner.getSelectedItemPosition());
+</pre>
+<p>
+    Cuplikan berikutnya membuat operasi untuk menyisipkan baris kontak mentah ke dalam
+    tabel {@link android.provider.ContactsContract.RawContacts}:
+</p>
+<pre>
+    /*
+     * Prepares the batch operation for inserting a new raw contact and its data. Even if
+     * the Contacts Provider does not have any data for this person, you can't add a Contact,
+     * only a raw contact. The Contacts Provider will then add a Contact automatically.
+     */
+
+     // Creates a new array of ContentProviderOperation objects.
+    ArrayList&lt;ContentProviderOperation&gt; ops =
+            new ArrayList&lt;ContentProviderOperation&gt;();
+
+    /*
+     * Creates a new raw contact with its account type (server type) and account name
+     * (user's account). Remember that the display name is not stored in this row, but in a
+     * StructuredName data row. No other data is required.
+     */
+    ContentProviderOperation.Builder op =
+            ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
+            .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType())
+            .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, mSelectedAccount.getName());
+
+    // Builds the operation and adds it to the array of operations
+    ops.add(op.build());
+</pre>
+<p>
+    Berikutnya, kode akan membuat baris data untuk baris-baris nama tampilan, telepon, dan email.
+</p>
+<p>
+    Setiap objek pembangun operasi menggunakan
+    {@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()}
+    untuk mendapatkan
+    {@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID}. Acuan menunjuk
+    balik ke objek {@link android.content.ContentProviderResult} dari operasi pertama,
+    yang menambahkan baris kontak mentah dan mengembalikan nilai {@code android.provider.BaseColumns#_ID}
+    barunya. Hasilnya, setiap data ditautkan secara otomatis oleh
+    {@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID}-nya
+    ke baris {@link android.provider.ContactsContract.RawContacts} baru yang memilikinya.
+</p>
+<p>
+    Objek {@link android.content.ContentProviderOperation.Builder} yang menambahkan baris email
+    diberi flag {@link android.content.ContentProviderOperation.Builder#withYieldAllowed(boolean)
+    withYieldAllowed()}, yang mengatur yield point:
+</p>
+<pre>
+    // Creates the display name for the new raw contact, as a StructuredName data row.
+    op =
+            ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+            /*
+             * withValueBackReference sets the value of the first argument to the value of
+             * the ContentProviderResult indexed by the second argument. In this particular
+             * call, the raw contact ID column of the StructuredName data row is set to the
+             * value of the result returned by the first operation, which is the one that
+             * actually adds the raw contact row.
+             */
+            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
+
+            // Sets the data row's MIME type to StructuredName
+            .withValue(ContactsContract.Data.MIMETYPE,
+                    ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
+
+            // Sets the data row's display name to the name in the UI.
+            .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name);
+
+    // Builds the operation and adds it to the array of operations
+    ops.add(op.build());
+
+    // Inserts the specified phone number and type as a Phone data row
+    op =
+            ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+            /*
+             * Sets the value of the raw contact id column to the new raw contact ID returned
+             * by the first operation in the batch.
+             */
+            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
+
+            // Sets the data row's MIME type to Phone
+            .withValue(ContactsContract.Data.MIMETYPE,
+                    ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
+
+            // Sets the phone number and type
+            .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
+            .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType);
+
+    // Builds the operation and adds it to the array of operations
+    ops.add(op.build());
+
+    // Inserts the specified email and type as a Phone data row
+    op =
+            ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+            /*
+             * Sets the value of the raw contact id column to the new raw contact ID returned
+             * by the first operation in the batch.
+             */
+            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
+
+            // Sets the data row's MIME type to Email
+            .withValue(ContactsContract.Data.MIMETYPE,
+                    ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
+
+            // Sets the email address and type
+            .withValue(ContactsContract.CommonDataKinds.Email.ADDRESS, email)
+            .withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType);
+
+    /*
+     * Demonstrates a yield point. At the end of this insert, the batch operation's thread
+     * will yield priority to other threads. Use after every set of operations that affect a
+     * single contact, to avoid degrading performance.
+     */
+    op.withYieldAllowed(true);
+
+    // Builds the operation and adds it to the array of operations
+    ops.add(op.build());
+</pre>
+<p>
+    Cuplikan terakhir menampilkan panggilan ke
+    {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()} yang
+    menyisipkan baris-baris kontak mentah dan data baru.
+</p>
+<pre>
+    // Ask the Contacts Provider to create a new contact
+    Log.d(TAG,"Selected account: " + mSelectedAccount.getName() + " (" +
+            mSelectedAccount.getType() + ")");
+    Log.d(TAG,"Creating contact: " + name);
+
+    /*
+     * Applies the array of ContentProviderOperation objects in batch. The results are
+     * discarded.
+     */
+    try {
+
+            getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
+    } catch (Exception e) {
+
+            // Display a warning
+            Context ctx = getApplicationContext();
+
+            CharSequence txt = getString(R.string.contactCreationFailure);
+            int duration = Toast.LENGTH_SHORT;
+            Toast toast = Toast.makeText(ctx, txt, duration);
+            toast.show();
+
+            // Log exception
+            Log.e(TAG, "Exception encountered while inserting contact: " + e);
+    }
+}
+</pre>
+<p>
+    Operasi batch juga memungkinkan Anda menerapkan <strong>kontrol konkurensi optimistis</strong>,
+    sebuah metode yang menerapkan transaksi modifikasi tanpa harus mengunci repository yang mendasari.
+    Untuk menggunakan metode ini, terapkan transaksi dan periksa modifikasi lain yang
+    mungkin telah dibuat bersamaan. Jika ternyata modifikasi tidak konsisten, Anda
+    mengembalikan transaksi ke kondisi semula dan mencobanya kembali.
+</p>
+<p>
+    Kontrol konkurensi optimistis berguna untuk perangkat seluler, apabila hanya ada satu pengguna setiap
+   kalinya, dan akses simultan ke repository data jarang terjadi. Karena penguncian tidak digunakan,
+    tidak ada waktu yang terbuang untuk memasang kunci atau menunggu transaksi lain untuk melepas kunci.
+</p>
+<p>
+    Untuk menggunakan kontrol konkurensi optimistis saat memperbarui satu baris
+    {@link android.provider.ContactsContract.RawContacts}, ikuti langkah-langkah ini:
+</p>
+<ol>
+    <li>
+        Ambil kolom {@link android.provider.ContactsContract.SyncColumns#VERSION}
+        kontak mentah bersama data lain yang Anda ambil.
+    </li>
+    <li>
+        Buat sebuah objek {@link android.content.ContentProviderOperation.Builder} yang cocok untuk
+        memberlakukan batasan, dengan menggunakan metode
+        {@link android.content.ContentProviderOperation#newAssertQuery(Uri)}. Untuk URI konten,
+        gunakan {@link android.provider.ContactsContract.RawContacts#CONTENT_URI
+        RawContacts.CONTENT_URI}
+        dengan {@code android.provider.BaseColumns#_ID} kontak mentah yang ditambahkan padanya.
+    </li>
+    <li>
+        Untuk objek {@link android.content.ContentProviderOperation.Builder}, panggil
+        {@link android.content.ContentProviderOperation.Builder#withValue(String, Object)
+        withValue()} untuk membandingkan kolom {@link android.provider.ContactsContract.SyncColumns#VERSION}
+        dengan nomor versi yang baru saja Anda ambil.
+    </li>
+    <li>
+        Untuk {@link android.content.ContentProviderOperation.Builder} yang sama, panggil
+        {@link android.content.ContentProviderOperation.Builder#withExpectedCount(int)
+        withExpectedCount()} untuk memastikan bahwa hanya satu baris yang diuji oleh pernyataan ini.
+    </li>
+    <li>
+        Panggil {@link android.content.ContentProviderOperation.Builder#build()} untuk membuat
+        objek {@link android.content.ContentProviderOperation}, kemudian tambahkan objek ini sebagai
+        objek pertama di {@link java.util.ArrayList} yang Anda teruskan ke
+        {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}.
+    </li>
+    <li>
+        Terapkan transaksi batch.
+    </li>
+</ol>
+<p>
+    Jika baris kontak mentah diperbarui oleh operasi lain antara waktu Anda membaca baris dan
+    waktu Anda mencoba memodifikasinya, "asert" {@link android.content.ContentProviderOperation}
+    akan gagal, dan seluruh batch operasi akan dibatalkan. Anda nanti bisa memilih untuk mencoba ulang
+    batch atau melakukan tindakan lain.
+</p>
+<p>
+    Cuplikan berikut memperagakan cara membuat "asert"
+    {@link android.content.ContentProviderOperation} setelah membuat query satu kontak mentah yang menggunakan
+     {@link android.content.CursorLoader}:
+</p>
+<pre>
+/*
+ * The application uses CursorLoader to query the raw contacts table. The system calls this method
+ * when the load is finished.
+ */
+public void onLoadFinished(Loader&lt;Cursor&gt; loader, Cursor cursor) {
+
+    // Gets the raw contact's _ID and VERSION values
+    mRawContactID = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID));
+    mVersion = cursor.getInt(cursor.getColumnIndex(SyncColumns.VERSION));
+}
+
+...
+
+// Sets up a Uri for the assert operation
+Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, mRawContactID);
+
+// Creates a builder for the assert operation
+ContentProviderOperation.Builder assertOp = ContentProviderOperation.netAssertQuery(rawContactUri);
+
+// Adds the assertions to the assert operation: checks the version and count of rows tested
+assertOp.withValue(SyncColumns.VERSION, mVersion);
+assertOp.withExpectedCount(1);
+
+// Creates an ArrayList to hold the ContentProviderOperation objects
+ArrayList ops = new ArrayList&lt;ContentProviderOperationg&gt;;
+
+ops.add(assertOp.build());
+
+// You would add the rest of your batch operations to "ops" here
+
+...
+
+// Applies the batch. If the assert fails, an Exception is thrown
+try
+    {
+        ContentProviderResult[] results =
+                getContentResolver().applyBatch(AUTHORITY, ops);
+
+    } catch (OperationApplicationException e) {
+
+        // Actions you want to take if the assert operation fails go here
+    }
+</pre>
+<h3 id="Intents">Pengambilan dan modifikasi dengan intent</h3>
+<p>
+    Mengirimkan intent ke aplikasi kontak perangkat memungkinkan Anda mengakses Penyedia Kontak
+    secara tidak langsung. Intent akan memulai UI aplikasi kontak perangkat, tempat pengguna bisa
+    melakukan pekerjaan yang terkait dengan kontak. Dengan tipe akses ini, pengguna bisa:
+    <ul>
+        <li>Memilih kontak dari daftar dan meneruskannya ke aplikasi untuk pekerjaan lebih jauh.</li>
+        <li>Mengedit data kontak yang ada.</li>
+        <li>Memasukkan kontak mentah baru untuk akun mereka.</li>
+        <li>Menghapus kontak atau data kontak.</li>
+    </ul>
+<p>
+    Jika pengguna menyisipkan atau memperbarui data, Anda bisa mengumpulkan data lebih dahulu dan mengirimkannya sebagai
+    bagian dari intent.
+</p>
+<p>
+    Bila Anda menggunakan intent untuk mengakses Penyedia Kontak melalui aplikasi kontak perangkat, Anda
+    tidak perlu menulis UI atau kode sendiri untuk mengakses penyedia. Anda juga tidak harus
+   meminta izin untuk membaca dari atau menulis ke penyedia. Aplikasi kontak perangkat bisa
+    mendelegasikan izin membaca untuk kontak kepada Anda, dan karena Anda membuat modifikasi pada
+    penyedia melalui aplikasi lain, Anda tidak perlu memiliki izin menulis.
+</p>
+<p>
+    Proses umum pengiriman intent untuk mengakses penyedia dijelaskan secara detail dalam panduan
+    <a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
+    Dasar-Dasar Penyedia Konten</a> di bagian "Akses data melalui intent". Tindakan,
+    tipe MIME, dan nilai data yang Anda gunakan untuk tugas yang tersedia dirangkum dalam Tabel 4, sedangkan
+    nilai ekstra yang bisa Anda gunakan bersama
+    {@link android.content.Intent#putExtra(String, String) putExtra()} tercantum dalam
+    dokumentasi acuan untuk {@link android.provider.ContactsContract.Intents.Insert}:
+</p>
+<p class="table-caption" id="table4">
+  <strong>Tabel 4.</strong> Intent Penyedia Kontak.
+</p>
+<table style="width:75%">
+    <tr>
+        <th scope="col" style="width:10%">Tugas</th>
+        <th scope="col" style="width:5%">Tindakan</th>
+        <th scope="col" style="width:10%">Data</th>
+        <th scope="col" style="width:10%">Tipe MIME</th>
+        <th scope="col" style="width:25%">Catatan</th>
+    </tr>
+    <tr>
+        <td><strong>Memilih kontak dari daftar</strong></td>
+        <td>{@link android.content.Intent#ACTION_PICK}</td>
+        <td>
+            Salah satu dari:
+            <ul>
+                <li>
+{@link android.provider.ContactsContract.Contacts#CONTENT_URI Contacts.CONTENT_URI},
+                    yang menampilkan daftar kontak.
+                </li>
+                <li>
+{@link android.provider.ContactsContract.CommonDataKinds.Phone#CONTENT_URI Phone.CONTENT_URI},
+                    yang menampilkan daftar nomor telepon untuk kontak mentah.
+                </li>
+                <li>
+{@link android.provider.ContactsContract.CommonDataKinds.StructuredPostal#CONTENT_URI
+StructuredPostal.CONTENT_URI},
+                    yang menampilkan daftar alamat pos untuk kontak mentah.
+                </li>
+                <li>
+{@link android.provider.ContactsContract.CommonDataKinds.Email#CONTENT_URI Email.CONTENT_URI},
+                    yang menampilkan daftar alamat email untuk kontak baru.
+                </li>
+            </ul>
+        </td>
+        <td>
+            Tidak digunakan
+        </td>
+        <td>
+            Menampilkan daftar kontak mentah atau daftar data dari kontak mentah, sesuai dengan tipe
+            URI konten yang Anda sediakan.
+            <p>
+                Panggil
+         {@link android.app.Activity#startActivityForResult(Intent, int) startActivityForResult()},
+                yang menghasilkan URI konten dari baris terpilih. Bentuk URI adalah
+                URI konten tabel dengan <code>LOOKUP_ID</code> baris yang ditambahkan padanya.
+                Aplikasi kontak perangkat mendelegasikan izin membaca dan menulis untuk URI konten ini
+                selama masa pakai aktivitas Anda. Lihat panduan
+                <a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
+                Dasar-Dasar Penyedia Konten</a> untuk detail selengkapnya.
+            </p>
+        </td>
+    </tr>
+    <tr>
+        <td><strong>Menyisipkan kontak mentah baru</strong></td>
+        <td>{@link android.provider.ContactsContract.Intents.Insert#ACTION Insert.ACTION}</td>
+        <td>N/A</td>
+        <td>
+            {@link android.provider.ContactsContract.RawContacts#CONTENT_TYPE
+            RawContacts.CONTENT_TYPE}, tipe MIME untuk satu set kontak mentah.
+        </td>
+        <td>
+            Menampilkan layar <strong>Add Contact</strong> aplikasi kontak perangkat. Nilai
+            ekstra yang Anda tambahkan ke intent akan ditampilkan. Jika dikirimkan bersama
+        {@link android.app.Activity#startActivityForResult(Intent, int) startActivityForResult()},
+            URI konten dari kontak mentah yang baru saja ditambahkan akan dikembalikan ke
+            {@link android.app.Activity#onActivityResult(int, int, Intent) onActivityResult()}
+           metode callback aktivitas Anda pada argumen {@link android.content.Intent}, di
+            bidang "data". Untuk mendapatkan nilainya, panggil {@link android.content.Intent#getData()}.
+        </td>
+    </tr>
+    <tr>
+        <td><strong>Mengedit kontak</strong></td>
+        <td>{@link android.content.Intent#ACTION_EDIT}</td>
+        <td>
+            {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} untuk
+            kontak. Aktivitas editor memungkinkan pengguna mengedit setiap data yang dikaitkan
+            dengan kontak ini.
+        </td>
+        <td>
+            {@link android.provider.ContactsContract.Contacts#CONTENT_ITEM_TYPE
+            Contacts.CONTENT_ITEM_TYPE}, kontak tunggal.</td>
+        <td>
+            Menampilkan layar Edit Contact dalam aplikasi kontak. Nilai ekstra yang Anda tambahkan
+            ke intent akan ditampilkan. Bila pengguna mengklik <strong>Done</strong> untuk menyimpan
+            hasil edit, aktivitas Anda kembali ke latar depan.
+        </td>
+    </tr>
+    <tr>
+        <td><strong>Menampilkan picker yang juga bisa menambahkan data.</strong></td>
+        <td>{@link android.content.Intent#ACTION_INSERT_OR_EDIT}</td>
+        <td>
+            N/A
+        </td>
+        <td>
+            {@link android.provider.ContactsContract.Contacts#CONTENT_ITEM_TYPE}
+        </td>
+         <td>
+            Intent ini selalu menampilkan layar picker aplikasi kontak. Pengguna bisa memilih
+            kontak untuk diedit, atau menambahkan kontak baru. Layar edit atau layar tambah
+            akan muncul, sesuai dengan pilihan pengguna, dan data ekstra yang Anda kirimkan dalam intent
+            akan ditampilkan. Jika aplikasi Anda menampilkan data kontak seperti email atau nomor telepon, gunakan
+            intent ini untuk memungkinkan pengguna menambahkan data ke kontak yang ada.
+
+            <p class="note">
+                <strong>Catatan:</strong> Tidak perlu mengirimkan nilai nama dalam ekstra intent ini,
+                karena pengguna selalu mengambil nama yang ada atau menambahkan nama baru. Lebih-lebih,
+                jika Anda mengirimkan nama, dan pengguna memilih untuk melakukan edit, aplikasi kontak akan
+                menampilkan nama yang Anda kirimkan, yang menimpa nilai sebelumnya. Jika pengguna tidak
+                menyadari hal ini dan menyimpan hasil edit, nilai lama akan hilang.
+            </p>
+         </td>
+    </tr>
+</table>
+<p>
+    Aplikasi kontak perangkat tidak memperbolehkan Anda menghapus kontak mentah atau datanya dengan
+    intent. Sebagai gantinya, untuk menghapus kontak mentah, gunakan
+    {@link android.content.ContentResolver#delete(Uri, String, String[]) ContentResolver.delete()}
+    atau {@link android.content.ContentProviderOperation#newDelete(Uri)
+    ContentProviderOperation.newDelete()}.
+</p>
+<p>
+    Cuplikan berikut menampilkan cara menyusun dan mengirimkan intent yang menyisipkan kontak dan data
+    mentah baru:
+</p>
+<pre>
+// Gets values from the UI
+String name = mContactNameEditText.getText().toString();
+String phone = mContactPhoneEditText.getText().toString();
+String email = mContactEmailEditText.getText().toString();
+
+String company = mCompanyName.getText().toString();
+String jobtitle = mJobTitle.getText().toString();
+
+// Creates a new intent for sending to the device's contacts application
+Intent insertIntent = new Intent(ContactsContract.Intents.Insert.ACTION);
+
+// Sets the MIME type to the one expected by the insertion activity
+insertIntent.setType(ContactsContract.RawContacts.CONTENT_TYPE);
+
+// Sets the new contact name
+insertIntent.putExtra(ContactsContract.Intents.Insert.NAME, name);
+
+// Sets the new company and job title
+insertIntent.putExtra(ContactsContract.Intents.Insert.COMPANY, company);
+insertIntent.putExtra(ContactsContract.Intents.Insert.JOB_TITLE, jobtitle);
+
+/*
+ * Demonstrates adding data rows as an array list associated with the DATA key
+ */
+
+// Defines an array list to contain the ContentValues objects for each row
+ArrayList&lt;ContentValues&gt; contactData = new ArrayList&lt;ContentValues&gt;();
+
+
+/*
+ * Defines the raw contact row
+ */
+
+// Sets up the row as a ContentValues object
+ContentValues rawContactRow = new ContentValues();
+
+// Adds the account type and name to the row
+rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType());
+rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_NAME, mSelectedAccount.getName());
+
+// Adds the row to the array
+contactData.add(rawContactRow);
+
+/*
+ * Sets up the phone number data row
+ */
+
+// Sets up the row as a ContentValues object
+ContentValues phoneRow = new ContentValues();
+
+// Specifies the MIME type for this data row (all data rows must be marked by their type)
+phoneRow.put(
+        ContactsContract.Data.MIMETYPE,
+        ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE
+);
+
+// Adds the phone number and its type to the row
+phoneRow.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone);
+
+// Adds the row to the array
+contactData.add(phoneRow);
+
+/*
+ * Sets up the email data row
+ */
+
+// Sets up the row as a ContentValues object
+ContentValues emailRow = new ContentValues();
+
+// Specifies the MIME type for this data row (all data rows must be marked by their type)
+emailRow.put(
+        ContactsContract.Data.MIMETYPE,
+        ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE
+);
+
+// Adds the email address and its type to the row
+emailRow.put(ContactsContract.CommonDataKinds.Email.ADDRESS, email);
+
+// Adds the row to the array
+contactData.add(emailRow);
+
+/*
+ * Adds the array to the intent's extras. It must be a parcelable object in order to
+ * travel between processes. The device's contacts app expects its key to be
+ * Intents.Insert.DATA
+ */
+insertIntent.putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, contactData);
+
+// Send out the intent to start the device's contacts app in its add contact activity.
+startActivity(insertIntent);
+</pre>
+<h3 id="DataIntegrity">Integritas data</h3>
+<p>
+    Karena repository kontak berisi data penting dan sensitif yang diharapkan pengguna agar
+    benar dan terbaru. Penyedia Kontak memiliki aturan yang didefinisikan dengan baik demi integritas data. Anda
+    bertanggung jawab untuk mematuhi aturan ini saat memodifikasi data kontak. Aturan-aturan penting itu
+    dicantumkan di sini:
+</p>
+<dl>
+    <dt>
+        Selalu tambahkan baris {@link android.provider.ContactsContract.CommonDataKinds.StructuredName}
+        untuk setiap baris {@link android.provider.ContactsContract.RawContacts} yang Anda tambahkan.
+    </dt>
+    <dd>
+        Baris {@link android.provider.ContactsContract.RawContacts} tanpa
+        baris {@link android.provider.ContactsContract.CommonDataKinds.StructuredName} dalam
+        tabel {@link android.provider.ContactsContract.Data} bisa menyebabkan masalah selama
+       agregasi.
+    </dd>
+    <dt>
+        Selalu tautkan baris {@link android.provider.ContactsContract.Data} baru ke baris
+        {@link android.provider.ContactsContract.RawContacts} induknya.
+    </dt>
+    <dd>
+        Baris {@link android.provider.ContactsContract.Data} yang tidak ditautkan ke
+        {@link android.provider.ContactsContract.RawContacts} tidak akan terlihat dalam aplikasi kontak
+        perangkat, dan itu bisa menimbulkan masalah dengan adaptor sinkronisasi.
+    </dd>
+    <dt>
+        Ubah data hanya untuk kontak mentah yang Anda miliki.
+    </dt>
+    <dd>
+        Ingatlah bahwa Penyedia Kontak biasanya mengelola data dari berbagai
+        tipe akun/layanan online. Anda harus memastikan bahwa aplikasi Anda hanya memodifikasi
+        atau menghapus data untuk baris milik Anda, dan bahwa aplikasi hanya menyisipkan data dengan
+        tipe akun dan nama yang Anda kontrol.
+    </dd>
+    <dt>
+        Selalu gunakan konstanta yang didefinisikan dalam {@link android.provider.ContactsContract} dan
+        subkelasnya untuk otoritas, URI konten, URI path, nama kolom, tipe MIME, dan
+        nilai {@link android.provider.ContactsContract.CommonDataKinds.CommonColumns#TYPE}.
+    </dt>
+    <dd>
+        Menggunakan konstanta ini membantu Anda menghindari kesalahan. Anda juga akan diberi tahu dengan peringatan
+        compiler jika salah satu konstanta sudah usang.
+    </dd>
+</dl>
+<h3 id="CustomData">Baris data custom</h3>
+<p>
+    Dengan membuat dan menggunakan tipe MIME custom sendiri, Anda bisa menyisipkan, mengedit, menghapus, dan mengambil
+    baris data sendiri dalam tabel {@link android.provider.ContactsContract.Data}. Baris Anda
+    dibatasi untuk menggunakan kolom yang didefinisikan dalam
+    {@link android.provider.ContactsContract.DataColumns}, meskipun Anda bisa memetakan nama kolom
+    bertipe spesifik sendiri ke nama kolom default. Dalam aplikasi kontak perangkat,
+    data untuk baris Anda ditampilkan, tetapi tidak bisa diedit atau dihapus, dan pengguna tidak bisa menambahkan
+    data lain. Untuk memudahkan pengguna mengubah baris data custom Anda, Anda harus menyediakan aktivitas
+    editor dalam aplikasi Anda sendiri.
+</p>
+<p>
+    Untuk menampilkan data custom, sediakan file <code>contacts.xml</code> berisi elemen
+    <code>&lt;ContactsAccountType&gt;</code> dan satu atau beberapa elemen anak
+    <code>&lt;ContactsDataKind&gt;</code>. Hal ini dijelaskan lebih detail di
+    bagian <a href="#SocialStreamDataKind"><code>&lt;ContactsDataKind&gt; element</code></a>.
+</p>
+<p>
+    Untuk mengetahui selengkapnya tentang tipe MIME custom, bacalah panduan
+    <a href="{@docRoot}guide/topics/providers/content-provider-creating.html">
+    Membuat Penyedia Konten</a>.
+</p>
+<h2 id="SyncAdapters">Adaptor Sinkronisasi Penyedia Kontak</h2>
+<p>
+    Penyedia Kontak didesain khusus untuk menangani <strong>sinkronisasi</strong>
+    data kontak antara perangkat dan layanan online. Hal ini memungkinkan pengguna mengunduh
+    data yang ada dari perangkat baru dan mengunggah data yang ada ke akun baru.
+    Sinkronisasi juga memastikan bahwa pengguna memiliki data terbaru, apa pun
+    sumber penambahan dan perubahan itu. Keuntungan lain dari sinkronisasi adalah membuat
+    data kontak tersedia sekalipun perangkat tidak terhubung ke jaringan.
+</p>
+<p>
+    Walaupun Anda bisa menerapkan sinkronisasi dengan berbagai cara, sistem Android menyediakan
+    kerangka kerja sinkronisasi plug-in yang mengotomatiskan tugas-tugas berikut:
+    <ul>
+
+    <li>
+        Memeriksa ketersediaan jaringan.
+    </li>
+    <li>
+        Menjadwalkan dan menjalankan sinkronisasi, berdasarkan preferensi pengguna.
+    </li>
+    <li>
+        Memulai kembali sinkronisasi yang telah berhenti.
+    </li>
+    </ul>
+<p>
+    Untuk menggunakan kerangka kerja ini, Anda harus menyediakan plug-in adaptor sinkronisasi. Setiap adaptor sinkronisasi bersifat unik bagi
+    layanan dan penyedia konten, tetapi mampu menangani beberapa nama akun untuk layanan yang sama. Kerangka
+    kerja ini juga memungkinkan beberapa adaptor sinkronisasi untuk layanan dan penyedia yang sama.
+</p>
+<h3 id="SyncClassesFiles">Kelas dan file adaptor sinkronisasi</h3>
+<p>
+    Anda mengimplementasikan adaptor sinkronisasi sebagai subkelas
+    {@link android.content.AbstractThreadedSyncAdapter} dan menginstalnya sebagai bagian dari aplikasi
+    Android. Sistem akan mempelajari adaptor sinkronisasi dari elemen-elemen di manifes
+     aplikasi Anda dan dari file XML khusus yang ditunjuk oleh manifes. File XML mendefinisikan
+    tipe akun untuk layanan online dan otoritas untuk penyedia konten, yang bersama-sama
+    mengidentifikasi adaptor secara unik. Adaptor sinkronisasi tidak menjadi aktif hingga pengguna menambahkan
+    akun untuk tipe akun adaptor sinkronisasi dan memungkinkan sinkronisasi untuk penyedia
+    konten yang disinkronkan dengan adaptor sinkronisasi.  Pada saat itu, sistem mulai mengelola adaptor,
+    memanggilnya seperlunya untuk menyinkronkan antara penyedia konten dan server.
+</p>
+<p class="note">
+    <strong>Catatan:</strong> Menggunakan tipe akun sebagai bagian dari identifikasi adaptor sinkronisasi memungkinkan
+    sistem mendeteksi dan menghimpun adaptor-adaptor sinkronisasi yang mengakses berbagai layanan dari
+    organisasi yang sama. Misalnya, adaptor sinkronisasi untuk semua layanan online Google semuanya memiliki tipe akun
+    yang sama <code>com.google</code>. Bila pengguna menambahkan akun Google ke perangkatnya, semua
+    adaptor sinkronisasi yang terinstal untuk layanan Google akan dicantumkan bersama; setiap adaptor sinkronisasi
+    yang tercantum akan menyinkronkan diri dengan berbagai penyedia konten pada perangkat.
+</p>
+<p>
+    Karena sebagian besar layanan mengharuskan pengguna untuk memeriksa identitas sebelum mengakses
+    data, sistem Android menawarkan kerangka kerja autentikasi yang serupa dengan, dan sering kali
+    digunakan bersama, kerangka kerja adaptor sinkronisasi. Kerangka kerja autentikasi menggunakan
+    autentikator plug-in yang merupakan subkelas
+    {@link android.accounts.AbstractAccountAuthenticator}. Autentikator memeriksa
+    identitas pengguna dalam langkah-langkah berikut:
+    <ol>
+        <li>
+            Mengumpulkan nama pengguna, kata sandi, atau informasi serupa (
+            <strong>kredensial</strong> pengguna).
+        </li>
+        <li>
+            Mengirimkan kredensial ke layanan
+        </li>
+        <li>
+            Memeriksa balasan layanan.
+        </li>
+    </ol>
+<p>
+    Jika layanan menerima kredensial, autentikator bisa
+    menyimpan kredensial itu untuk digunakan nanti. Karena kerangka kerja autentikator plug-in,
+    {@link android.accounts.AccountManager} bisa menyediakan akses ke setiap token autentikasi yang didukung suatu autentikator
+    dan dipilihnya untuk diekspos, seperti token autentikasi OAuth2.
+</p>
+<p>
+    Meskipun autentikasi tidak diharuskan, sebagian besar layanan kontak menggunakannya.
+    Akan tetapi, Anda tidak wajib menggunakan kerangka kerja autentikasi Android untuk melakukan autentikasi.
+</p>
+<h3 id="SyncAdapterImplementing">Implementasi adaptor sinkronisasi</h3>
+<p>
+    Untuk mengimplementasikan adaptor sinkronisasi bagi Penyedia Kontak, perlu Anda memulai dengan membuat
+    aplikasi Android yang berisi elemen-elemen berikut:
+</p>
+    <dl>
+        <dt>
+            Komponen {@link android.app.Service} yang merespons permintaan sistem untuk
+            mengikat ke adaptor sinkronisasi.
+        </dt>
+        <dd>
+            Bila sistem ingin menjalankan sinkronisasi, sistem akan memanggil metode
+            {@link android.app.Service#onBind(Intent) onBind()} layanan untuk mendapatkan
+            {@link android.os.IBinder} bagi adaptor sinkronisasi. Hal ini memungkinkan sistem melakukan
+            panggilan lintas proses ke metode adaptor.
+            <p>
+                Dalam contoh aplikasi <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">
+               Sample Sync Adapter</a>, nama kelas layanan ini adalah
+                <code>com.example.android.samplesync.syncadapter.SyncService</code>.
+            </p>
+        </dd>
+        <dt>
+            Adaptor sinkronisasi yang sesungguhnya, diimplementasikan sebagai subkelas konkret dari
+            {@link android.content.AbstractThreadedSyncAdapter}.
+        </dt>
+        <dd>
+            Kelas ini melakukan pekerjaan mengunduh data dari server, mengunggah data ke
+            perangkat, dan menyelesaikan konflik. Pekerjaan utama adaptor
+            diselesaikan dengan metode {@link android.content.AbstractThreadedSyncAdapter#onPerformSync(
+            Account, Bundle, String, ContentProviderClient, SyncResult)
+            onPerformSync()}. Instance kelas ini harus dibuat sebagai singleton.
+            <p>
+                Dalam contoh aplikasi <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">
+               Sample Sync Adapter</a>, adaptor sinkronisasi didefinisikan dalam kelas
+                <code>com.example.android.samplesync.syncadapter.SyncAdapter</code>.
+            </p>
+        </dd>
+        <dt>
+            Subkelas {@link android.app.Application}.
+        </dt>
+        <dd>
+            Kelas ini berfungsi sebagai pabrik untuk singleton adaptor sinkronisasi. Gunakan
+            metode {@link android.app.Application#onCreate()} untuk membuat instance adaptor sinkronisasi , dan
+            menyediakan metode "getter" statis untuk mengembalikan singleton ke
+            metode {@link android.app.Service#onBind(Intent) onBind()} dari layanan
+            adaptor sinkronisasi.
+        </dd>
+        <dt>
+            <strong>Opsional:</strong> Komponen {@link android.app.Service} yang merespons
+            permintaan dari sistem untuk autentikasi pengguna.
+        </dt>
+        <dd>
+            {@link android.accounts.AccountManager} memulai layanan ini untuk memulai proses
+            autentikasi. Metode {@link android.app.Service#onCreate()} layanan membuat instance
+            objek autentikator. Bila sistem ingin mengautentikasi akun pengguna untuk
+            adaptor sinkronisasi aplikasi, sistem akan memanggil metode
+{@link android.app.Service#onBind(Intent) onBind()}            layanan guna mendapatkan
+            {@link android.os.IBinder} bagi autentikator. Hal ini memungkinkan sistem melakukan
+            panggilan lintas proses ke metode autentikator.
+            <p>
+                Dalam contoh aplikasi <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">
+               Sample Sync Adapter</a>, nama kelas layanan ini adalah
+                <code>com.example.android.samplesync.authenticator.AuthenticationService</code>.
+            </p>
+        </dd>
+        <dt>
+            <strong>Opsional:</strong> Subkelas konkret
+            {@link android.accounts.AbstractAccountAuthenticator} yang menangani permintaan
+            autentikasi.
+        </dt>
+        <dd>
+            Kelas ini menyediakan metode yang dipicu {@link android.accounts.AccountManager}
+            untuk mengautentikasi kredensial pengguna dengan layanan. Detail
+            proses autentikasi sangat bervariasi, berdasarkan teknologi server yang digunakan. Anda harus
+            mengacu ke dokumentasi bagi perangkat lunak server untuk mengetahui selengkapnya tentang autentikasi.
+            <p>
+                Dalam contoh aplikasi <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">
+               Sample Sync Adapter</a>, autentikator didefinisikan dalam kelas
+                <code>com.example.android.samplesync.authenticator.Authenticator</code>.
+            </p>
+        </dd>
+        <dt>
+            File XML yang mendefinisikan adaptor sinkronisasi dan autentikator bagi sistem.
+        </dt>
+        <dd>
+            Komponen-komponen layanan adaptor sinkronisasi dan autentikator
+            didefinisikan dalam elemen-elemen
+<code>&lt;<a href="{@docRoot}guide/topics/manifest/service-element.html">service</a>&gt;</code>
+            di manifes aplikasi. Elemen-elemen ini
+            berisi
+<code>&lt;<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">meta-data</a>&gt;</code>
+elemen anak yang menyediakan data tertentu ke
+            sistem:
+            <ul>
+                <li>
+                    Elemen
+<code>&lt;<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">meta-data</a>&gt;</code>
+                    untuk layanan adaptor sinkronisasi menunjuk ke
+                    file XML <code>res/xml/syncadapter.xml</code>. Pada gilirannya, file ini mendefinisikan
+                    URI untuk layanan web yang akan disinkronkan dengan Penyedia Kontak,
+                    dan tipe akun untuk layanan web.
+                </li>
+                <li>
+                    <strong>Opsional:</strong> Elemen
+<code>&lt;<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">meta-data</a>&gt;</code>
+                   untuk autentikator menunjuk ke file XML
+                    <code>res/xml/authenticator.xml</code>. Pada gilirannya, file ini menetapkan
+                    tipe akun yang didukung autentikator, serta sumber daya UI yang
+                    muncul selama proses autentikasi. Tipe akun yang ditetapkan dalam elemen ini
+                    harus sama dengan tipe akun yang ditetapkan untuk adaptor
+                    sinkronisasi.
+                </li>
+            </ul>
+        </dd>
+    </dl>
+<h2 id="SocialStream">Data Aliran Sosial</h2>
+<p>
+    Tabel-tabel {@code android.provider.ContactsContract.StreamItems} dan
+    {@code android.provider.ContactsContract.StreamItemPhotos}
+    mengelola data yang masuk dari jaringan sosial. Anda bisa menulis adaptor sinkronisasi yang menambahkan data aliran
+    dari jaringan Anda sendiri ke tabel-tabel ini, atau Anda bisa membaca data aliran dari tabel-tabel ini dan
+    menampilkannya dalam aplikasi sendiri, atau keduanya. Dengan fitur-fitur ini, layanan dan aplikasi
+    jaringan sosial Anda bisa diintegrasikan ke dalam pengalaman jaringan sosial Android.
+</p>
+<h3 id="StreamText">Teks aliran sosial</h3>
+<p>
+    Item aliran selalu dikaitkan dengan kontak mentah.
+    {@code android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID} menautkan ke
+    nilai <code>_ID</code> untuk kontak mentah. Tipe akun dan nama akun kontak
+    mentah juga disimpan dalam baris item aliran.
+</p>
+<p>
+    Simpanlah data dari aliran Anda dalam kolom-kolom berikut:
+</p>
+<dl>
+    <dt>
+        {@code android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_TYPE}
+    </dt>
+    <dd>
+        <strong>Diperlukan.</strong> Tipe akun pengguna untuk kontak mentah yang dikaitkan dengan
+        item aliran ini. Ingatlah untuk mengatur nilai ini saat Anda menyisipkan item aliran.
+    </dd>
+    <dt>
+        {@code android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_NAME}
+    </dt>
+    <dd>
+        <strong>Diperlukan.</strong> Nama akun pengguna untuk kontak mentah yang dikaitkan dengan
+        item aliran ini. Ingatlah untuk mengatur nilai ini saat Anda menyisipkan item aliran.
+    </dd>
+    <dt>
+        Kolom identifier
+    </dt>
+    <dd>
+        <strong>Diperlukan.</strong> Anda harus memasukkan kolom identifier berikut saat
+        menyisipkan item aliran:
+        <ul>
+            <li>
+                {@code android.provider.ContactsContract.StreamItemsColumns#CONTACT_ID}:
+                Nilai {@code android.provider.BaseColumns#_ID} kontak yang dikaitkan dengan item aliran
+                ini.
+            </li>
+            <li>
+                {@code android.provider.ContactsContract.StreamItemsColumns#CONTACT_LOOKUP_KEY}:
+                Nilai {@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY}
+                kontak yang dikaitkan dengan item aliran ini.
+            </li>
+            <li>
+                {@code android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID}:
+                Nilai {@code android.provider.BaseColumns#_ID} kontak mentah yang dikaitkan dengan item aliran
+                ini.
+            </li>
+        </ul>
+    </dd>
+    <dt>
+        {@code android.provider.ContactsContract.StreamItemsColumns#COMMENTS}
+    </dt>
+    <dd>
+        Opsional. Menyimpan informasi rangkuman yang bisa Anda tampilkan di awal item aliran.
+    </dd>
+    <dt>
+        {@code android.provider.ContactsContract.StreamItemsColumns#TEXT}
+    </dt>
+    <dd>
+        Teks item aliran, baik konten yang diposting oleh sumber item,
+        maupun keterangan beberapa tindakan yang menghasilkan item aliran. Kolom ini bisa berisi
+        sembarang gambar sumber daya pemformatan dan tertanam yang bisa dirender oleh
+        {@link android.text.Html#fromHtml(String) fromHtml()}. Penyedia bisa memotong atau
+        menghapus konten yang panjang, tetapi penyedia akan mencoba menghindari memutus tag.
+    </dd>
+    <dt>
+        {@code android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP}
+    </dt>
+    <dd>
+        String teks berisi waktu item aliran yang disisipkan atau diperbarui, berupa
+        <em>milidetik</em> sejak waktu patokan. Aplikasi yang menyisipkan atau memperbarui item aliran
+        bertanggung jawab memelihara kolom ini; aplikasi tidak dipelihara secara otomatis oleh
+        Penyedia Kontak.
+    </dd>
+</dl>
+<p>
+    Untuk menampilkan informasi pengidentifikasi item aliran Anda, gunakan
+    {@code android.provider.ContactsContract.StreamItemsColumns#RES_ICON},
+    {@code android.provider.ContactsContract.StreamItemsColumns#RES_LABEL}, dan
+    {@code android.provider.ContactsContract.StreamItemsColumns#RES_PACKAGE} untuk menautkan ke sumber daya
+    dalam aplikasi Anda.
+</p>
+<p>
+    Tabel {@code android.provider.ContactsContract.StreamItems} juga berisi kolom-kolom
+    {@code android.provider.ContactsContract.StreamItemsColumns#SYNC1} hingga
+    {@code android.provider.ContactsContract.StreamItemsColumns#SYNC4} untuk penggunaan eksklusif oleh
+    adaptor sinkronisasi.
+</p>
+<h3 id="StreamPhotos">Foto aliran sosial</h3>
+<p>
+   Tabel {@code android.provider.ContactsContract.StreamItemPhotos} menyimpan foto-foto yang dikaitkan
+   dengan item aliran. Kolom
+{@code android.provider.ContactsContract.StreamItemPhotosColumns#STREAM_ITEM_ID}   tabel ini
+   menautkan ke nilai dalam kolom {@code android.provider.BaseColumns#_ID}
+   tabel {@code android.provider.ContactsContract.StreamItems}. Acuan foto disimpan dalam
+   tabel pada kolom-kolom ini:
+</p>
+<dl>
+    <dt>
+        Kolom {@code android.provider.ContactsContract.StreamItemPhotos#PHOTO} (BLOB).
+    </dt>
+    <dd>
+        Representasi biner foto, yang diubah ukurannya oleh penyedia untuk penyimpanan dan tampilan.
+        Kolom ini tersedia untuk kompatibilitas ke belakang dengan versi Penyedia Kontak
+        sebelumnya yang menggunakannya untuk menyimpan foto. Akan tetapi, pada versi saat ini
+        Anda tidak boleh menggunakan kolom ini untuk menyimpan foto. Sebagai gantinya, gunakan
+         {@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID} atau
+        {@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI} (keduanya
+        dijelaskan dalam poin-poin berikut) untuk menyimpan foto di file. Kolom ini sekarang
+        berisi thumbnail foto, yang tersedia untuk dibaca.
+    </dd>
+    <dt>
+        {@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID}
+    </dt>
+    <dd>
+        Identifier numerik foto untuk kontak mentah. Tambahkan nilai ini ke konstanta
+        {@link android.provider.ContactsContract.DisplayPhoto#CONTENT_URI DisplayPhoto.CONTENT_URI}
+        untuk mendapatkan URI konten yang menunjuk ke satu file foto, kemudian panggil
+        {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String)
+        openAssetFileDescriptor()} untuk mendapatkan handle ke file foto.
+    </dd>
+    <dt>
+        {@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI}
+    </dt>
+    <dd>
+        URI konten menunjuk langsung ke file foto untuk foto yang diwakili oleh baris ini.
+        Panggillah {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String)
+        openAssetFileDescriptor()} dengan URI ini untuk mendapatkan handle ke file foto.
+    </dd>
+</dl>
+<h3 id="SocialStreamTables">Menggunakan tabel aliran sosial</h3>
+<p>
+    Tabel-tabel ini sama fungsinya dengan tabel-tabel utama lainnya dalam Penyedia Kontak, kecuali:
+</p>
+    <ul>
+        <li>
+            Tabel-tabel ini memerlukan izin akses tambahan. Untuk membaca dari tabel, aplikasi Anda
+            harus memiliki izin {@code android.Manifest.permission#READ_SOCIAL_STREAM}. Untuk memodifikasi
+            tabel, aplikasi Anda harus memiliki izin
+            {@code android.Manifest.permission#WRITE_SOCIAL_STREAM}.
+        </li>
+        <li>
+            Untuk tabel {@code android.provider.ContactsContract.StreamItems}, jumlah baris
+            yang disimpan bagi setiap kontak mentah adalah terbatas. Setelah batasnya tercapai,
+            Penyedia Kontak akan membuat ruang untuk baris item aliran baru dengan menghapus secara otomatis
+            baris yang memiliki
+            {@code android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP} terlama. Untuk mendapatkan
+            batas, keluarkan query ke URI konten
+            {@code android.provider.ContactsContract.StreamItems#CONTENT_LIMIT_URI}. Anda bisa membiarkan
+            semua argumen selain URI konten diatur ke <code>null</code>. Query
+            menghasilkan sebuah Kursor yang berisi baris tunggal, dengan kolom tunggal
+            {@code android.provider.ContactsContract.StreamItems#MAX_ITEMS}.
+        </li>
+    </ul>
+
+<p>
+    Kelas {@code android.provider.ContactsContract.StreamItems.StreamItemPhotos} mendefinisikan
+    subtabel {@code android.provider.ContactsContract.StreamItemPhotos} yang berisi
+    baris foto untuk satu item aliran.
+</p>
+<h3 id="SocialStreamInteraction">Interaksi aliran sosial</h3>
+<p>
+    Data aliran sosial yang dikelola oleh Penyedia Kontak, bersama aplikasi kontak
+    perangkat, menawarkan cara andal untuk menghubungkan sistem jaringan sosial Anda
+    dengan kontak yang ada. Tersedia fitur-fitur berikut:
+</p>
+    <ul>
+        <li>
+            Dengan menyinkronkan layanan jaringan sosial ke Penyedia Kontak dengan adaptor
+            sinkronisasi, Anda bisa mengambil aktivitas terbaru untuk kontak pengguna dan menyimpannya dalam tabel-tabel
+             {@code android.provider.ContactsContract.StreamItems} dan
+            {@code android.provider.ContactsContract.StreamItemPhotos} untuk digunakan nanti.
+        </li>
+        <li>
+            Selain sinkronisasi rutin, Anda bisa memicu adaptor sinkronisasi agar mengambil
+            data tambahan bila pengguna memilih sebuah kontak untuk ditampilkan. Hal ini memungkinkan adaptor sinkronisasi Anda
+            mengambil foto resolusi tinggi dan item aliran terbaru untuk kontak.
+        </li>
+        <li>
+            Dengan mendaftarkan pemberitahuan pada aplikasi kontak perangkat dan Penyedia Kontak,
+            Anda bisa <em>menerima</em> intent saat kontak ditampilkan, dan pada saat itu
+            memperbarui status kontak dari layanan Anda. Pendekatan ini mungkin lebih cepat dan menggunakan
+            bandwidth lebih sedikit daripada melakukan sinkronisasi penuh dengan adaptor sinkronisasi.
+        </li>
+        <li>
+            Pengguna bisa menambahkan kontak ke layanan jaringan sosial Anda sambil melihat kontak
+            dalam aplikasi kontak perangkat. Anda mengaktifkannya dengan fitur "invite contact",
+            yang Anda aktifkan dengan kombinasi aktivitas yang menambahkan kontak yang ada ke jaringan
+           Anda, dan file XML yang menyediakan aplikasi kontak perangkat dan
+            Penyedia Kontak dengan detail aplikasi Anda.
+        </li>
+    </ul>
+<p>
+    Sinkronisasi rutin item aliran dengan Penyedia Kontak sama dengan
+    sinkronisasi lainnya. Untuk mengetahui selengkapnya tentang sinkronisasi, lihat bagian
+    <a href="#SyncAdapters">Adaptor Sinkronisasi Penyedia Kontak</a>. Mendaftarkan pemberitahuan dan
+    mengundang kontak dibahas dalam dua bagian berikutnya.
+</p>
+<h4>Pendaftaran untuk menangani tampilan jaringan sosial</h4>
+<p>
+    Untuk mendaftarkan adaptor sinkronisasi agar menerima pemberitahuan saat pengguna menampilkan kontak
+    yang dikelola oleh adaptor sinkronisasi Anda:
+</p>
+<ol>
+    <li>
+        Buat file yang bernama <code>contacts.xml</code> dalam direktori <code>res/xml/</code>
+        proyek Anda. Jika sudah memiliki file ini, langkah ini boleh dilewati.
+    </li>
+    <li>
+        Dalam file ini, tambahkan elemen
+<code>&lt;ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android"&gt;</code>.
+        Jika elemen ini sudah ada, langkah ini boleh dilewati.
+    </li>
+    <li>
+        Untuk mendaftarkan layanan yang diberitahukan saat pengguna membuka halaman detail kontak dalam
+        aplikasi kontak perangkat, tambahkan atribut
+        <code>viewContactNotifyService="<em>serviceclass</em>"</code> ke elemen, dengan
+        <code><em>serviceclass</em></code> sebagai nama kelas mutlak (fully qualified) dari layanan
+        yang seharusnya menerima intent dari aplikasi kontak perangkat. Untuk layanan
+        notifier, gunakan kelas yang memperluas {@link android.app.IntentService}, guna memudahkan layanan
+        untuk menerima intent. Data dalam intent yang masuk berisi URI konten dari kontak
+        mentah yang diklik pengguna. Untuk layanan notifier, Anda bisa mengikatnya ke kemudian memanggil
+        adaptor sinkronisasi Anda untuk memperbarui data bagi kontak mentah.
+    </li>
+</ol>
+<p>
+    Untuk mendaftarkan aktivitas agar dipanggil saat pengguna mengklik item aliran atau foto atau keduanya:
+</p>
+<ol>
+    <li>
+        Buat file yang bernama <code>contacts.xml</code> dalam direktori <code>res/xml/</code>
+        proyek Anda. Jika sudah memiliki file ini, langkah ini boleh dilewati.
+    </li>
+    <li>
+        Dalam file ini, tambahkan elemen
+<code>&lt;ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android"&gt;</code>.
+        Jika elemen ini sudah ada, langkah ini boleh dilewati.
+    </li>
+    <li>
+        Untuk mendaftarkan salah satu aktivitas Anda guna menangani klik oleh pengguna pada item aliran dalam
+        aplikasi kontak perangkat, tambahkan atribut
+        <code>viewStreamItemActivity="<em>activityclass</em>"</code> ke elemen, dengan
+        <code><em>activityclass</em></code> sebagai nama kelas mutlak (fully-qualified) dari aktivitas
+        yang harus menerima intent dari aplikasi kontak perangkat.
+    </li>
+    <li>
+        Untuk mendaftarkan salah satu aktivitas Anda guna menangani klik oleh pengguna pada foto aliran dalam
+        aplikasi kontak perangkat, tambahkan atribut
+        <code>viewStreamItemPhotoActivity="<em>activityclass</em>"</code> ke elemen, dengan
+        <code><em>activityclass</em></code> adalah kelas nama mutlak aktivitas
+        yang harus menerima intent dari aplikasi kontak perangkat.
+    </li>
+</ol>
+<p>
+    Elemen <code>&lt;ContactsAccountType&gt;</code> dijelaskan lebih detail di
+    bagian <a href="#SocialStreamAcctType">Elemen &lt;ContactsAccountType&gt;</a>.
+</p>
+<p>
+    Intent yang masuk berisi URI konten dari materi atau foto yang diklik pengguna.
+    Untuk mendapatkan aktivitas terpisah bagi item teks dan foto, gunakan kedua atribut dalam file yang sama.
+</p>
+<h4>Berinteraksi dengan layanan jaringan sosial Anda</h4>
+<p>
+    Pengguna tidak harus meninggalkan aplikasi perangkat kontak untuk mengundang kontak ke situs
+    jaringan sosial Anda. Sebagai gantinya, Anda bisa meminta aplikasi kontak perangkat mengirimkan intent untuk mengundang
+    kontak ke salah satu aktivitas Anda. Untuk mempersiapkannya:
+</p>
+<ol>
+    <li>
+        Buat file yang bernama <code>contacts.xml</code> dalam direktori <code>res/xml/</code>
+        proyek Anda. Jika sudah memiliki file ini, langkah ini boleh dilewati.
+    </li>
+    <li>
+        Dalam file ini, tambahkan elemen
+<code>&lt;ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android"&gt;</code>.
+        Jika elemen ini sudah ada, langkah ini boleh dilewati.
+    </li>
+    <li>
+        Tambahkan atribut-atribut berikut:
+        <ul>
+            <li><code>inviteContactActivity="<em>activityclass</em>"</code></li>
+            <li>
+                <code>inviteContactActionLabel="&#64;string/<em>invite_action_label</em>"</code>
+            </li>
+        </ul>
+        Nilai <code><em>activityclass</em></code> adalah nama kelas mutlak
+        aktivitas yang harus menerima intent ini. Nilai <code><em>invite_action_label</em></code>
+        adalah string teks yang ditampilkan dalam menu <strong>Add Connection</strong> dalam
+        aplikasi kontak perangkat.
+    </li>
+</ol>
+<p class="note">
+    <strong>Catatan:</strong> <code>ContactsSource</code> adalah nama tag yang sudah usang untuk
+    <code>ContactsAccountType</code>.
+</p>
+<h3 id="ContactsFile">Acuan contacts.xml</h3>
+<p>
+    File <code>contacts.xml</code> berisi elemen XML yang mengontrol interaksi adaptor sinkronisasi
+    Anda dan aplikasi dengan aplikasi kontak dan Penyedia Kontak. Elemen-elemen ini
+    dijelaskan di bagian-bagian selanjutnya.
+</p>
+<h4 id="SocialStreamAcctType">Elemen &lt;ContactsAccountType&gt;</h4>
+<p>
+    Elemen <code>&lt;ContactsAccountType&gt;</code> mengontrol interaksi aplikasi
+    Anda dengan aplikasi kontak. Sintaksnya adalah sebagai berikut:
+</p>
+<pre>
+&lt;ContactsAccountType
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        inviteContactActivity="<em>activity_name</em>"
+        inviteContactActionLabel="<em>invite_command_text</em>"
+        viewContactNotifyService="<em>view_notify_service</em>"
+        viewGroupActivity="<em>group_view_activity</em>"
+        viewGroupActionLabel="<em>group_action_text</em>"
+        viewStreamItemActivity="<em>viewstream_activity_name</em>"
+        viewStreamItemPhotoActivity="<em>viewphotostream_activity_name</em>"&gt;
+</pre>
+<p>
+    <strong>dimuat dalam:</strong>
+</p>
+<p>
+    <code>res/xml/contacts.xml</code>
+</p>
+<p>
+    <strong>bisa berisi:</strong>
+</p>
+<p>
+    <strong><code>&lt;ContactsDataKind&gt;</code></strong>
+</p>
+<p>
+    <strong>Keterangan:</strong>
+</p>
+<p>
+    Mendeklarasikan komponen Android dan label UI yang memungkinkan pengguna mengundang salah satu kontak ke
+    jaringan sosial, memberi tahu pengguna bila salah satu aliran jaringan sosial diperbarui, dan
+    seterusnya.
+</p>
+<p>
+    Perhatikan bahwa awalan atribut <code>android:</code> tidak perlu untuk atribut-atribut
+    <code>&lt;ContactsAccountType&gt;</code>.
+</p>
+<p>
+    <strong>Atribut:</strong>
+</p>
+<dl>
+    <dt>{@code inviteContactActivity}</dt>
+    <dd>
+        Nama kelas mutlak aktivitas dalam aplikasi yang Anda ingin
+        aktifkan bila pengguna memilih <strong>Add connection</strong> dari aplikasi kontak
+        perangkat.
+    </dd>
+    <dt>{@code inviteContactActionLabel}</dt>
+    <dd>
+        String teks yang ditampilkan untuk aktivitas yang ditetapkan dalam
+        {@code inviteContactActivity}, dalam menu <strong>Add connection</strong>.
+        Misalnya, Anda bisa menggunakan string "Ikuti di jaringan saya". Anda bisa menggunakan identifier sumber daya
+        string untuk tabel ini.
+    </dd>
+    <dt>{@code viewContactNotifyService}</dt>
+    <dd>
+        Nama kelas mutlak layanan dalam aplikasi Anda yang harus menerima
+        pemberitahuan saat pengguna menampilkan kontak. Pemberitahuan ini dikirimkan oleh aplikasi kontak
+        perangkat; hal ini memungkinkan aplikasi Anda menunda operasi yang banyak memproses data
+        hingga dibutuhkan. Misalnya, aplikasi Anda bisa merespons pemberitahuan ini
+        dengan membaca dalam dan menampilkan foto resolusi tinggi kontak dan item aliran sosial
+        terbaru. Fitur ini dijelaskan lebih detail di bagian
+        <a href="#SocialStreamInteraction">Interaksi aliran sosial</a>. Anda bisa melihat
+        contoh layanan pemberitahuan dalam file <code>NotifierService.java</code> dalam contoh aplikasi
+        <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">Sample Sync Adapter</a>.
+
+    </dd>
+    <dt>{@code viewGroupActivity}</dt>
+    <dd>
+        Nama kelas mutlak aktivitas dalam aplikasi yang bisa menampilkan
+        informasi grup. Bila pengguna mengklik label grup dalam aplikasi
+        kontak perangkat, UI aktivitas ini akan ditampilkan.
+    </dd>
+    <dt>{@code viewGroupActionLabel}</dt>
+    <dd>
+        Label yang ditampilkan aplikasi kontak untuk kontrol UI yang memungkinkan
+        pengguna melihat grup dalam aplikasi Anda.
+        <p>
+            Misalnya, jika Anda menginstal aplikasi Google+ di perangkat dan menyinkronkan
+            Google+ dengan aplikasi kontak, Anda akan melihat lingkaran Google+ tercantum sebagai grup
+            dalam tab <strong>Groups</strong> aplikasi kontak Anda. Jika Anda mengklik
+            lingkaran Google+, Anda akan melihat orang-orang di lingkaran itu tercantum sebagai satu "grup". Di atas
+            tampilan, Anda akan melihat ikon Google+; jika mengklik ikon itu, kontrol akan beralih ke
+            aplikasi Google+. Aplikasi kontak melakukan ini dengan
+            {@code viewGroupActivity}, yang menggunakan ikon Google+ sebagai nilai
+            {@code viewGroupActionLabel}.
+        </p>
+        <p>
+            Identifier sumber daya string diperbolehkan untuk atribut ini.
+        </p>
+    </dd>
+    <dt>{@code viewStreamItemActivity}</dt>
+    <dd>
+        Nama kelas mutlak aktivitas dalam aplikasi Anda
+        yang diluncurkan aplikasi kontak perangkat bila pengguna mengklik item aliran untuk kontak mentah.
+    </dd>
+    <dt>{@code viewStreamItemPhotoActivity}</dt>
+    <dd>
+        Nama kelas mutlak aktivitas yang diluncurkan
+        aplikasi kontak perangkat bila pengguna mengklik foto dalam item aliran
+        untuk kontak mentah.
+    </dd>
+</dl>
+<h4 id="SocialStreamDataKind">Elemen &lt;ContactsDataKind&gt;</h4>
+<p>
+    Elemen <code>&lt;ContactsDataKind&gt;</code> mengontrol tampilan baris data custom
+    aplikasi Anda dalam UI aplikasi kontak. Sintaksnya adalah sebagai berikut:
+</p>
+<pre>
+&lt;ContactsDataKind
+        android:mimeType="<em>MIMEtype</em>"
+        android:icon="<em>icon_resources</em>"
+        android:summaryColumn="<em>column_name</em>"
+        android:detailColumn="<em>column_name</em>"&gt;
+</pre>
+<p>
+    <strong>dimuat dalam:</strong>
+</p>
+<code>&lt;ContactsAccountType&gt;</code>
+<p>
+    <strong>Keterangan:</strong>
+</p>
+<p>
+    Gunakan elemen ini untuk memerintahkan aplikasi kontak agar menampilkan konten baris data custom sebagai
+    bagian dari detail kontak mentah. Setiap elemen anak <code>&lt;ContactsDataKind&gt;</code>
+    <code>&lt;ContactsAccountType&gt;</code> mewakili tipe baris data custom yang
+    ditambahkan adaptor sinkronisasi Anda ke tabel {@link android.provider.ContactsContract.Data}. Tambahkan satu
+    elemen <code>&lt;ContactsDataKind&gt;</code> untuk setiap tipe MIME custom yang Anda gunakan. Anda tidak harus
+    menambahkan elemen jika Anda memiliki baris data custom yang datanya tidak ingin ditampilkan.
+</p>
+<p>
+    <strong>Atribut:</strong>
+</p>
+<dl>
+    <dt>{@code android:mimeType}</dt>
+    <dd>
+        Tipe MIME custom yang telah Anda definisikan untuk salah satu tipe baris data custom dalam
+        tabel {@link android.provider.ContactsContract.Data}. Misalnya, nilai
+        <code>vnd.android.cursor.item/vnd.example.locationstatus</code> bisa berupa tipe MIME
+       custom untuk baris data yang mencatat lokasi kontak yang terakhir diketahui.
+    </dd>
+    <dt>{@code android:icon}</dt>
+    <dd>
+
+        <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Sumber daya drawable</a>
+        Android yang ditampilkan aplikasi kontak di samping data Anda. Gunakan ini untuk menunjukkan kepada
+        pengguna bahwa data berasal dari layanan Anda.
+    </dd>
+    <dt>{@code android:summaryColumn}</dt>
+    <dd>
+        Nama kolom untuk yang pertama dari dua nilai yang diambil dari baris data. Nilai
+        ditampilkan sebagai baris pertama entri untuk baris data ini. Baris pertama
+        dimaksudkan untuk digunakan sebagai rangkuman data, tetapi itu bersifat opsional. Lihat juga
+        <a href="#detailColumn">android:detailColumn</a>.
+    </dd>
+    <dt>{@code android:detailColumn}</dt>
+    <dd>
+        Nama kolom untuk yang kedua dari dua nilai yang diambil dari baris data. Nilai
+        ditampilkan sebagai baris kedua entri untuk baris data ini. Lihat juga
+        {@code android:summaryColumn}.
+    </dd>
+</dl>
+<h2 id="AdditionalFeatures">Fitur Tambahan Penyedia Kontak</h2>
+<p>
+    Di samping fitur-fitur utama yang dijelaskan di bagian sebelumnya, Penyedia Kontak menawarkan
+   fitur-fitur berguna ini untuk digunakan bersama data kontak:
+</p>
+    <ul>
+       <li>Grup kontak</li>
+       <li>Fitur foto</li>
+    </ul>
+<h3 id="Groups">Grup kontak</h3>
+<p>
+    Penyedia Kontak secara opsional bisa melabeli kumpulan kontak terkait dengan data
+    <strong>grup</strong>. Jika server yang dikaitkan dengan akun pengguna
+    ingin mempertahankan grup, adaptor sinkronisasi untuk tipe akun dari akun itu harus mentransfer
+    data grup antara Penyedia Kontak dan server. Bila pengguna menambahkan kontak baru ke
+    server, kemudian memasukkan kontak ini dalam grup baru, adaptor sinkronisasi harus menambahkan grup baru
+    ke tabel {@link android.provider.ContactsContract.Groups}. Grup atau grup-grup yang memiliki kontak
+    disimpan dalam tabel {@link android.provider.ContactsContract.Data}, dengan menggunakan
+    tipe MIME {@link android.provider.ContactsContract.CommonDataKinds.GroupMembership}.
+</p>
+<p>
+    Jika Anda mendesain adaptor sinkronisasi yang akan menambahkan data kontak mentah dari
+    server ke Penyedia Kontak, dan Anda tidak menggunakan grup, maka Anda harus memberi tahu
+    penyedia itu agar membuat data Anda terlihat. Dalam kode yang dijalankan bila pengguna menambahkan akun
+    ke perangkat, perbarui baris {@link android.provider.ContactsContract.Settings}
+    yang ditambahkan Penyedia Kontak untuk akunnya. Dalam baris ini, atur nilai kolom
+    {@link android.provider.ContactsContract.SettingsColumns#UNGROUPED_VISIBLE
+    Settings.UNGROUPED_VISIBLE} ke 1. Bila melakukannya, Penyedia Kontak akan selalu
+    membuat data kontak Anda terlihat, meskipun Anda tidak menggunakan grup.
+</p>
+<h3 id="Photos">Foto kontak</h3>
+<p>
+    Tabel {@link android.provider.ContactsContract.Data} menyimpan foto sebagai baris dengan tipe MIME
+    {@link android.provider.ContactsContract.CommonDataKinds.Photo#CONTENT_ITEM_TYPE
+    Photo.CONTENT_ITEM_TYPE}. Kolom
+    {@link android.provider.ContactsContract.RawContactsColumns#CONTACT_ID} baris yang ditautkan ke
+    kolom {@code android.provider.BaseColumns#_ID} kontak mentah yang memiliki kolom itu.
+    Kelas {@link android.provider.ContactsContract.Contacts.Photo} mendefinisikan subtabel
+    {@link android.provider.ContactsContract.Contacts} yang berisi informasi foto untuk foto
+    utama kontak, yang merupakan foto utama dari kontak mentah utama kontak itu. Demikian pula,
+    kelas {@link android.provider.ContactsContract.RawContacts.DisplayPhoto} mendefinisikan subtabel
+    {@link android.provider.ContactsContract.RawContacts} yang berisi informasi foto untuk
+    foto utama kontak mentah.
+</p>
+<p>
+    Dokumentasi acuan untuk {@link android.provider.ContactsContract.Contacts.Photo} dan
+    {@link android.provider.ContactsContract.RawContacts.DisplayPhoto} berisi contoh-contoh
+    pengambilan informasi foto. Tidak ada kelas praktis untuk mengambil
+    thumbnail utama kontak mentah, tetapi Anda bisa mengirim query ke
+    tabel {@link android.provider.ContactsContract.Data}, dengan memilih
+    {@code android.provider.BaseColumns#_ID} kontak mentah,
+    {@link android.provider.ContactsContract.CommonDataKinds.Photo#CONTENT_ITEM_TYPE
+    Photo.CONTENT_ITEM_TYPE}, dan kolom {@link android.provider.ContactsContract.Data#IS_PRIMARY}
+    untuk menemukan baris foto utama kontak mentah.
+</p>
+<p>
+    Data aliran sosial untuk seseorang bisa juga disertai foto. Data ini disimpan dalam
+    tabel {@code android.provider.ContactsContract.StreamItemPhotos}, yang dijelaskan lebih detail
+    di bagian <a href="#StreamPhotos">Foto aliran sosial</a>.
+</p>
diff --git a/docs/html-intl/intl/id/guide/topics/providers/content-provider-basics.jd b/docs/html-intl/intl/id/guide/topics/providers/content-provider-basics.jd
new file mode 100644
index 0000000..4af9277
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/providers/content-provider-basics.jd
@@ -0,0 +1,1196 @@
+page.title=Dasar-Dasar Penyedia Konten
+@jd:body
+<div id="qv-wrapper">
+<div id="qv">
+<!-- In this document -->
+<h2>Dalam dokumen ini</h2>
+<ol>
+    <li>
+        <a href="#Basics">Ikhtisar</a>
+        <ol>
+            <li>
+                <a href="#ClientProvider">Mengakses penyedia</a>
+            </li>
+            <li>
+                <a href="#ContentURIs">URI Konten</a>
+            </li>
+        </ol>
+    </li>
+    <li>
+        <a href="#SimpleQuery">Mengambil Data dari Penyedia</a>
+        <ol>
+            <li>
+                <a href="#RequestPermissions">Meminta izin akses baca</a>
+            </li>
+            <li>
+                <a href="#Query">Membuat query</a>
+            </li>
+            <li>
+                <a href="#DisplayResults">Menampilkan hasil query</a>
+            </li>
+            <li>
+                <a href="#GettingResults">Mendapatkan data dari hasil query</a>
+            </li>
+        </ol>
+    </li>
+    <li>
+        <a href="#Permissions">Izin Penyedia Konten</a>
+    </li>
+    <li>
+        <a href="#Modifications">Menyisipkan, Memperbarui, dan Menghapus Data</a>
+        <ol>
+            <li>
+                <a href="#Inserting">Menyisipkan data</a>
+            </li>
+            <li>
+                <a href="#Updating">Memperbarui data</a>
+            </li>
+            <li>
+                <a href="#Deleting">Menghapus data</a>
+            </li>
+        </ol>
+    </li>
+    <li>
+        <a href="#DataTypes">Tipe Data Penyedia</a>
+    </li>
+    <li>
+        <a href="#AltForms">Bentuk-Bentuk Alternatif Akses Penyedia</a>
+        <ol>
+            <li>
+                <a href="#Batch">Akses batch</a>
+            </li>
+            <li>
+                <a href="#Intents">Akses data melalui intent</a>
+            </li>
+        </ol>
+    </li>
+    <li>
+        <a href="#ContractClasses">Kelas-kelas Kontrak</a>
+    </li>
+    <li>
+        <a href="#MIMETypeReference">Acuan Tipe MIME</a>
+    </li>
+</ol>
+
+    <!-- Key Classes -->
+<h2>Kelas-kelas utama</h2>
+    <ol>
+        <li>
+            {@link android.content.ContentProvider}
+        </li>
+        <li>
+            {@link android.content.ContentResolver}
+        </li>
+        <li>
+            {@link android.database.Cursor}
+        </li>
+        <li>
+            {@link android.net.Uri}
+        </li>
+    </ol>
+
+    <!-- Related Samples -->
+<h2>Contoh-Contoh Terkait</h2>
+    <ol>
+        <li>
+        <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/List2.html">
+        Kursor (Orang)</a>
+        </li>
+        <li>
+        <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/List7.html">
+        Kursor (Telepon)</a>
+        </li>
+    </ol>
+
+    <!-- See also -->
+<h2>Lihat juga</h2>
+    <ol>
+        <li>
+            <a href="{@docRoot}guide/topics/providers/content-provider-creating.html">
+            Membuat Penyedia Konten</a>
+        </li>
+        <li>
+            <a href="{@docRoot}guide/topics/providers/calendar-provider.html">
+            Penyedia Kalender</a>
+        </li>
+    </ol>
+</div>
+</div>
+
+    <!-- Intro paragraphs -->
+<p>
+    Penyedia konten mengelola akses ke repository data pusat. Penyedia
+    adalah bagian dari aplikasi Android, yang sering menyediakan UI-nya sendiri untuk menggunakan
+    data. Akan tetapi, penyedia konten terutama dimaksudkan untuk digunakan oleh
+    aplikasi lain, yang mengakses penyedia itu melalui objek klien penyedia. Bersama-sama, penyedia
+    dan klien penyedia menawarkan antarmuka standar yang konsisten ke data yang juga menangani
+    komunikasi antar-proses dan akses data aman.
+</p>
+<p>
+    Topik ini menerangkan dasar-dasar dari hal-hal berikut:
+</p>
+    <ul>
+        <li>Cara kerja penyedia konten.</li>
+        <li>API yang Anda gunakan untuk mengambil data dari penyedia konten.</li>
+        <li>API yang Anda gunakan untuk menyisipkan, memperbarui, atau menghapus data dalam penyedia konten.</li>
+        <li>Fitur API lainnya yang memudahkan kita menggunakan penyedia.</li>
+    </ul>
+
+    <!-- Basics -->
+<h2 id="Basics">Ikhtisar</h2>
+<p>
+    Penyedia konten menyajikan data ke aplikasi eksternal sebagai satu atau beberapa tabel yang
+    serupa dengan tabel-tabel yang ditemukan dalam database relasional. Sebuah baris mewakili instance beberapa tipe
+    data yang dikumpulkan penyedia, dan tiap kolom dalam baris mewakili sepotong
+    data yang dikumpulkan untuk sebuah instance.
+</p>
+<p>
+    Misalnya, salah satu penyedia bawaan di platform Android adalah kamus pengguna, yang
+    menyimpan ejaan kata-kata tidak-standar yang ingin disimpan pengguna. Tabel 1 mengilustrasikan
+    wujud data yang mungkin ada dalam tabel penyedia ini:
+</p>
+<p class="table-caption">
+    <strong>Tabel 1:</strong> Contoh tabel kamus pengguna.
+</p>
+<table id="table1" style="width: 50%;">
+    <tr>
+        <th style="width:20%" align="center" scope="col">word</th>
+        <th style="width:20%" align="center" scope="col">app id</th>
+        <th style="width:20%" align="center" scope="col">frequency</th>
+        <th style="width:20%" align="center" scope="col">locale</th>
+        <th style="width:20%" align="center" scope="col">_ID</th>
+    </tr>
+    <tr>
+        <td align="center" scope="row">mapreduce</td>
+        <td align="center">user1</td>
+        <td align="center">100</td>
+        <td align="center">en_US</td>
+        <td align="center">1</td>
+    </tr>
+    <tr>
+        <td align="center" scope="row">precompiler</td>
+        <td align="center">user14</td>
+        <td align="center">200</td>
+        <td align="center">fr_FR</td>
+        <td align="center">2</td>
+    </tr>
+    <tr>
+        <td align="center" scope="row">applet</td>
+        <td align="center">user2</td>
+        <td align="center">225</td>
+        <td align="center">fr_CA</td>
+        <td align="center">3</td>
+    </tr>
+    <tr>
+        <td align="center" scope="row">const</td>
+        <td align="center">user1</td>
+        <td align="center">255</td>
+        <td align="center">pt_BR</td>
+        <td align="center">4</td>
+    </tr>
+    <tr>
+        <td align="center" scope="row">int</td>
+        <td align="center">user5</td>
+        <td align="center">100</td>
+        <td align="center">en_UK</td>
+        <td align="center">5</td>
+    </tr>
+</table>
+<p>
+    Dalam tabel 1, tiap baris mewakili instance sebuah kata yang mungkin tidak
+    ditemukan dalam kamus standar. Tiap kolom mewakili beberapa data untuk kata itu, misalnya
+    bahasa lokal tempat kata itu ditemukan kali pertama. Header kolom adalah nama kolom yang disimpan dalam
+    penyedia. Untuk mengacu ke bahasa lokal suatu baris, Anda mengacu ke kolom <code>locale</code>-nya. Untuk
+    penyedia ini, kolom <code>_ID</code> berfungsi sebagai "kunci utama" kolom yang
+    dipelihara oleh penyedia secara otomatis.
+</p>
+<p class="note">
+    <strong>Catatan:</strong> Penyedia tidak diharuskan memiliki kunci utama, dan tidak diharuskan
+    menggunakan <code>_ID</code> sebagai nama kolom kunci utama jika kunci itu ada. Akan tetapi,
+    jika Anda ingin mengikat data dari penyedia ke {@link android.widget.ListView}, salah satu
+    nama kolom harus <code>_ID</code>. Ketentuan ini dijelaskan secara lebih detail di bagian
+    <a href="#DisplayResults">Menampilkan hasil query</a>.
+</p>
+<h3 id="ClientProvider">Mengakses penyedia</h3>
+<p>
+    Aplikasi mengakses data dari penyedia konten dengan
+    sebuah objek klien {@link android.content.ContentResolver}. Objek ini memiliki metode yang memanggil
+    metode dengan nama identik dalam objek penyedia, instance salah satu
+    subkelas konkret dari {@link android.content.ContentProvider}. Metode-metode
+    {@link android.content.ContentResolver} menyediakan fungsi-fungsi dasar
+    "CRUD" (create, retrieve, update, dan delete) pada penyimpanan yang persisten.
+</p>
+<p>
+    Objek {@link android.content.ContentResolver} dalam
+    proses aplikasi klien dan objek {@link android.content.ContentProvider} dalam aplikasi yang memiliki
+    penyedia itu secara otomatis akan menangani komunikasi antar-proses.
+    {@link android.content.ContentProvider} juga berfungsi sebagai lapisan abstraksi antara
+    repository datanya dan penampilan eksternal data sebagai tabel.
+</p>
+<p class="note">
+    <strong>Catatan:</strong> Untuk mengakses penyedia, aplikasi Anda biasanya harus meminta
+    izin tertentu dalam file manifesnya. Hal ini dijelaskan lebih detail di bagian
+    <a href="#Permissions">Izin Penyedia Konten</a>
+</p>
+<p>
+    Misalnya, untuk mendapatkan daftar kata dan lokalnya dari Penyedia Kamus Pengguna,
+    Anda memanggil {@link android.content.ContentResolver#query ContentResolver.query()}.
+    Metode {@link android.content.ContentResolver#query query()} memanggil
+    metode {@link android.content.ContentProvider#query ContentProvider.query()} yang didefinisikan oleh
+    Penyedia Kamus Pengguna. Baris-baris kode berikut menunjukkan sebuah
+    panggilan {@link android.content.ContentResolver#query ContentResolver.query()}:
+<p>
+<pre>
+// Queries the user dictionary and returns results
+mCursor = getContentResolver().query(
+    UserDictionary.Words.CONTENT_URI,   // The content URI of the words table
+    mProjection,                        // The columns to return for each row
+    mSelectionClause                    // Selection criteria
+    mSelectionArgs,                     // Selection criteria
+    mSortOrder);                        // The sort order for the returned rows
+</pre>
+<p>
+    Tabel 2 menampilkan cara argumen untuk
+    {@link android.content.ContentResolver#query
+    query(Uri,projection,selection,selectionArgs,sortOrder)} cocok dengan sebuah pernyataan SELECT di SQL:
+</p>
+<p class="table-caption">
+    <strong>Tabel 2:</strong> Query() dibandingkan dengan query SQL.
+</p>
+<table id="table2" style="width: 75%;">
+    <tr>
+        <th style="width:25%" align="center" scope="col">Argumen query()</th>
+        <th style="width:25%" align="center" scope="col">Kata kunci/parameter SELECT</th>
+        <th style="width:50%" align="center" scope="col">Catatan</th>
+    </tr>
+    <tr>
+        <td align="center"><code>Uri</code></td>
+        <td align="center"><code>FROM <em>table_name</em></code></td>
+        <td><code>Uri</code> memetakan ke tabel dalam penyedia yang bernama <em>table_name</em>.</td>
+    </tr>
+    <tr>
+        <td align="center"><code>projection</code></td>
+        <td align="center"><code><em>col,col,col,...</em></code></td>
+        <td>
+            <code>projection</code> adalah satu larik kolom yang harus disertakan untuk tiap baris
+            yang diambil.
+        </td>
+    </tr>
+    <tr>
+        <td align="center"><code>selection</code></td>
+        <td align="center"><code>WHERE <em>col</em> = <em>value</em></code></td>
+        <td><code>selection</code> menetapkan kriteria untuk memilih baris.</td>
+    </tr>
+    <tr>
+        <td align="center"><code>selectionArgs</code></td>
+        <td align="center">
+            (Tidak ada padanan persis. Argumen pemilihan mengganti <code>?</code> placeholder dalam
+            klausa pemilihan.)
+        </td>
+    </tr>
+    <tr>
+        <td align="center"><code>sortOrder</code></td>
+        <td align="center"><code>ORDER BY <em>col,col,...</em></code></td>
+        <td>
+            <code>sortOrder</code> menetapkan urutan munculnya baris dalam
+            {@link android.database.Cursor} yang dihasilkan.
+        </td>
+    </tr>
+</table>
+<h3 id="ContentURIs">URI Konten</h3>
+<p>
+    <strong>URI konten</strong> adalah URI yang mengidentifikasi data dalam penyedia. URI Konten
+    menyertakan nama simbolis seluruh penyedia (<strong>otoritas</strong>nya) dan sebuah
+    nama yang menunjuk ke tabel (<strong>path</strong>). Bila Anda memanggil
+    metode klien untuk mengakses tabel dalam penyedia, URI konten untuk tabel itu adalah salah satu
+    argumennya.
+</p>
+<p>
+    Dalam baris kode sebelumnya, konstanta
+    {@link android.provider.UserDictionary.Words#CONTENT_URI} mengandung URI konten dari
+    tabel "words" kamus pengguna. Objek {@link android.content.ContentResolver}
+    akan mengurai otoritas URI, dan menggunakannya untuk "mengetahui" penyedia dengan
+    membandingkan otoritas tersebut dengan sebuah tabel sistem berisi penyedia yang dikenal.
+{@link android.content.ContentResolver}    kemudian bisa mengirim argumen query ke penyedia
+    yang benar.
+</p>
+<p>
+    {@link android.content.ContentProvider} menggunakan bagian path dari URI konten untuk memilih
+    tabel yang akan diakses. Penyedia biasanya memiliki <strong>path</strong> untuk tiap tabel yang dieksposnya.
+</p>
+<p>
+    Dalam baris kode sebelumnya, URI lengkap untuk tabel "words" adalah:
+</p>
+<pre>
+content://user_dictionary/words
+</pre>
+<p>
+    dalam hal ini string <code>user_dictionary</code> adalah otoritas penyedia, dan string
+    <code>words</code> adalah path tabel. String
+    <code>content://</code> (<strong>skema</strong>) selalu ada,
+    dan mengidentifikasinya sebagai URI konten.
+</p>
+<p>
+    Banyak penyedia yang memperbolehkan Anda mengakses satu baris dalam tabel dengan menambahkan sebuah ID nilai
+    ke akhir URI. Misalnya, untuk mengambil sebuah baris yang <code>_ID</code>-nya adalah
+    <code>4</code> dari kamus pengguna, Anda bisa menggunakan URI konten ini:
+</p>
+<pre>
+Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);
+</pre>
+<p>
+    Anda akan sering menggunakan nilai-nilai ID bila telah mengambil satu set baris kemudian ingin memperbarui atau menghapus
+    salah satunya.
+</p>
+<p class="note">
+    <strong>Catatan:</strong> Kelas-kelas {@link android.net.Uri} dan {@link android.net.Uri.Builder}
+    berisi metode praktis untuk membangun objek dari string URI yang tersusun dengan baik.
+{@link android.content.ContentUris}    berisi metode praktis untuk menambahkan nilai ID ke
+    URI. Cuplikan kode sebelumnya menggunakan {@link android.content.ContentUris#withAppendedId
+    withAppendedId()} untuk menambahkan id ke URI konten User Dictionary.
+</p>
+
+
+    <!-- Retrieving Data from the Provider -->
+<h2 id="SimpleQuery">Mengambil Data dari Penyedia</h2>
+<p>
+    Bagian ini menerangkan cara mengambil data dari penyedia, dengan menggunakan Penyedia Kamus Pengguna
+    sebagai contoh.
+</p>
+<p class="note">
+    Demi kejelasan, cuplikan kode di bagian ini memanggil
+    {@link android.content.ContentResolver#query ContentResolver.query()} pada "UI thread"". Akan tetapi, dalam
+    kode sesungguhnya, Anda harus melakukan query secara asinkron pada sebuah thread terpisah. Satu cara melakukannya
+    adalah menggunakan kelas {@link android.content.CursorLoader}, yang dijelaskan
+    lebih detail dalam panduan <a href="{@docRoot}guide/components/loaders.html">
+    Loader</a>. Juga, baris-baris kode tersebut hanyalah cuplikan; tidak menunjukkan sebuah aplikasi
+     lengkap.
+</p>
+<p>
+    Untuk mengambil data dari penyedia, ikutilah langkah-langkah dasar ini:
+</p>
+<ol>
+   <li>
+        Minta izin akses baca untuk penyedia itu.
+   </li>
+   <li>
+        Definisikan kode yang mengirim query ke penyedia.
+   </li>
+</ol>
+<h3 id="RequestPermissions">Meminta izin akses baca</h3>
+<p>
+    Untuk mengambil data dari penyedia, aplikasi Anda memerlukan "izin akses baca" untuk
+    penyedia itu. Anda tidak bisa meminta izin ini saat runtime; sebagai gantinya, Anda harus menetapkan bahwa
+    Anda memerlukan izin ini dalam manifes, dengan menggunakan elemen
+<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
+    dan nama persis izin yang didefinisikan oleh
+    penyedia itu. Bila menetapkan elemen ini dalam manifes, Anda secara efektif "meminta"
+    izin ini untuk aplikasi Anda. Bila pengguna menginstal aplikasi Anda, mereka secara implisit akan memberikan
+    permintaan ini.
+</p>
+<p>
+    Untuk menemukan nama persis dari izin akses baca untuk penyedia yang sedang Anda gunakan, serta
+    nama-nama izin akses lain yang digunakan oleh penyedia, lihatlah dalam
+    dokumentasi penyedia.
+</p>
+<p>
+    Peran izin dalam yang mengakses penyedia dijelaskan lebih detail di bagian
+    <a href="#Permissions">Izin Penyedia Konten</a>.
+</p>
+<p>
+    Penyedia Kamus Pengguna mendefinisikan izin
+    <code>android.permission.READ_USER_DICTIONARY</code> dalam file manifesnya, sehingga
+    aplikasi yang ingin membaca dari penyedia itu harus meminta izin ini.
+</p>
+<!-- Constructing the query -->
+<h3 id="Query">Membuat query</h3>
+<p>
+    Langkah berikutnya dalam mengambil data penyedia adalah membuat query. Cuplikan kode pertama ini
+    mendefinisikan beberapa variabel untuk mengakses Penyedia Kamus Pengguna:
+</p>
+<pre class="prettyprint">
+
+// A "projection" defines the columns that will be returned for each row
+String[] mProjection =
+{
+    UserDictionary.Words._ID,    // Contract class constant for the _ID column name
+    UserDictionary.Words.WORD,   // Contract class constant for the word column name
+    UserDictionary.Words.LOCALE  // Contract class constant for the locale column name
+};
+
+// Defines a string to contain the selection clause
+String mSelectionClause = null;
+
+// Initializes an array to contain selection arguments
+String[] mSelectionArgs = {""};
+
+</pre>
+<p>
+    Cuplikan berikutnya menampilkan cara menggunakan
+    {@link android.content.ContentResolver#query ContentResolver.query()}, dengan menggunakan Penyedia Kamus Pengguna
+    sebagai contoh. Query klien penyedia serupa dengan query SQL, dan berisi satu
+    set kolom yang akan dihasilkan, satu set kriteria pemilihan, dan urutan sortir.
+</p>
+<p>
+    Set kolom yang harus dikembalikan query disebut dengan <strong>proyeksi</strong>
+    (variabel <code>mProjection</code>).
+</p>
+<p>
+    Ekspresi yang menetapkan baris yang harus diambil dipecah menjadi klausa pemilihan dan
+    argumen pemilihan. Klausa pemilihan adalah kombinasi ekspresi logis dan boolean,
+    nama kolom, dan nilai (variabel <code>mSelectionClause</code>). Jika Anda menetapkan
+    parameter <code>?</code> yang bisa diganti, sebagai ganti nilai, metode query akan mengambil nilai
+    dari larik argumen pemilihan (variabel <code>mSelectionArgs</code>).
+</p>
+<p>
+    Dalam cuplikan berikutnya, jika pengguna tidak memasukkan sebuah kata, klausa pemilihan akan diatur ke
+    <code>null</code>, dan query menghasilkan semua kata dalam penyedia. Jika pengguna memasukkan
+    sebuah kata, klausa pemilihan akan diatur ke <code>UserDictionary.Words.WORD + " = ?"</code> dan
+    elemen pertama larik argumen pemilihan diatur ke kata yang dimasukkan pengguna.
+</p>
+<pre class="prettyprint">
+/*
+ * This defines a one-element String array to contain the selection argument.
+ */
+String[] mSelectionArgs = {""};
+
+// Gets a word from the UI
+mSearchString = mSearchWord.getText().toString();
+
+// Remember to insert code here to check for invalid or malicious input.
+
+// If the word is the empty string, gets everything
+if (TextUtils.isEmpty(mSearchString)) {
+    // Setting the selection clause to null will return all words
+    mSelectionClause = null;
+    mSelectionArgs[0] = "";
+
+} else {
+    // Constructs a selection clause that matches the word that the user entered.
+    mSelectionClause = UserDictionary.Words.WORD + " = ?";
+
+    // Moves the user's input string to the selection arguments.
+    mSelectionArgs[0] = mSearchString;
+
+}
+
+// Does a query against the table and returns a Cursor object
+mCursor = getContentResolver().query(
+    UserDictionary.Words.CONTENT_URI,  // The content URI of the words table
+    mProjection,                       // The columns to return for each row
+    mSelectionClause                   // Either null, or the word the user entered
+    mSelectionArgs,                    // Either empty, or the string the user entered
+    mSortOrder);                       // The sort order for the returned rows
+
+// Some providers return null if an error occurs, others throw an exception
+if (null == mCursor) {
+    /*
+     * Insert code here to handle the error. Be sure not to use the cursor! You may want to
+     * call android.util.Log.e() to log this error.
+     *
+     */
+// If the Cursor is empty, the provider found no matches
+} else if (mCursor.getCount() &lt; 1) {
+
+    /*
+     * Insert code here to notify the user that the search was unsuccessful. This isn't necessarily
+     * an error. You may want to offer the user the option to insert a new row, or re-type the
+     * search term.
+     */
+
+} else {
+    // Insert code here to do something with the results
+
+}
+</pre>
+<p>
+    Query ini analog dengan pernyataan SQL:
+</p>
+<pre>
+SELECT _ID, word, locale FROM words WHERE word = &lt;userinput&gt; ORDER BY word ASC;
+</pre>
+<p>
+    Dalam pernyataan SQL ini, nama kolom yang sesungguhnya digunakan sebagai ganti konstanta kelas kontrak.
+</p>
+<h4 id="Injection">Melindungi dari input merusak</h4>
+<p>
+    Jika data dikelola oleh penyedia konten berada dalam database SQL, memasukkan data tak dipercaya eksternal
+    ke dalam pernyataan SQL mentah bisa menyebabkan injeksi SQL.
+</p>
+<p>
+    Perhatikan klausa pemilihan ini:
+</p>
+<pre>
+// Constructs a selection clause by concatenating the user's input to the column name
+String mSelectionClause =  "var = " + mUserInput;
+</pre>
+<p>
+    Jika melakukannya, Anda akan membuat pengguna menyambungkan SQL merusak ke pernyataan SQL Anda.
+    Misalnya, pengguna bisa memasukkan "nothing; DROP TABLE *;"  untuk <code>mUserInput</code>, yang
+    akan menghasilkan klausa pemilihan <code>var = nothing; DROP TABLE *;</code>. Karena
+    klausa pemilihan diperlakukan sebagai pernyataan SQL, hal ini bisa menyebabkan penyedia itu menghapus semua
+    tabel dalam database SQLite yang mendasarinya (kecuali penyedia disiapkan untuk menangkap upaya
+    <a href="http://en.wikipedia.org/wiki/SQL_injection">injeksi SQL</a>).
+</p>
+<p>
+    Untuk menghindari masalah ini, gunakan klausa pemilihan yang menggunakan <code>?</code> sebagai
+    parameter yang bisa diganti dan larik argumen pemilihan yang terpisah. Bila Anda melakukannya, input pengguna
+    akan dibatasi secara langsung pada query agar tidak ditafsirkan sebagai bagian dari pernyataan SQL.
+    Karena tidak diperlakukan sebagai SQL, input pengguna tidak bisa menyuntikkan SQL merusak. Sebagai ganti menggunakan
+    penyambungan untuk menyertakan input pengguna, gunakan klausa pemilihan ini:
+</p>
+<pre>
+// Constructs a selection clause with a replaceable parameter
+String mSelectionClause =  "var = ?";
+</pre>
+<p>
+    Buat larik argumen pemilihan seperti ini:
+</p>
+<pre>
+// Defines an array to contain the selection arguments
+String[] selectionArgs = {""};
+</pre>
+<p>
+    Masukkan nilai dalam larik argumen pemilihan seperti ini:
+</p>
+<pre>
+// Sets the selection argument to the user's input
+selectionArgs[0] = mUserInput;
+</pre>
+<p>
+    Sebuah klausa pemilihan yang menggunakan <code>?</code> sebagai parameter yang bisa diganti dan sebuah larik
+    argumen pemilihan adalah cara yang lebih disukai untuk menyebutkan pemilihan, sekalipun penyedia tidak
+    dibuat berdasarkan database SQL.
+</p>
+<!-- Displaying the results -->
+<h3 id="DisplayResults">Menampilkan hasil query</h3>
+<p>
+    Metode klien {@link android.content.ContentResolver#query ContentResolver.query()} selalu
+    menghasilkan {@link android.database.Cursor} berisi kolom-kolom yang ditetapkan oleh
+    proyeksi query untuk baris yang cocok dengan kriteria pemilihan query. Objek
+    {@link android.database.Cursor} menyediakan akses baca acak ke baris dan kolom yang
+    dimuatnya. Dengan metode {@link android.database.Cursor}, Anda bisa mengulang baris-baris dalam
+    hasil, menentukan tipe data tiap kolom, mengambil data dari kolom, dan memeriksa
+    properti lain dari hasil. Beberapa implementasi {@link android.database.Cursor}
+    akan memperbarui objek secara otomatis bila data penyedia berubah, atau memicu metode dalam objek pengamat
+    bila {@link android.database.Cursor} berubah, atau keduanya.
+</p>
+<p class="note">
+    <strong>Catatan:</strong> Penyedia bisa membatasi akses ke kolom berdasarkan sifat
+    objek yang membuat query. Misalnya, Penyedia Kontak membatasi akses untuk beberapa kolom pada
+    adaptor sinkronisasi, sehingga tidak akan mengembalikannya ke aktivitas atau layanan.
+</p>
+<p>
+    Jika tidak ada baris yang cocok dengan kriteria pemilihan, penyedia
+    akan mengembalikan objek {@link android.database.Cursor} dengan
+    {@link android.database.Cursor#getCount Cursor.getCount()} adalah 0 (kursor kosong).
+</p>
+<p>
+    Jika terjadi kesalahan internal, hasil query akan bergantung pada penyedia tertentu. Penyedia bisa
+    memilih untuk menghasilkan <code>null</code>, atau melontarkan {@link java.lang.Exception}.
+</p>
+<p>
+    Karena {@link android.database.Cursor} adalah "daftar" baris, cara yang cocok untuk menampilkan
+    konten {@link android.database.Cursor} adalah mengaitkannya dengan {@link android.widget.ListView}
+    melalui {@link android.widget.SimpleCursorAdapter}.
+</p>
+<p>
+    Cuplikan berikut melanjutkan kode dari cuplikan sebelumnya. Cuplikan ini membuat
+    objek {@link android.widget.SimpleCursorAdapter} berisi {@link android.database.Cursor}
+    yang diambil oleh query, dan mengatur objek ini menjadi adaptor bagi
+    {@link android.widget.ListView}:
+</p>
+<pre class="prettyprint">
+// Defines a list of columns to retrieve from the Cursor and load into an output row
+String[] mWordListColumns =
+{
+    UserDictionary.Words.WORD,   // Contract class constant containing the word column name
+    UserDictionary.Words.LOCALE  // Contract class constant containing the locale column name
+};
+
+// Defines a list of View IDs that will receive the Cursor columns for each row
+int[] mWordListItems = { R.id.dictWord, R.id.locale};
+
+// Creates a new SimpleCursorAdapter
+mCursorAdapter = new SimpleCursorAdapter(
+    getApplicationContext(),               // The application's Context object
+    R.layout.wordlistrow,                  // A layout in XML for one row in the ListView
+    mCursor,                               // The result from the query
+    mWordListColumns,                      // A string array of column names in the cursor
+    mWordListItems,                        // An integer array of view IDs in the row layout
+    0);                                    // Flags (usually none are needed)
+
+// Sets the adapter for the ListView
+mWordList.setAdapter(mCursorAdapter);
+</pre>
+<p class="note">
+    <strong>Catatan:</strong> Untuk mendukung {@link android.widget.ListView} dengan
+    {@link android.database.Cursor}, kursor harus berisi kolom bernama <code>_ID</code>.
+    Karena itu, query yang ditampilkan sebelumnya mengambil kolom <code>_ID</code> untuk
+    tabel "words", walaupun {@link android.widget.ListView} tidak menampilkannya.
+    Pembatasan ini juga menjelaskan mengapa sebagian besar penyedia memiliki kolom <code>_ID</code> untuk masing-masing
+    tabelnya.
+</p>
+
+        <!-- Getting data from query results -->
+<h3 id="GettingResults">Mendapatkan data dari hasil query</h3>
+<p>
+    Daripada sekadar menampilkan hasil query, Anda bisa menggunakannya untuk tugas-tugas lain. Misalnya,
+    Anda bisa mengambil ejaan dari kamus pengguna kemudian mencarinya dalam
+    penyedia lain. Caranya, ulangi baris-baris dalam {@link android.database.Cursor}:
+</p>
+<pre class="prettyprint">
+
+// Determine the column index of the column named "word"
+int index = mCursor.getColumnIndex(UserDictionary.Words.WORD);
+
+/*
+ * Only executes if the cursor is valid. The User Dictionary Provider returns null if
+ * an internal error occurs. Other providers may throw an Exception instead of returning null.
+ */
+
+if (mCursor != null) {
+    /*
+     * Moves to the next row in the cursor. Before the first movement in the cursor, the
+     * "row pointer" is -1, and if you try to retrieve data at that position you will get an
+     * exception.
+     */
+    while (mCursor.moveToNext()) {
+
+        // Gets the value from the column.
+        newWord = mCursor.getString(index);
+
+        // Insert code here to process the retrieved word.
+
+        ...
+
+        // end of while loop
+    }
+} else {
+
+    // Insert code here to report an error if the cursor is null or the provider threw an exception.
+}
+</pre>
+<p>
+    Implementasi {@link android.database.Cursor} berisi beberapa metode "get" untuk
+    mengambil berbagai tipe data dari objek. Misalnya, cuplikan sebelumnya
+    menggunakan {@link android.database.Cursor#getString getString()}. Implementasi juga memiliki
+    metode {@link android.database.Cursor#getType getType()} yang menghasilkan nilai yang menunjukkan
+    tipe data kolom.
+</p>
+
+
+    <!-- Requesting permissions -->
+<h2 id="Permissions">Izin Penyedia Konten</h2>
+<p>
+    Aplikasi penyedia bisa menetapkan izin yang harus dimiliki aplikasi lain untuk
+    mengakses data penyedia. Izin ini akan memastikan bahwa pengguna mengetahui data
+    yang coba diakses oleh aplikasi. Berdasarkan ketentuan penyedia, aplikasi lain
+    meminta izin yang diperlukannya untuk mengakses penyedia. Pengguna akhir akan melihat
+    izin yang diminta saat menginstal aplikasi.
+</p>
+<p>
+    Jika aplikasi penyedia tidak menetapkan izin apa pun, maka aplikasi lain tidak memiliki
+    akses ke data penyedia. Akan tetapi, komponen-komponen dalam aplikasi penyedia selalu memiliki
+    akses penuh untuk baca dan tulis, izin apa pun yang ditetapkan.
+</p>
+<p>
+    Seperti disebutkan sebelumnya, Penyedia Kamus Pengguna mensyaratkan izin
+    <code>android.permission.READ_USER_DICTIONARY</code> untuk mengambil data darinya.
+    Penyedia memiliki izin <code>android.permission.WRITE_USER_DICTIONARY</code>
+    yang terpisah untuk menyisipkan, memperbarui, atau menghapus data.
+</p>
+<p>
+    Untuk mendapatkan izin yang diperlukan untuk mengakses penyedia, aplikasi memintanya dengan elemen
+<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
+    dalam file manifesnya. Bila Android Package Manager memasang aplikasi, pengguna
+    harus menyetujui semua izin yang diminta aplikasi. Jika pengguna menyetujui semuanya,
+    Package Manager akan melanjutkan instalasi; jika pengguna tidak menyetujui, Package Manager
+    akan membatalkan instalasi.
+</p>
+<p>
+    Elemen
+<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
+    berikut meminta akses baca ke Penyedia Kamus Pengguna:
+</p>
+<pre>
+    &lt;uses-permission android:name="android.permission.READ_USER_DICTIONARY"&gt;
+</pre>
+<p>
+    Dampak izin pada akses penyedia dijelaskan secara lebih detail dalam panduan
+    <a href="{@docRoot}guide/topics/security/security.html">Keamanan dan Izin</a>.
+</p>
+
+
+<!-- Inserting, Updating, and Deleting Data -->
+<h2 id="Modifications">Menyisipkan, Memperbarui, dan Menghapus Data</h2>
+<p>
+    Lewat cara yang sama dengan cara mengambil data dari penyedia, Anda juga menggunakan interaksi antara
+    klien penyedia dan {@link android.content.ContentProvider} penyedia untuk memodifikasi data.
+    Anda memanggil metode {@link android.content.ContentResolver} dengan argumen yang diteruskan ke
+    metode {@link android.content.ContentProvider} yang sesuai. Penyedia dan klien penyedia
+    menangani secara otomatis keamanan dan komunikasi antar-proses.
+</p>
+<h3 id="Inserting">Menyisipkan data</h3>
+<p>
+    Untuk menyisipkan data ke penyedia, Anda memanggil metode
+    {@link android.content.ContentResolver#insert ContentResolver.insert()}.
+ Metode ini menyisipkan sebuah baris baru ke penyedia itu dan menghasilkan URI konten untuk baris itu.
+    Cuplikan ini menampilkan cara menyisipkan sebuah kata baru ke Penyedia Kamus Pengguna:
+</p>
+<pre class="prettyprint">
+// Defines a new Uri object that receives the result of the insertion
+Uri mNewUri;
+
+...
+
+// Defines an object to contain the new values to insert
+ContentValues mNewValues = new ContentValues();
+
+/*
+ * Sets the values of each column and inserts the word. The arguments to the "put"
+ * method are "column name" and "value"
+ */
+mNewValues.put(UserDictionary.Words.APP_ID, "example.user");
+mNewValues.put(UserDictionary.Words.LOCALE, "en_US");
+mNewValues.put(UserDictionary.Words.WORD, "insert");
+mNewValues.put(UserDictionary.Words.FREQUENCY, "100");
+
+mNewUri = getContentResolver().insert(
+    UserDictionary.Word.CONTENT_URI,   // the user dictionary content URI
+    mNewValues                          // the values to insert
+);
+</pre>
+<p>
+    Data untuk baris baru masuk ke dalam satu objek {@link android.content.ContentValues}, yang
+    serupa bentuknya dengan kursor satu-baris. Kolom dalam objek ini tidak perlu memiliki
+    tipe data yang sama, dan jika Anda tidak ingin menetapkan nilai sama sekali, Anda bisa mengatur kolom
+    ke <code>null</code> dengan menggunakan {@link android.content.ContentValues#putNull ContentValues.putNull()}.
+</p>
+<p>
+    Cuplikan ini tidak menambahkan kolom <code>_ID</code>, karena kolom ini dipelihara
+    secara otomatis. Penyedia menetapkan sebuah nilai unik <code>_ID</code> ke setiap baris yang
+    ditambahkan. Penyedia biasanya menggunakan nilai ini sebagai kunci utama tabel.
+</p>
+<p>
+    URI konten yang dihasilkan dalam <code>newUri</code> akan mengidentifikasi baris yang baru ditambahkan, dengan
+    format berikut:
+</p>
+<pre>
+content://user_dictionary/words/&lt;id_value&gt;
+</pre>
+<p>
+    <code>&lt;id_value&gt;</code> adalah konten <code>_ID</code> untuk baris baru.
+    Kebanyakan penyedia bisa mendeteksi bentuk URI konten ini secara otomatis kemudian melakukan
+    operasi yang diminta pada baris tersebut.
+</p>
+<p>
+    Untuk mendapatkan nilai <code>_ID</code> dari {@link android.net.Uri} yang dihasilkan, panggil
+    {@link android.content.ContentUris#parseId ContentUris.parseId()}.
+</p>
+<h3 id="Updating">Memperbarui data</h3>
+<p>
+    Untuk memperbarui sebuah baris, gunakan objek {@link android.content.ContentValues} dengan
+    nilai-nilai yang diperbarui, persis seperti yang Anda lakukan pada penyisipan, dan kriteria pemilihan persis seperti yang Anda lakukan pada query.
+    Metode klien yang Anda gunakan adalah
+    {@link android.content.ContentResolver#update ContentResolver.update()}. Anda hanya perlu menambahkan
+    nilai-nilai ke objek {@link android.content.ContentValues} untuk kolom yang sedang Anda perbarui. Jika Anda
+    ingin membersihkan konten kolom, aturlah nilai ke <code>null</code>.
+</p>
+<p>
+    Cuplikan berikut mengubah semua baris yang kolom lokalnya memiliki bahasa "en" ke
+    lokal <code>null</code>. Nilai hasil adalah jumlah baris yang diperbarui:
+</p>
+<pre>
+// Defines an object to contain the updated values
+ContentValues mUpdateValues = new ContentValues();
+
+// Defines selection criteria for the rows you want to update
+String mSelectionClause = UserDictionary.Words.LOCALE +  "LIKE ?";
+String[] mSelectionArgs = {"en_%"};
+
+// Defines a variable to contain the number of updated rows
+int mRowsUpdated = 0;
+
+...
+
+/*
+ * Sets the updated value and updates the selected words.
+ */
+mUpdateValues.putNull(UserDictionary.Words.LOCALE);
+
+mRowsUpdated = getContentResolver().update(
+    UserDictionary.Words.CONTENT_URI,   // the user dictionary content URI
+    mUpdateValues                       // the columns to update
+    mSelectionClause                    // the column to select on
+    mSelectionArgs                      // the value to compare to
+);
+</pre>
+<p>
+    Anda juga harus membersihkan input pengguna bila memanggil
+    {@link android.content.ContentResolver#update ContentResolver.update()}. Untuk mengetahui selengkapnya tentang
+    hal ini, bacalah bagian <a href="#Injection">Melindungi dari input merusak</a>.
+</p>
+<h3 id="Deleting">Menghapus data</h3>
+<p>
+    Menghapus baris serupa dengan mengambil baris data: Anda menetapkan kriteria pemilihan untuk baris
+    yang ingin Anda hapus dan metode klien akan menghasilkan jumlah baris yang dihapus.
+    Cuplikan berikut menghapus baris yang appid-nya sama dengan "user". Metode menghasilkan
+    jumlah baris yang dihapus.
+</p>
+<pre>
+
+// Defines selection criteria for the rows you want to delete
+String mSelectionClause = UserDictionary.Words.APP_ID + " LIKE ?";
+String[] mSelectionArgs = {"user"};
+
+// Defines a variable to contain the number of rows deleted
+int mRowsDeleted = 0;
+
+...
+
+// Deletes the words that match the selection criteria
+mRowsDeleted = getContentResolver().delete(
+    UserDictionary.Words.CONTENT_URI,   // the user dictionary content URI
+    mSelectionClause                    // the column to select on
+    mSelectionArgs                      // the value to compare to
+);
+</pre>
+<p>
+    Anda juga harus membersihkan input pengguna bila memanggil
+    {@link android.content.ContentResolver#delete ContentResolver.delete()}. Untuk mengetahui selengkapnya tentang
+    hal ini, bacalah bagian <a href="#Injection">Melindungi dari input merusak</a>.
+</p>
+<!-- Provider Data Types -->
+<h2 id="DataTypes">Tipe Data Penyedia</h2>
+<p>
+    Penyedia konten bisa menawarkan berbagai tipe data. Penyedia Kamus Pengguna hanya menawarkan
+    teks, namun penyedia juga bisa menawarkan format berikut:
+</p>
+    <ul>
+        <li>
+            integer
+        </li>
+        <li>
+            long integer (long)
+        </li>
+        <li>
+            floating point
+        </li>
+        <li>
+            long floating point (double)
+        </li>
+    </ul>
+<p>
+    Tipe data lain yang sering digunakan penyedia adalah Binary Large OBject (BLOB) yang diimplementasikan sebagai
+    larik byte 64 KB. Anda bisa melihat tipe data yang tersedia dengan memperhatikan metode "get"
+    kelas {@link android.database.Cursor}.
+</p>
+<p>
+    Tipe data tiap kolom dalam penyedia biasanya tercantum dalam dokumentasinya.
+    Tipe data untuk Penyedia Kamus Pengguna tercantum dalam dokumentasi acuan
+    untuk kelas kontraknya {@link android.provider.UserDictionary.Words} (kelas kontrak
+    dijelaskan di bagian <a href="#ContractClasses">Kelas-kelas Kontrak</a>).
+    Anda juga bisa menentukan tipe data dengan memanggil {@link android.database.Cursor#getType
+    Cursor.getType()}.
+</p>
+<p>
+    Penyedia juga memelihara informasi tipe data MIME untuk tiap URI konten yang didefinisikannya. Anda bisa
+    menggunakan informasi tipe MIME untuk mengetahui apakah aplikasi Anda bisa menangani data yang
+    disediakan penyedia, atau memilih tipe penanganan berdasarkan tipe MIME. Anda biasanya memerlukan
+    tipe MIME saat menggunakan penyedia yang berisi
+    struktur atau file data yang kompleks. Misalnya, tabel {@link android.provider.ContactsContract.Data}
+    dalam Penyedia Kontak menggunakan tipe MIME untuk memberi label tipe data kontak yang disimpan di tiap
+    baris. Untuk mendapatkan tipe MIME yang sesuai dengan URI konten, panggil
+    {@link android.content.ContentResolver#getType ContentResolver.getType()}.
+</p>
+<p>
+    Bagian <a href="#MIMETypeReference">Acuan Tipe MIME</a> menerangkan
+    sintaks tipe MIME baik yang standar maupun custom.
+</p>
+
+
+<!-- Alternative Forms of Provider Access -->
+<h2 id="AltForms">Bentuk-Bentuk Alternatif Akses Penyedia</h2>
+<p>
+    Tiga bentuk alternatif akses penyedia adalah penting dalam pengembangan aplikasi:
+</p>
+<ul>
+    <li>
+        <a href="#Batch">Akses batch</a>: Anda bisa membuat sebuah batch panggilan akses dengan metode-metode dalam
+        kelas {@link android.content.ContentProviderOperation}, kemudian menerapkannya dengan
+        {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}.
+    </li>
+    <li>
+        Query asinkron: Anda harus melakukan query dalam thread terpisah. Satu cara melakukannya adalah
+        menggunakan objek {@link android.content.CursorLoader}. Contoh-contoh dalam panduan
+        <a href="{@docRoot}guide/components/loaders.html">Loader</a> memperagakan
+        cara melakukannya.
+    </li>
+    <li>
+        <a href="#Intents">Akses data melalui intent</a>: Walaupun tidak bisa mengirim intent
+        ke penyedia secara langsung, Anda bisa mengirim intent ke aplikasi penyedia, yang
+        biasanya paling lengkap dibekali untuk memodifikasi data penyedia.
+    </li>
+</ul>
+<p>
+    Akses batch dan modifikasi melalui intent dijelaskan dalam bagian-bagian berikut.
+</p>
+<h3 id="Batch">Akses batch</h3>
+<p>
+    Akses batch ke penyedia berguna untuk menyisipkan baris dalam jumlah besar, atau menyisipkan
+    baris ke dalam beberapa tabel dalam panggilan metode yang sama, atau biasanya melakukan satu set
+    operasi lintas batas proses sebagai transaksi (operasi atomik).
+</p>
+<p>
+    Untuk mengakses penyedia dalam "mode batch",
+    buat satu larik objek {@link android.content.ContentProviderOperation}, kemudian
+    kirim larik itu ke penyedia konten dengan
+    {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}. Anda meneruskan
+    <em>otoritas</em> penyedia konten ke metode ini, daripada URI konten tertentu.
+    Ini memungkinkan tiap objek {@link android.content.ContentProviderOperation} dalam larik untuk bekerja
+    terhadap tabel yang berbeda. Panggilan ke {@link android.content.ContentResolver#applyBatch
+    ContentResolver.applyBatch()} menghasilkan satu larik hasil.
+</p>
+<p>
+    Keterangan kelas kontrak {@link android.provider.ContactsContract.RawContacts}
+    menyertakan cuplikan kode yang memperagakan penyisipan batch. Contoh aplikasi
+    <a href="{@docRoot}resources/samples/ContactManager/index.html">Contacts Manager</a>
+    berisi contoh akses batch dalam file sumber <code>ContactAdder.java</code>-nya
+.
+</p>
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<h2>Menampilkan data dengan aplikasi pembantu</h2>
+<p>
+    Jika aplikasi Anda <em>memang</em> memiliki izin akses, Anda masih mungkin perlu menggunakan
+    intent untuk menampilkan data dalam aplikasi lain. Misalnya, aplikasi Kalender menerima
+    intent {@link android.content.Intent#ACTION_VIEW}, yang menampilkan tanggal atau kejadian tertentu.
+    Hal ini memungkinkan Anda menampilkan informasi kalender tanpa harus membuat UI sendiri.
+    Untuk mengetahui selengkapnya tentang fitur ini, lihat panduan
+    <a href="{@docRoot}guide/topics/providers/calendar-provider.html">Penyedia Kalender</a>.
+</p>
+<p>
+    Aplikasi yang Anda kirimi intent tidak harus aplikasi
+    yang terkait dengan penyedia. Misalnya, Anda bisa mengambil satu kontak dari
+    Penyedia Kontak, kemudian mengirim intent {@link android.content.Intent#ACTION_VIEW}
+    berisi URI konten untuk gambar kontak itu ke penampil gambar.
+</p>
+</div>
+</div>
+<h3 id="Intents">Akses data melalui intent</h3>
+<p>
+    Intent bisa menyediakan akses tidak langsung ke penyedia konten. Anda memperbolehkan pengguna mengakses
+    data dalam penyedia sekalipun aplikasi Anda tidak memiliki izin akses, baik dengan
+    mendapatkan intent yang dihasilkan aplikasi yang memiliki izin, atau dengan mengaktifkan
+    aplikasi yang memiliki izin dan membiarkan pengguna melakukan pekerjaan di dalamnya.
+</p>
+<h4>Mendapatkan akses dengan izin sementara</h4>
+<p>
+    Anda bisa mengakses data dalam penyedia konten, sekalipun tidak memiliki
+    izin akses yang sesuai, dengan mengirimkan intent ke aplikasi yang memang memiliki izin dan
+    menerima hasil berupa intent berisi izin "URI".
+    Inilah izin untuk URI konten tertentu yang berlaku hingga aktivitas yang menerima
+    izin selesai. Aplikasi yang memiliki izin tetap akan memberikan
+    izin sementara dengan mengatur flag dalam intent yang dihasilkan:
+</p>
+<ul>
+    <li>
+        <strong>Izin baca:</strong>
+        {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION}
+    </li>
+    <li>
+        <strong>Izin tulis:</strong>
+        {@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION}
+    </li>
+</ul>
+<p class="note">
+    <strong>Catatan:</strong> Flag ini tidak memberikan akses baca atau tulis umum ke penyedia
+    yang otoritasnya dimuat dalam URI konten. Aksesnya hanya untuk URI itu sendiri.
+</p>
+<p>
+    Penyedia mendefinisikan izin URI untuk URI konten dalam manifesnya, dengan menggunakan atribut
+<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">android:grantUriPermission</a></code>
+    dari elemen
+<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>
+,   serta elemen anak
+<code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission&gt;</a></code>
+    dari elemen
+<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>.
+ Mekanisme izin URI dijelaskan secara lebih detail dalam panduan
+    <a href="{@docRoot}guide/topics/security/security.html">Keamanan dan Izin</a>,
+    di bagian "Izin URI".
+</p>
+<p>
+    Misalnya, Anda bisa mengambil data untuk satu kontak di Penyedia Kontak, sekalipun tidak
+    memiliki izin {@link android.Manifest.permission#READ_CONTACTS}. Anda mungkin ingin melakukan
+    ini dalam aplikasi yang mengirim kartu ucapan elektronik ke seorang kenalan pada hari ulang tahunnya. Sebagai ganti
+    meminta {@link android.Manifest.permission#READ_CONTACTS}, yang memberi Anda akses ke semua
+    kontak pengguna dan semua informasinya, Anda lebih baik membiarkan pengguna mengontrol
+    kontak-kontak yang akan digunakan oleh aplikasi Anda. Caranya, gunakan proses berikut:
+</p>
+<ol>
+    <li>
+        Aplikasi Anda akan mengirim intent berisi tindakan
+        {@link android.content.Intent#ACTION_PICK} dan tipe MIME "contacts"
+        {@link android.provider.ContactsContract.RawContacts#CONTENT_ITEM_TYPE}, dengan menggunakan
+        metode {@link android.app.Activity#startActivityForResult
+        startActivityForResult()}.
+    </li>
+    <li>
+        Karena intent ini cocok dengan filter intent untuk
+        aktivitas "pemilihan" aplikasi People, aktivitas akan muncul ke latar depan.
+    </li>
+    <li>
+        Dalam aktivitas pemilihan, pengguna memilih sebuah
+        kontak untuk diperbarui. Bila ini terjadi, aktivitas pemilihan akan memanggil
+        {@link android.app.Activity#setResult setResult(resultcode, intent)}
+        untuk membuat intent yang akan diberikan kembali ke aplikasi Anda. Intent itu berisi URI konten
+        kontak yang dipilih pengguna, dan flag "extras"
+        {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION}. Semua flag ini memberikan
+        izin URI ke aplikasi Anda untuk membaca data kontak yang ditunjuk oleh
+        URI konten. Aktivitas pemilihan kemudian memanggil {@link android.app.Activity#finish()} untuk
+        mengembalikan kontrol ke aplikasi Anda.
+    </li>
+    <li>
+        Aktivitas Anda akan kembali ke latar depan, dan sistem memanggil metode
+        {@link android.app.Activity#onActivityResult onActivityResult()}
+        aktivitas Anda. Metode ini menerima intent yang dihasilkan oleh aktivitas pemilihan dalam
+        aplikasi People.
+    </li>
+    <li>
+        Dengan URI konten dari intent yang dihasilkan, Anda bisa membaca data kontak
+        dari Penyedia Kontak, sekalipun Anda tidak meminta izin akses baca tetap
+        ke penyedia dalam manifes Anda. Anda kemudian bisa mendapatkan informasi hari ulang tahun si kontak
+        atau alamat emailnya, kemudian mengirim kartu ucapan elektronik.
+    </li>
+</ol>
+<h4>Menggunakan aplikasi lain</h4>
+<p>
+    Satu cara mudah agar pengguna bisa memodifikasi data yang izin aksesnya tidak Anda miliki adalah
+    mengaktifkan aplikasi yang memiliki izin dan membiarkan pengguna melakukan pekerjaannya di sana.
+</p>
+<p>
+    Misalnya, aplikasi Kalender menerima
+    intent {@link android.content.Intent#ACTION_INSERT}, yang memungkinkan Anda mengaktifkan
+    UI penyisipan aplikasi itu. Anda bisa meneruskan data "extras" dalam intent ini, yang
+    digunakan aplikasi untuk mengisi dahulu UI-nya. Karena kejadian berulang memiliki sintaks yang rumit,
+    cara yang lebih disukai untuk menyisipkan kejadian ke dalam Penyedia Kalender adalah mengaktifkan aplikasi Kalender dengan
+    {@link android.content.Intent#ACTION_INSERT}, kemudian membiarkan pengguna menyisipkan kejadian di sana.
+</p>
+<!-- Contract Classes -->
+<h2 id="ContractClasses">Kelas-kelas Kontrak</h2>
+<p>
+    Kelas kontrak mendefinisikan konstanta yang membantu aplikasi menggunakan URI konten, nama
+    kolom, tindakan intent, dan fitur lain pada penyedia konten. Kelas kontrak tidak
+    disertakan secara otomatis bersama penyedia; pengembang penyedia harus mendefinisikannya kemudian
+    membuatnya tersedia bagi pengembang lain. Banyak penyedia yang disertakan pada platform Android
+    memiliki kelas kontrak yang sesuai dalam {@link android.provider} paketnya.
+</p>
+<p>
+    Misalnya, Penyedia Kamus Pengguna memiliki kelas kontrak
+    {@link android.provider.UserDictionary} yang berisi URI konten dan konstanta nama kolom. URI
+    konten untuk tabel "words" didefinisikan dalam konstanta
+    {@link android.provider.UserDictionary.Words#CONTENT_URI UserDictionary.Words.CONTENT_URI}.
+    Kelas {@link android.provider.UserDictionary.Words} juga berisi konstanta nama kolom,
+    yang digunakan dalam cuplikan contoh pada panduan ini. Misalnya, sebuah proyeksi query bisa
+    didefinisikan sebagai:
+</p>
+<pre>
+String[] mProjection =
+{
+    UserDictionary.Words._ID,
+    UserDictionary.Words.WORD,
+    UserDictionary.Words.LOCALE
+};
+</pre>
+<p>
+    Kelas kontrak lain adalah {@link android.provider.ContactsContract} untuk Penyedia Kontak.
+    Dokumentasi acuan untuk kelas ini menyertakan contoh cuplikan kode. Salah satu
+    subkelasnya, {@link android.provider.ContactsContract.Intents.Insert}, adalah
+    kelas kontrak yang berisi konstanta untuk intent dan data intent.
+</p>
+
+
+<!-- MIME Type Reference -->
+<h2 id="MIMETypeReference">Acuan Tipe MIME</h2>
+<p>
+    Penyedia konten bisa menghasilkan tipe media MIME standar, atau string tipe MIME custom, atau keduanya.
+</p>
+<p>
+    Tipe MIME memiliki format
+</p>
+<pre>
+<em>type</em>/<em>subtype</em>
+</pre>
+<p>
+    Misalnya, tipe MIME <code>text/html</code> yang dikenal luas memiliki tipe <code>text</code> dan
+    subtipe <code>html</code>. Jika penyedia menghasilkan tipe ini untuk sebuah URI, artinya
+    query dengan URI itu akan menghasilkan teks berisi tag HTML.
+</p>
+<p>
+    String tipe MIME custom, yang juga disebut dengan tipe MIME "khusus vendor", memiliki nilai-nilai
+    <em>tipe</em> dan <em>subtipe</em> yang lebih kompleks. Nilai <em>tipe</em> selalu
+</p>
+<pre>
+vnd.android.cursor.<strong>dir</strong>
+</pre>
+<p>
+    untuk beberapa baris, atau
+</p>
+<pre>
+vnd.android.cursor.<strong>item</strong>
+</pre>
+<p>
+    untuk satu baris.
+</p>
+<p>
+    <em>Subtipe</em> adalah khusus penyedia. Penyedia bawaan Android biasanya memiliki subtipe
+    sederhana. Misalnya, bila aplikasi Contacts membuat satu baris untuk nomor telepon,
+    aplikasi akan mengatur tipe MIME berikut di baris itu:
+</p>
+<pre>
+vnd.android.cursor.item/phone_v2
+</pre>
+<p>
+    Perhatikan bahwa nilai subtipe adalah sekadar <code>phone_v2</code>.
+</p>
+<p>
+    Pengembang penyedia lain bisa membuat pola subtipe sendiri berdasarkan
+    otoritas dan nama-nama tabel penyedia. Misalnya, perhatikan penyedia yang berisi jadwal kereta api.
+    Otoritas penyedia adalah <code>com.example.trains</code>, dan berisi tabel-tabel
+    Line1, Line2, dan Line3. Untuk merespons URI konten
+</p>
+<p>
+<pre>
+content://com.example.trains/Line1
+</pre>
+<p>
+    untuk tabel Line1, penyedia menghasilkan tipe MIME
+</p>
+<pre>
+vnd.android.cursor.<strong>dir</strong>/vnd.example.line1
+</pre>
+<p>
+     Untuk merespons URI konten
+</p>
+<pre>
+content://com.example.trains/Line2/5
+</pre>
+<p>
+    untuk baris 5 di tabel Line2, penyedia menghasilkan tipe MIME
+</p>
+<pre>
+vnd.android.cursor.<strong>item</strong>/vnd.example.line2
+</pre>
+<p>
+    Kebanyakan penyedia konten mendefinisikan konstanta kelas kontrak untuk tipe MIME yang digunakannya. Kelas kontrak
+    {@link android.provider.ContactsContract.RawContacts} pada Penyedia Kontak
+    misalnya, mendefinisikan konstanta
+    {@link android.provider.ContactsContract.RawContacts#CONTENT_ITEM_TYPE} untuk tipe MIME
+    baris kontak mentah tunggal.
+</p>
+<p>
+    URI konten untuk baris-baris tunggal dijelaskan di bagian
+    <a href="#ContentURIs">URI Konten</a>.
+</p>
diff --git a/docs/html-intl/intl/id/guide/topics/providers/content-provider-creating.jd b/docs/html-intl/intl/id/guide/topics/providers/content-provider-creating.jd
new file mode 100644
index 0000000..7fbc613
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/providers/content-provider-creating.jd
@@ -0,0 +1,1214 @@
+page.title=Membuat Penyedia Konten
+@jd:body
+<div id="qv-wrapper">
+<div id="qv">
+
+
+<h2>Dalam dokumen ini</h2>
+<ol>
+    <li>
+        <a href="#DataStorage">Mendesain Penyimpanan Data</a>
+    </li>
+    <li>
+        <a href="#ContentURI">Mendesain URI Konten</a>
+    </li>
+    <li>
+        <a href="#ContentProvider">Mengimplementasikan Kelas ContentProvider</a>
+        <ol>
+            <li>
+                <a href="#RequiredAccess">Metode-Metode yang Diperlukan</a>
+            </li>
+            <li>
+                <a href="#Query">Mengimplementasikan metode query()</a>
+            </li>
+            <li>
+                <a href="#Insert">Mengimplementasikan metode insert()</a>
+            </li>
+            <li>
+                <a href="#Delete">Mengimplementasikan metode delete()</a>
+            </li>
+            <li>
+                <a href="#Update">Mengimplementasikan metode update()</a>
+            </li>
+            <li>
+                <a href="#OnCreate">Mengimplementasikan metode onCreate()</a>
+            </li>
+        </ol>
+    </li>
+    <li>
+        <a href="#MIMETypes">Mengimplementasikan Tipe MIME Penyedia Konten</a>
+        <ol>
+            <li>
+                <a href="#TableMIMETypes">Tipe MIME untuk tabel</a>
+            </li>
+            <li>
+                <a href="#FileMIMETypes">Tipe MIME untuk file</a>
+            </li>
+        </ol>
+    </li>
+    <li>
+        <a href="#ContractClass">Mengimplementasikan Kelas Kontrak</a>
+    </li>
+    <li>
+        <a href="#Permissions">Mengimplementasikan Izin Penyedia Konten</a>
+    </li>
+    <li>
+        <a href="#ProviderElement">Elemen &lt;provider&gt;</a>
+    </li>
+    <li>
+        <a href="#Intents">Intent dan Akses Data</a>
+    </li>
+</ol>
+<h2>Kelas-kelas utama</h2>
+    <ol>
+        <li>
+            {@link android.content.ContentProvider}
+        </li>
+        <li>
+            {@link android.database.Cursor}
+        </li>
+        <li>
+            {@link android.net.Uri}
+        </li>
+    </ol>
+<h2>Contoh-Contoh Terkait</h2>
+    <ol>
+        <li>
+            <a href="{@docRoot}resources/samples/NotePad/index.html">
+                Aplikasi contoh Note Pad
+            </a>
+        </li>
+    </ol>
+<h2>Lihat juga</h2>
+    <ol>
+        <li>
+            <a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
+            Dasar-Dasar Penyedia Konten</a>
+        </li>
+        <li>
+            <a href="{@docRoot}guide/topics/providers/calendar-provider.html">
+            Penyedia Kalender</a>
+        </li>
+    </ol>
+</div>
+</div>
+
+
+<p>
+    Penyedia konten mengelola akses ke repository data pusat. Anda mengimplementasikan
+    penyedia sebagai satu atau beberapa kelas dalam aplikasi Android, bersama elemen-elemen dalam
+    file manifes. Salah satu kelas Anda mengimplementasikan subkelas
+    {@link android.content.ContentProvider}, yang merupakan antarmuka antara penyedia Anda dan
+    aplikasi lain. Walaupun penyedia konten dimaksudkan untuk menyediakan data bagi
+    aplikasi lain, Anda tentu saja bisa memiliki aktivitas dalam aplikasi yang memungkinkan pengguna
+    melakukan query dan memodifikasi data yang dikelola oleh penyedia Anda.
+</p>
+<p>
+    Bagian selebihnya dalam topik ini adalah daftar langkah-langkah dasar untuk membangun penyedia konten dan daftar
+    API yang akan digunakan.
+</p>
+
+
+<!-- Before You Start Building -->
+<h2 id="BeforeYouStart">Sebelum Anda Mulai Membangun</h2>
+<p>
+    Sebelum Anda mulai membangun penyedia, lakukanlah hal-hal berikut:
+</p>
+<ol>
+    <li>
+        <strong>Putuskan apakah Anda memerlukan penyedia konten</strong>. Anda perlu membangun sebuah
+        penyedia konten jika ingin menyediakan salah satu atau beberapa dari fitur berikut:
+        <ul>
+            <li>Anda ingin menawarkan data atau file yang kompleks ke aplikasi lain.</li>
+            <li>Anda ingin memungkinkan pengguna menyalin data yang kompleks dari aplikasi Anda ke dalam aplikasi lain.</li>
+            <li>Anda ingin menyediakan saran pencarian custom dengan menggunakan kerangka kerja pencarian.</li>
+        </ul>
+    <p>
+        Anda <em>tidak</em> mengharuskan penyedia untuk menggunakan database SQLite jika hanya digunakan dalam
+        aplikasi sendiri.
+    </p>
+    </li>
+    <li>
+        Jika Anda belum siap melakukannya, bacalah topik
+        <a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
+        Dasar-Dasar Penyedia Konten</a> untuk mengetahui selengkapnya tentang penyedia.
+    </li>
+</ol>
+<p>
+    Berikutnya, ikuti langkah-langkah ini untuk membangun penyedia:
+</p>
+<ol>
+    <li>
+        Desain penyimpanan mentah untuk data Anda. Penyedia konten menawarkan data dengan dua cara:
+        <dl>
+            <dt>
+                Data file
+            </dt>
+            <dd>
+                Data yang biasanya masuk ke dalam file, misalnya
+                foto, audio, atau video. Simpan file dalam ruang privat
+                aplikasi Anda. Untuk merespons permintaan file dari aplikasi lain,
+                penyedia Anda bisa menawarkan handle ke file tersebut.
+            </dd>
+            <dt>
+                Data "terstruktur"
+            </dt>
+            <dd>
+                Data yang biasanya masuk ke dalam database, larik, atau struktur serupa.
+                Simpan data dalam bentuk yang kompatibel dengan tabel berisi baris dan kolom. Baris
+                mewakili entitas, misalnya satu orang atau satu barang inventori. Kolom mewakili
+                beberapa data untuk entitas itu, misalnya nama orang atau harga barang. Cara umum untuk
+                menyimpan tipe data ini adalah dalam database SQLite, namun Anda bisa menggunakan tipe
+                penyimpanan apa saja yang persisten. Untuk mengetahui selengkapnya tentang tipe penyimpanan yang tersedia di
+                sistem Android, lihat bagian <a href="#DataStorage">
+                Mendesain Penyimpanan Data</a>.
+            </dd>
+        </dl>
+    </li>
+    <li>
+        Definisikan sebuah implementasi konkret kelas {@link android.content.ContentProvider} dan
+        metode yang diperlukannya. Kelas ini adalah antarmuka antara data Anda dan bagian selebihnya pada
+        sistem Android. Untuk informasi selengkapnya tentang kelas ini, lihat bagian
+        <a href="#ContentProvider">Mengimplementasikan Kelas ContentProvider</a>.
+    </li>
+    <li>
+        Definisikan string otoritas, semua URI isinya, dan nama-nama kolom penyedia. Jika Anda ingin
+        penyedia aplikasi menangani intent, definisikan juga semua tindakan intent, data ekstra,
+        dan flag. Definisikan juga izin yang akan Anda syaratkan terhadap aplikasi yang ingin
+        mengakses data Anda. Anda harus mempertimbangkan pendefinisian semua nilai ini sebagai konstanta di
+        kelas kontrak terpisah; nantinya, Anda bisa mengekspos kelas ini kepada pengembang lain. Untuk
+        informasi selengkapnya tentang URI konten, lihat
+        bagian <a href="#ContentURI">Mendesain URI Konten</a>.
+        Untuk informasi selengkapnya tentang intent, lihat
+        bagian <a href="#Intents">Intent dan Akses Data</a>.
+    </li>
+    <li>
+        Tambahkan bagian opsional lainnya, seperti data contoh atau implementasi
+        {@link android.content.AbstractThreadedSyncAdapter} yang bisa menyinkronkan data antara
+        penyedia dan data berbasis cloud.
+    </li>
+</ol>
+
+
+<!-- Designing Data Storage -->
+<h2 id="DataStorage">Mendesain Penyimpanan Data</h2>
+<p>
+    Penyedia konten adalah antarmuka ke data yang disimpan dalam format terstruktur. Sebelum membuat
+    antarmuka, Anda harus memutuskan cara menyimpan data. Anda bisa menyimpan data dalam bentuk apa saja yang Anda
+    sukai, kemudian mendesain antarmuka untuk membaca dan menulis data yang diperlukan.
+</p>
+<p>
+    Berikut ini adalah beberapa teknologi penyimpanan data yang tersedia di Android:
+</p>
+<ul>
+    <li>
+        Sistem Android menyertakan API database SQLite yang digunakan penyedia Android sendiri
+        untuk menyimpan data berorientasi tabel. Kelas
+        {@link android.database.sqlite.SQLiteOpenHelper} membantu Anda membuat database, dan kelas
+        {@link android.database.sqlite.SQLiteDatabase} adalah kelas dasar untuk mengakses
+        database.
+        <p>
+            Ingatlah bahwa Anda tidak harus menggunakan database untuk mengimplementasikan repository. Penyedia
+            muncul secara eksternal sebagai satu set tabel, yang serupa dengan sebuah database relasional, namun ini
+            bukan persyaratan untuk implementasi internal penyedia.
+        </p>
+    </li>
+    <li>
+        Untuk menyimpan file data, Android memiliki beragam API berorientasi file.
+        Untuk mengetahui selengkapnya tentang penyimpanan file, bacalah topik
+        <a href="{@docRoot}guide/topics/data/data-storage.html">Penyimpanan Data</a>. Jika Anda sedang
+        mendesain penyedia yang menawarkan data yang terkait dengan media seperti musik atau video, Anda bisa
+        memiliki penyedia yang mengombinasikan data tabel dan file.
+    </li>
+    <li>
+        Untuk bekerja dengan data berbasis jaringan, gunakan kelas-kelas dalam {@link java.net} dan
+        {@link android.net}. Anda juga bisa menyinkronkan data berbasis jaringan dengan penyimpanan data lokal
+        seperti database, kemudian menawarkan data sebagai tabel atau file.
+        Aplikasi contoh <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">
+        Sample Sync Adapter</a> memperagakan tipe sinkronisasi ini.
+    </li>
+</ul>
+<h3 id="DataDesign">
+    Pertimbangan desain data
+</h3>
+<p>
+    Berikut ini adalah beberapa tip untuk mendesain struktur data penyedia:
+</p>
+<ul>
+    <li>
+        Data tabel harus selalu memiliki kolom "kunci utama" yang dipelihara oleh penyedia
+        sebagai nilai numerik unik untuk setiap baris. Anda bisa menggunakan nilai ini untuk menautkan baris ke
+        baris yang terkait dalam tabel lain (dengan menggunakannya sebagai "kunci asing"). Walaupun Anda bisa menggunakan nama
+        apa saja untuk kolom ini, menggunakan {@link android.provider.BaseColumns#_ID BaseColumns._ID} adalah
+        pilihan terbaik, karena menautkan hasil query penyedia dengan
+        {@link android.widget.ListView} mensyaratkan bahwa salah satu kolom yang diambil memiliki nama
+        <code>_ID</code>.
+    </li>
+    <li>
+        Jika Anda ingin untuk menyediakan gambar bitmap atau potongan data berorientasi file lainnya yang berukuran sangat besar, simpanlah
+        data dalam sebuah file kemudian sediakan secara tidak langsung sebagai ganti menyimpannya secara langsung dalam
+        tabel. Jika melakukannya, Anda perlu memberi tahu pengguna penyedia Anda bahwa mereka perlu menggunakan metode file
+        {@link android.content.ContentResolver} untuk mengakses data.
+    </li>
+    <li>
+        Gunakan tipe data Binary Large OBject (BLOB) untuk menyimpan data yang bervariasi ukurannya atau memiliki
+        struktur yang beragam. Misalnya, Anda bisa menggunakan sebuah kolom BLOB untuk menyimpan
+        <a href="http://code.google.com/p/protobuf">buffer protokol</a> atau
+        <a href="http://www.json.org">struktur JSON</a>.
+        <p>
+            Anda juga bisa menggunakan BLOB untuk mengimplementasikan tabel yang <em>tidak bergantung skema</em>. Dalam
+            tipe tabel ini, Anda mendefinisikan kolom kunci utama, kolom tipe MIME, dan satu atau beberapa
+            kolom generik sebagai BLOB. Arti dari data dalam kolom-kolom BLOB ditunjukkan
+            oleh nilai dalam kolom tipe MIME. Cara ini memungkinkan Anda menyimpan berbagai tipe baris dalam
+            tabel yang sama. Tabel "data"
+            {@link android.provider.ContactsContract.Data} Penyedia Kontak adalah contoh tabel yang tidak bergantung skema
+            tersebut.
+        </p>
+    </li>
+</ul>
+<!-- Designing Content URIs -->
+<h2 id="ContentURI">Mendesain URI Konten</h2>
+<p>
+    <strong>URI konten</strong> adalah URI yang mengidentifikasi data dalam penyedia. URI Konten
+    berisi nama simbolis seluruh penyedia (<strong>otoritas</strong>nya) dan sebuah
+    nama yang menunjuk ke tabel atau file (<strong>path</strong>). Bagian id opsional menunjuk ke
+    satu baris dalam tabel. Setiap metode akses data
+    {@link android.content.ContentProvider} memiliki sebuah URI konten sebagai argumen; hal ini memungkinkan Anda
+    menentukan tabel, baris, atau file yang akan diakses.
+</p>
+<p>
+    Dasar-dasar URI konten dijelaskan dalam topik
+    <a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
+    Dasar-Dasar Penyedia Konten</a>.
+</p>
+<h3>Mendesain otoritas</h3>
+<p>
+    Penyedia biasanya memiliki otoritas tunggal, yang berfungsi sebagai nama internal Android-nya. Untuk
+    menghindari konflik dengan penyedia lain, Anda harus menggunakan kepemilikan domain internet (secara terbalik)
+    sebagai basis otoritas penyedia Anda. Karena saran ini juga berlaku untuk
+    nama-nama paket Android, Anda bisa mendefinisikan otoritas penyedia sebagai perluasan dari nama
+    paket yang berisi penyedia. Misalnya, jika nama paket Android Anda adalah
+    <code>com.example.&lt;appname&gt;</code>, Anda harus memberikan penyedia Anda
+    otoritas <code>com.example.&lt;appname&gt;.provider</code>.
+</p>
+<h3>Mendesain struktur path</h3>
+<p>
+    Pengembang biasanya membuat URI konten dari otoritas dengan menambahkan path yang menunjuk ke
+    masing-masing tabel. Misalnya, jika Anda memiliki dua tabel <em>table1</em> dan
+    <em>table2</em>, Anda mengombinasikan otoritas dari contoh sebelumnya untuk menghasilkan
+    URI konten
+    <code>com.example.&lt;appname&gt;.provider/table1</code> dan
+    <code>com.example.&lt;appname&gt;.provider/table2</code>. Path tidak
+    dibatasi pada segmen tunggal, dan tidak harus berupa tabel untuk masing-masing tingkat path.
+</p>
+<h3>Menangani ID URI konten</h3>
+<p>
+    Berdasarkan standar, penyedia menawarkan akses ke satu baris dalam tabel dengan menerima URI konten
+    dengan sebuah nilai ID untuk baris itu di akhir URI. Juga berdasarkan standar, penyedia mencocokkan
+    nilai ID dengan kolom <code>_ID</code> tabel, dan melakukan akses yang diminta terhadap baris
+    yang cocok.
+</p>
+<p>
+    Standar ini memudahkan pola desain umum untuk aplikasi yang mengakses penyedia. Aplikasi
+    melakukan query terhadap penyedia dan menampilkan {@link android.database.Cursor} yang dihasilkan
+    dalam {@link android.widget.ListView} dengan menggunakan {@link android.widget.CursorAdapter}.
+    Definisi {@link android.widget.CursorAdapter} mengharuskan salah satu kolom dalam
+    {@link android.database.Cursor} berupa <code>_ID</code>
+</p>
+<p>
+    Pengguna kemudian mengambil salah satu baris yang ditampilkan dari UI untuk menemukan atau memodifikasi
+    data. Aplikasi mengambil baris yang sesuai dari {@link android.database.Cursor} yang mendukung
+    {@link android.widget.ListView}, mengambil nilai <code>_ID</code> untuk baris ini, menambahkannya ke
+    URI konten, dan mengirim permintaan akses ke penyedia. Penyedia nanti bisa melakukan
+    query atau modifikasi terhadap baris yang persis diambil pengguna.
+</p>
+<h3>Pola URI konten</h3>
+<p>
+    Untuk membantu Anda memilih tindakan yang diambil bagi URI konten yang masuk, API penyedia menyertakan
+    kelas praktis {@link android.content.UriMatcher}, yang memetakan "pola-pola" URI konten ke
+    nilai-nilai integer. Anda bisa menggunakan nilai-nilai integer dalam pernyataan <code>switch</code> yang
+    memilih tindakan yang diinginkan untuk URI konten atau URI yang cocok dengan pola tertentu.
+</p>
+<p>
+    Pola URI konten mencocokkan dengan URI konten menggunakan karakter wildcard:
+</p>
+    <ul>
+        <li>
+            <strong><code>*</code>:</strong> Mencocokkan string yang memiliki karakter yang sah dengan panjang berapa saja.
+        </li>
+        <li>
+            <strong><code>#</code>:</strong> Mencocokkan string karakter numerik dengan panjang berapa saja.
+        </li>
+    </ul>
+<p>
+    Sebagai contoh desain dan pemrograman penanganan URI konten, perhatikan penyedia dengan
+    otoritas <code>com.example.app.provider</code> yang mengenali URI konten berikut
+    yang menunjuk ke tabel-tabel:
+</p>
+<ul>
+    <li>
+        <code>content://com.example.app.provider/table1</code>: Tabel bernama <code>table1</code>.
+    </li>
+    <li>
+        <code>content://com.example.app.provider/table2/dataset1</code>: Tabel bernama
+        <code>dataset1</code>.
+    </li>
+    <li>
+        <code>content://com.example.app.provider/table2/dataset2</code>: Tabel bernama
+        <code>dataset2</code>.
+    </li>
+    <li>
+        <code>content://com.example.app.provider/table3</code>: Tabel bernama <code>table3</code>.
+    </li>
+</ul>
+<p>
+    Penyedia juga mengenali URI konten ini jika baris ID ditambahkan ke URI,
+    misalnya <code>content://com.example.app.provider/table3/1</code> untuk baris yang diidentifikasi oleh
+    <code>1</code> dalam <code>table3</code>.
+</p>
+<p>
+    Pola-pola URI konten berikut akan menjadi mungkin:
+</p>
+<dl>
+    <dt>
+        <code>content://com.example.app.provider/*</code>
+    </dt>
+    <dd>
+        Mencocokkan URI konten di penyedia.
+    </dd>
+    <dt>
+        <code>content://com.example.app.provider/table2/*</code>:
+    </dt>
+    <dd>
+        Mencocokkan URI konten untuk tabel-tabel <code>dataset1</code>
+        dan <code>dataset2</code>, namun tidak mencocokkan URI konten untuk <code>table1</code> atau
+        <code>table3</code>.
+    </dd>
+    <dt>
+        <code>content://com.example.app.provider/table3/#</code>: Mencocokkan URI konten
+        untuk satu baris di <code>table3</code>, misalnya
+        <code>content://com.example.app.provider/table3/6</code> untuk baris yang diidentifikasi oleh
+        <code>6</code>.
+    </dt>
+</dl>
+<p>
+    Cuplikan kode berikut menunjukkan cara kerja metode di {@link android.content.UriMatcher}.
+    Kode ini menangani URI seluruh tabel secara berbeda dengan URI untuk
+    satu baris, menggunakan pola URI konten
+    <code>content://&lt;authority&gt;/&lt;path&gt;</code> untuk tabel, dan
+    <code>content://&lt;authority&gt;/&lt;path&gt;/&lt;id&gt;</code> untuk satu baris.
+</p>
+<p>
+    Metode {@link android.content.UriMatcher#addURI(String, String, int) addURI()} memetakan
+    otoritas dan path ke nilai integer. Metode {@link android.content.UriMatcher#match(Uri)
+    match()} menghasilkan nilai integer URI. Pernyataan <code>switch</code>
+    memilih antara melakukan query seluruh tabel dan melakukan query satu record:
+</p>
+<pre class="prettyprint">
+public class ExampleProvider extends ContentProvider {
+...
+    // Creates a UriMatcher object.
+    private static final UriMatcher sUriMatcher;
+...
+    /*
+     * The calls to addURI() go here, for all of the content URI patterns that the provider
+     * should recognize. For this snippet, only the calls for table 3 are shown.
+     */
+...
+    /*
+     * Sets the integer value for multiple rows in table 3 to 1. Notice that no wildcard is used
+     * in the path
+     */
+    sUriMatcher.addURI("com.example.app.provider", "table3", 1);
+
+    /*
+     * Sets the code for a single row to 2. In this case, the "#" wildcard is
+     * used. "content://com.example.app.provider/table3/3" matches, but
+     * "content://com.example.app.provider/table3 doesn't.
+     */
+    sUriMatcher.addURI("com.example.app.provider", "table3/#", 2);
+...
+    // Implements ContentProvider.query()
+    public Cursor query(
+        Uri uri,
+        String[] projection,
+        String selection,
+        String[] selectionArgs,
+        String sortOrder) {
+...
+        /*
+         * Choose the table to query and a sort order based on the code returned for the incoming
+         * URI. Here, too, only the statements for table 3 are shown.
+         */
+        switch (sUriMatcher.match(uri)) {
+
+
+            // If the incoming URI was for all of table3
+            case 1:
+
+                if (TextUtils.isEmpty(sortOrder)) sortOrder = "_ID ASC";
+                break;
+
+            // If the incoming URI was for a single row
+            case 2:
+
+                /*
+                 * Because this URI was for a single row, the _ID value part is
+                 * present. Get the last path segment from the URI; this is the _ID value.
+                 * Then, append the value to the WHERE clause for the query
+                 */
+                selection = selection + "_ID = " uri.getLastPathSegment();
+                break;
+
+            default:
+            ...
+                // If the URI is not recognized, you should do some error handling here.
+        }
+        // call the code to actually do the query
+    }
+</pre>
+<p>
+    Kelas lainnya, {@link android.content.ContentUris}, menyediakan metode praktis untuk menggunakan
+    bagian <code>id</code> URI konten. Kelas-kelas {@link android.net.Uri} dan
+    {@link android.net.Uri.Builder} menyertakan metode praktis untuk mengurai
+    objek {@link android.net.Uri} yang ada dan membuat objek baru.
+</p>
+
+<!-- Implementing the ContentProvider class -->
+<h2 id="ContentProvider">Mengimplementasikan Kelas ContentProvider</h2>
+<p>
+    Instance {@link android.content.ContentProvider} mengelola akses
+    ke satu set data terstruktur dengan menangani permintaan dari aplikasi lain. Semua bentuk
+    akses pada akhirnya akan memanggil {@link android.content.ContentResolver}, yang kemudian memanggil
+    metode konkret {@link android.content.ContentProvider} untuk mendapatkan akses.
+</p>
+<h3 id="RequiredAccess">Metode-metode yang diperlukan</h3>
+<p>
+    Kelas abstrak {@link android.content.ContentProvider} mendefinisikan enam metode abstrak yang
+    harus Anda implementasikan sebagai bagian dari subkelas konkret Anda sendiri. Semua metode ini kecuali
+    {@link android.content.ContentProvider#onCreate() onCreate()} dipanggil oleh aplikasi klien
+    yang berupaya mengakses penyedia konten Anda:
+</p>
+<dl>
+    <dt>
+        {@link android.content.ContentProvider#query(Uri, String[], String, String[], String)
+        query()}
+    </dt>
+    <dd>
+        Mengambil data dari penyedia Anda. Menggunakan argumen untuk memilih tabel yang akan
+        di-query, baris dan kolom yang akan dihasilkan, dan urutan sortir hasilnya.
+        Menghasilkan data berupa objek {@link android.database.Cursor}.
+    </dd>
+    <dt>
+        {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()}
+    </dt>
+    <dd>
+        Menyisipkan baris baru ke dalam penyedia Anda. Menggunakan argumen untuk memilih
+        tabel tujuan dan mendapatkan nilai-nilai kolom yang akan digunakan. Menghasilkan URI konten untuk
+        baris yang baru disisipkan.
+    </dd>
+    <dt>
+        {@link android.content.ContentProvider#update(Uri, ContentValues, String, String[])
+        update()}
+    </dt>
+    <dd>
+        Memperbarui baris yang ada di penyedia Anda. Menggunakan argumen untuk memilih tabel dan baris
+        yang akan diperbarui dan mendapatkan nilai-nilai kolom yang diperbarui. Menghasilkan jumlah baris yang diperbarui.
+    </dd>
+    <dt>
+        {@link android.content.ContentProvider#delete(Uri, String, String[]) delete()}
+    </dt>
+    <dd>
+        Menghapus baris dari penyedia Anda. Menggunakan argumen untuk memilih tabel dan baris yang akan
+        dihapus. Menghasilkan jumlah baris yang dihapus.
+    </dd>
+    <dt>
+        {@link android.content.ContentProvider#getType(Uri) getType()}
+    </dt>
+    <dd>
+        Menghasilkan tipe MIME yang sesuai dengan URI konten. Metode ini dijelaskan lebih detail
+        di bagian <a href="#MIMETypes">Mengimplementasikan Tipe MIME Penyedia Konten</a>.
+    </dd>
+    <dt>
+        {@link android.content.ContentProvider#onCreate() onCreate()}
+    </dt>
+    <dd>
+        Inisialisasi penyedia Anda. Sistem Android memanggil metode ini segera setelah
+        membuat penyedia Anda. Perhatikan bahwa penyedia Anda tidak dibuat hingga
+        objek {@link android.content.ContentResolver} mencoba mengaksesnya.
+    </dd>
+</dl>
+<p>
+    Perhatikan bahwa metode-metode ini memiliki signature yang sama dengan
+    metode-metode {@link android.content.ContentResolver} yang sama namanya.
+</p>
+<p>
+    Implementasi metode-metode ini harus memperhitungkan hal-hal berikut:
+</p>
+<ul>
+    <li>
+        Semua metode ini kecuali {@link android.content.ContentProvider#onCreate() onCreate()}
+        bisa dipanggil oleh beberapa thread sekaligus, jadi harus thread-safe (aman untuk thread). Untuk mengetahui
+        selengkapnya tentang multi-thread, lihat topik
+        <a href="{@docRoot}guide/components/processes-and-threads.html">
+        Proses dan Thread</a>.
+    </li>
+    <li>
+        Hindari melakukan operasi yang lama dalam {@link android.content.ContentProvider#onCreate()
+        onCreate()}. Tunda inisialisasi tugas hingga benar-benar diperlukan.
+        Bagian <a href="#OnCreate">Mengimplementasikan metode onCreate()</a>
+        membahas hal ini secara lebih detail.
+    </li>
+    <li>
+        Walaupun harus mengimplementasikan metode-metode ini, kode Anda tidak harus melakukan apa pun selain
+        tipe data yang diharapkan. Misalnya, Anda mungkin ingin mencegah aplikasi lain
+        menyisipkan data ke dalam beberapa tabel. Caranya, Anda bisa mengabaikan panggilan ke
+        {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()} dan menghasilkan
+        0.
+    </li>
+</ul>
+<h3 id="Query">Mengimplementasikan metode query()</h3>
+<p>
+    Metode
+    {@link android.content.ContentProvider#query(Uri, String[], String, String[], String)
+    ContentProvider.query()} harus menghasilkan objek {@link android.database.Cursor}, atau jika
+    gagal, melontarkan {@link java.lang.Exception}. Jika menggunakan database SQLite sebagai
+    penyimpanan data, Anda bisa mengembalikan{@link android.database.Cursor} yang dikembalikan oleh salah satu metode
+    <code>query()</code> dari kelas {@link android.database.sqlite.SQLiteDatabase}.
+    Jika query tidak mencocokkan baris apa pun, Anda harus mengembalikan instance {@link android.database.Cursor}
+    yang metode {@link android.database.Cursor#getCount()}-nya mengembalikan 0.
+    Anda harus mengembalikan <code>null</code> hanya jika terjadi kesalahan internal selama proses query.
+</p>
+<p>
+    Jika Anda tidak menggunakan database SQLite sebagai penyimpanan data, gunakan salah satu subkelas konkret
+    {@link android.database.Cursor}. Misalnya, kelas {@link android.database.MatrixCursor}
+    mengimplementasikan kursor dengan masing-masing baris berupa larik {@link java.lang.Object}. Dengan kelas ini,
+    gunakan {@link android.database.MatrixCursor#addRow(Object[]) addRow()} untuk menambahkan baris baru.
+</p>
+<p>
+    Ingatlah bahwa sistem Android harus mampu mengomunikasikan {@link java.lang.Exception}
+    lintas batas proses. Android bisa melakukannya untuk eksepsi berikut yang mungkin berguna
+    dalam menangani kesalahan query:
+</p>
+<ul>
+    <li>
+        {@link java.lang.IllegalArgumentException} (Anda bisa saja melontarkannya jika penyedia Anda
+        menerima URI konten yang tidak sah)
+    </li>
+    <li>
+        {@link java.lang.NullPointerException}
+    </li>
+</ul>
+<h3 id="Insert">Mengimplementasikan metode insert()</h3>
+<p>
+    Metode {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()} menambahkan satu
+    baris baru ke tabel yang sesuai, dengan menggunakan nilai-nilai dalam argumen {@link android.content.ContentValues}.
+ Jika kolom nama tidak ada dalam argumen {@link android.content.ContentValues}, Anda
+    mungkin perlu menyediakan nilai default untuknya, baik dalam kode penyedia atau dalam skema database
+    Anda.
+</p>
+<p>
+    Metode ini harus mengembalikan URI konten untuk baris baru. Untuk membuatnya, tambahkan nilai
+    <code>_ID</code> baris baru (atau kunci utama lainnya) ke tabel URI konten, dengan menggunakan
+    {@link android.content.ContentUris#withAppendedId(Uri, long) withAppendedId()}.
+</p>
+<h3 id="Delete">Mengimplementasikan metode delete()</h3>
+<p>
+    Metode {@link android.content.ContentProvider#delete(Uri, String, String[]) delete()}
+    tidak harus menghapus baris-baris dari penyimpanan data Anda secara fisik. Jika menggunakan adaptor sinkronisasi
+    bersama penyedia, Anda harus mempertimbangkan penandaan baris yang dihapus
+    dengan flag "delete"; bukan menghilangkan baris itu sepenuhnya. Adaptor sinkronisasi bisa
+    memeriksa baris yang dihapus dan menghilangkannya dari server sebelum menghapusnya dari penyedia.
+</p>
+<h3 id="Update">Mengimplementasikan metode update()</h3>
+<p>
+    Metode {@link android.content.ContentProvider#update(Uri, ContentValues, String, String[])
+    update()} mengambil argumen {@link android.content.ContentValues} yang sama dengan yang digunakan oleh
+    {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()}, dan
+    argumen-argumen <code>selection</code> dan <code>selectionArgs</code> yang sama dengan yang digunakan oleh
+    {@link android.content.ContentProvider#delete(Uri, String, String[]) delete()} dan
+    {@link android.content.ContentProvider#query(Uri, String[], String, String[], String)
+    ContentProvider.query()}. Hal ini bisa memungkinkan Anda menggunakan kembali kode di antara metode-metode ini.
+</p>
+<h3 id="OnCreate">Mengimplementasikan metode onCreate()</h3>
+<p>
+    Sistem Android memanggil {@link android.content.ContentProvider#onCreate()
+    onCreate()} saat memulai penyedia. Anda harus melakukan tugas-tugas inisialisasi yang berjalan cepat saja
+    dalam metode ini, serta menunda pembuatan database dan pemuatan data hingga penyedia benar-benar
+    menerima permintaan terhadap data. Jika Anda melakukan tugas yang memakan waktu dalam
+    {@link android.content.ContentProvider#onCreate() onCreate()}, Anda akan memperlambat
+    startup penyedia. Pada gilirannya, hal ini akan memperlambat respons dari penyedia terhadap
+    aplikasi lain.
+</p>
+<p>
+    Misalnya, jika menggunakan database SQLite, Anda bisa membuat
+    sebuah objek {@link android.database.sqlite.SQLiteOpenHelper} baru di
+    {@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()},
+    kemudian membuat tabel-tabel SQL saat pertama kali membuka database itu. Untuk memperlancar hal ini,
+    saat pertama Anda memanggil {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase
+    getWritableDatabase()}, metode ini memanggil metode
+    {@link android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase)
+    SQLiteOpenHelper.onCreate()} secara otomatis.
+</p>
+<p>
+    Dua cuplikan berikut memperagakan interaksi antara
+    {@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()} dan
+    {@link android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase)
+    SQLiteOpenHelper.onCreate()}. Cuplikan pertama adalah implementasi
+    {@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()}:
+</p>
+<pre class="prettyprint">
+public class ExampleProvider extends ContentProvider
+
+    /*
+     * Defines a handle to the database helper object. The MainDatabaseHelper class is defined
+     * in a following snippet.
+     */
+    private MainDatabaseHelper mOpenHelper;
+
+    // Defines the database name
+    private static final String DBNAME = "mydb";
+
+    // Holds the database object
+    private SQLiteDatabase db;
+
+    public boolean onCreate() {
+
+        /*
+         * Creates a new helper object. This method always returns quickly.
+         * Notice that the database itself isn't created or opened
+         * until SQLiteOpenHelper.getWritableDatabase is called
+         */
+        mOpenHelper = new MainDatabaseHelper(
+            getContext(),        // the application context
+            DBNAME,              // the name of the database)
+            null,                // uses the default SQLite cursor
+            1                    // the version number
+        );
+
+        return true;
+    }
+
+    ...
+
+    // Implements the provider's insert method
+    public Cursor insert(Uri uri, ContentValues values) {
+        // Insert code here to determine which table to open, handle error-checking, and so forth
+
+        ...
+
+        /*
+         * Gets a writeable database. This will trigger its creation if it doesn't already exist.
+         *
+         */
+        db = mOpenHelper.getWritableDatabase();
+    }
+}
+</pre>
+<p>
+    Cuplikan berikutnya adalah implementasi
+    {@link android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase)
+    SQLiteOpenHelper.onCreate()}, yang menyertakan kelas helper:
+</p>
+<pre class="prettyprint">
+...
+// A string that defines the SQL statement for creating a table
+private static final String SQL_CREATE_MAIN = "CREATE TABLE " +
+    "main " +                       // Table's name
+    "(" +                           // The columns in the table
+    " _ID INTEGER PRIMARY KEY, " +
+    " WORD TEXT"
+    " FREQUENCY INTEGER " +
+    " LOCALE TEXT )";
+...
+/**
+ * Helper class that actually creates and manages the provider's underlying data repository.
+ */
+protected static final class MainDatabaseHelper extends SQLiteOpenHelper {
+
+    /*
+     * Instantiates an open helper for the provider's SQLite data repository
+     * Do not do database creation and upgrade here.
+     */
+    MainDatabaseHelper(Context context) {
+        super(context, DBNAME, null, 1);
+    }
+
+    /*
+     * Creates the data repository. This is called when the provider attempts to open the
+     * repository and SQLite reports that it doesn't exist.
+     */
+    public void onCreate(SQLiteDatabase db) {
+
+        // Creates the main table
+        db.execSQL(SQL_CREATE_MAIN);
+    }
+}
+</pre>
+
+
+<!-- Implementing ContentProvider MIME Types -->
+<h2 id="MIMETypes">Mengimplementasikan Tipe MIME Penyedia Konten</h2>
+<p>
+    Kelas {@link android.content.ContentProvider} memiliki dua metode untuk menghasilkan tipe-tipe MIME:
+</p>
+<dl>
+    <dt>
+        {@link android.content.ContentProvider#getType(Uri) getType()}
+    </dt>
+    <dd>
+        Salah satu metode wajib yang harus Anda implementasikan untuk setiap penyedia.
+    </dd>
+    <dt>
+        {@link android.content.ContentProvider#getStreamTypes(Uri, String) getStreamTypes()}
+    </dt>
+    <dd>
+        Sebuah metode yang diharapkan untuk Anda implementasikan jika penyedia Anda menawarkan file.
+    </dd>
+</dl>
+<h3 id="TableMIMETypes">Tipe MIME untuk tabel</h3>
+<p>
+    Metode {@link android.content.ContentProvider#getType(Uri) getType()} mengembalikan
+    {@link java.lang.String} dengan format MIME yang menjelaskan tipe data yang dikembalikan oleh
+    argumen URI konten. Argumen {@link android.net.Uri} bisa berupa pola, bukannya URI tertentu;
+    dalam hal ini, Anda harus mengembalikan tipe data terkait URI konten yang cocok dengan
+    polanya.
+</p>
+<p>
+    Untuk tipe data umum misalnya teks, HTML, atau JPEG,
+    {@link android.content.ContentProvider#getType(Uri) getType()} harus mengembalikan
+    tipe MIME standar untuk data itu. Daftar lengkap tipe standar ini tersedia di situs web
+    <a href="http://www.iana.org/assignments/media-types/index.htm">IANA MIME Media Types</a>.
+
+</p>
+<p>
+    Untuk URI konten yang menunjuk ke baris atau baris-baris data tabel,
+    {@link android.content.ContentProvider#getType(Uri) getType()} harus mengembalikan
+    tipe MIME dalam format MIME khusus vendor Android:
+</p>
+<ul>
+    <li>
+        Bagian tipe: <code>vnd</code>
+    </li>
+    <li>
+        Bagian subtipe:
+        <ul>
+            <li>
+    Jika pola URI adalah untuk satu baris: <code>android.cursor.<strong>item</strong>/</code>
+            </li>
+            <li>
+    Jika pola URI adalah untuk lebih dari satu baris: <code>android.cursor.<strong>dir</strong>/</code>
+            </li>
+        </ul>
+    </li>
+    <li>
+        Bagian khusus penyedia: <code>vnd.&lt;name&gt;</code>.<code>&lt;type&gt;</code>
+        <p>
+            Anda menyediakan <code>&lt;name&gt;</code> dan <code>&lt;type&gt;</code>.
+            Nilai <code>&lt;name&gt;</code> harus unik secara global,
+            dan nilai <code>&lt;type&gt;</code> harus unik bagi pola URI
+            yang sesuai. Pilihan tepat untuk <code>&lt;name&gt;</code> adalah nama perusahaan Anda atau
+            sebagian dari nama paket Android aplikasi Anda. Pilihan tepat untuk
+            <code>&lt;type&gt;</code> adalah string yang mengidentifikasi tabel yang terkait dengan
+            URI.
+        </p>
+
+    </li>
+</ul>
+<p>
+    Misalnya, jika otoritas penyedia adalah
+    <code>com.example.app.provider</code>, dan penyedia mengekspos tabel bernama
+    <code>table1</code>, tipe MIME untuk beberapa baris dalam <code>table1</code> adalah:
+</p>
+<pre>
+vnd.android.cursor.<strong>dir</strong>/vnd.com.example.provider.table1
+</pre>
+<p>
+    Untuk satu baris <code>table1</code>, tipe MIME adalah:
+</p>
+<pre>
+vnd.android.cursor.<strong>item</strong>/vnd.com.example.provider.table1
+</pre>
+<h3 id="FileMIMETypes">Tipe MIME untuk file</h3>
+<p>
+    Jika penyedia Anda menawarkan file, implementasikan
+    {@link android.content.ContentProvider#getStreamTypes(Uri, String) getStreamTypes()}.
+    Metode ini menghasilkan larik {@link java.lang.String} tipe MIME untuk file
+    yang bisa dikembalikan penyedia Anda untuk URI konten bersangkutan. Anda harus memfilter tipe MIME yang Anda tawarkan dengan argumen filter
+    tipe MIME, sehingga Anda hanya mengembalikan tipe MIME yang ingin ditangani klien.
+</p>
+<p>
+    Misalnya, perhatikan penyedia yang menawarkan gambar foto sebagai file dalam format <code>.jpg</code>,
+    <code>.png</code>, dan <code>.gif</code>.
+    Jika aplikasi memanggil {@link android.content.ContentResolver#getStreamTypes(Uri, String)
+    ContentResolver.getStreamTypes()} dengan string filter <code>image/*</code> (sesuatu yang
+    merupakan "gambar"),
+    maka metode {@link android.content.ContentProvider#getStreamTypes(Uri, String)
+    ContentProvider.getStreamTypes()} harus mengembalikan larik:
+</p>
+<pre>
+{ &quot;image/jpeg&quot;, &quot;image/png&quot;, &quot;image/gif&quot;}
+</pre>
+<p>
+    Jika aplikasi tertarik pada file <code>.jpg</code>, maka aplikasi bisa memanggil
+    {@link android.content.ContentResolver#getStreamTypes(Uri, String)
+    ContentResolver.getStreamTypes()} dengan string filter <code>*\/jpeg</code>, dan
+    {@link android.content.ContentProvider#getStreamTypes(Uri, String)
+    ContentProvider.getStreamTypes()} harus mengembalikan:
+<pre>
+{&quot;image/jpeg&quot;}
+</pre>
+<p>
+    Jika penyedia Anda tidak menawarkan tipe MIME apa pun yang diminta dalam string filter,
+    {@link android.content.ContentProvider#getStreamTypes(Uri, String) getStreamTypes()}
+    harus mengembalikan <code>null</code>.
+</p>
+
+
+<!--  Implementing a Contract Class -->
+<h2 id="ContractClass">Mengimplementasikan Kelas Kontrak</h2>
+<p>
+    Kelas kontrak adalah kelas <code>public final</code> yang berisi definisi konstanta untuk URI, nama kolom, tipe MIME, dan
+metadata lain yang melekat ke penyedia. Kelas
+    membentuk sebuah kontrak antara penyedia dan aplikasi lain dengan memastikan bahwa penyedia
+    bisa diakses dengan benar sekalipun ada perubahan pada nilai URI sesungguhnya, nama kolom,
+    dan seterusnya.
+</p>
+<p>
+    Kelas kontrak juga membantu pengembang karena kelas ini biasanya memiliki nama-nama simbolik untuk konstantanya,
+    sehingga memperkecil kemungkinan pengembang menggunakan nilai yang salah untuk nama kolom atau URI. Karena berupa
+    kelas, kelas ini bisa berisi dokumentasi Javadoc. Lingkungan pengembangan terpadu (IDE) seperti
+    Eclipse secara otomatis bisa melengkapi nama-nama konstanta dari kelas kontrak dan menampilkan Javadoc untuk
+    konstanta.
+</p>
+<p>
+    Pengembang tidak bisa mengakses file kelas milik kelas kontrak dari aplikasi Anda, namun bisa
+    mengompilasinya secara statis ke dalam aplikasi mereka dari file <code>.jar</code> yang Anda sediakan.
+</p>
+<p>
+    Kelas {@link android.provider.ContactsContract} dan kelas-kelas tersarangnya adalah contoh
+    kelas kontrak.
+</p>
+<h2 id="Permissions">Mengimplementasikan Izin Penyedia Konten</h2>
+<p>
+    Izin dan akses untuk semua aspek sistem Android dijelaskan secara detail dalam
+    topik <a href="{@docRoot}guide/topics/security/security.html">Keamanan dan Izin</a>.
+    Topik <a href="{@docRoot}guide/topics/data/data-storage.html">Penyimpanan Data</a> juga
+    menjelaskan keamanan dan izin terkait dengan berbagai tipe penyimpanan.
+    Singkatnya, poin-poin pentingnya adalah:
+</p>
+<ul>
+    <li>
+        Secara default, file data yang disimpan pada penyimpanan internal perangkat bersifat privat bagi
+        aplikasi dan penyedia Anda.
+    </li>
+    <li>
+        Database {@link android.database.sqlite.SQLiteDatabase} yang Anda buat bersifat privat bagi
+        aplikasi dan penyedia Anda.
+    </li>
+    <li>
+        Secara default, file data yang Anda simpan ke penyimpanan eksternal bersifat <em>publik</em> dan
+        <em>bisa dibaca secara global</em>. Anda tidak bisa menggunakan penyedia konten untuk membatasi akses ke file dalam
+        penyimpanan eksternal, karena aplikasi lain bisa menggunakan panggilan API untuk membaca dan menulis ke file tersebut.
+    </li>
+    <li>
+        Panggilan metode untuk membuka atau membuat file atau database SQLite pada
+        penyimpanan internal perangkat Anda berpotensi memberikan akses baca maupun tulis ke semua aplikasi lain. Jika Anda
+        menggunakan file atau database internal sebagai repository penyedia, dan Anda memberinya
+        akses "world-readable" (bisa dibaca secara global) atau "world-writeable" (bisa ditulis secara global), izin yang Anda atur untuk penyedia dalam
+        manifesnya tidak akan melindungi data Anda. Akses default untuk file dan database dalam
+        penyimpanan internal adalah "privat", dan untuk repository penyedia, tidak boleh Anda ubah.
+    </li>
+</ul>
+<p>
+    Jika Anda ingin menggunakan izin penyedia konten untuk mengontrol akses ke data Anda, maka Anda harus
+    menyimpan data Anda dalam file internal, database SQLite, atau "cloud" (misalnya,
+    di server jauh), dan Anda harus membuat file dan database tetap privat bagi aplikasi Anda.
+</p>
+<h3>Mengimplementasikan izin</h3>
+<p>
+    Semua aplikasi bisa membaca dari atau menulis ke penyedia Anda, sekalipun data yang mendasari adalah
+    privat, karena secara default penyedia Anda tidak mengatur izin. Untuk mengubahnya,
+    atur izin untuk penyedia dalam file manifes, dengan menggunakan atribut atau elemen anak
+    dari elemen <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
+    &lt;provider&gt;</a></code>. Anda bisa mengatur izin yang berlaku pada seluruh penyedia,
+    atau pada tabel tertentu, atau bahkan pada record tertentu, atau ketiganya.
+</p>
+<p>
+    Anda mendefinisikan izin untuk penyedia dengan satu atau beberapa elemen
+    <code><a href="{@docRoot}guide/topics/manifest/permission-element.html">
+    &lt;permission&gt;</a></code> dalam file manifes. Untuk membuat
+    izin unik bagi penyedia, gunakan scoping (pengaturan lingkup) bergaya Java untuk
+    atribut <code><a href="{@docRoot}guide/topics/manifest/permission-element.html#nm">
+    android:name</a></code>. Misalnya, beri nama izin membaca dengan
+    <code>com.example.app.provider.permission.READ_PROVIDER</code>.
+
+</p>
+<p>
+    Daftar berikut menjelaskan lingkup penyedia izin, mulai dengan
+    izin yang berlaku pada seluruh penyedia kemudian menjadi semakin sempit.
+    Izin yang lebih sempit akan didahulukan daripada izin yang berlingkup lebih luas:
+</p>
+<dl>
+    <dt>
+        Izin baca-tulis tunggal tingkat penyedia
+    </dt>
+    <dd>
+        Suatu izin yang mengontrol akses baca-tulis bagi seluruh penyedia, ditetapkan
+        dengan atribut <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn">
+        android:permission</a></code> dari
+        elemen <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
+        &lt;provider&gt;</a></code>.
+    </dd>
+    <dt>
+        Izin baca-tulis terpisah tingkat penyedia
+    </dt>
+    <dd>
+        Satu izin baca dan satu izin tulis untuk seluruh penyedia. Anda menetapkan keduanya
+        dengan atribut <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#rprmsn">
+        android:readPermission</a></code> dan
+        <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#wprmsn">
+        android:writePermission</a></code> dari elemen
+        <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
+        &lt;provider&gt;</a></code>. Kedua izin akan didahulukan daripada izin yang diharuskan oleh
+        <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn">
+        android:permission</a></code>.
+    </dd>
+    <dt>
+        Izin tingkat path
+    </dt>
+    <dd>
+        Izin baca, tulis, atau baca/tulis untuk URI konten dalam penyedia Anda. Anda menetapkan
+        tiap URI yang ingin dikontrol dengan elemen anak
+        <code><a href="{@docRoot}guide/topics/manifest/path-permission-element.html">
+        &lt;path-permission&gt;</a></code> dari
+        elemen <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
+        &lt;provider&gt;</a></code>. Untuk setiap URI konten yang ditetapkan, Anda bisa menetapkan
+        satu izin baca/tulis, satu izin baca, atau satu izin tulis, atau ketiganya. Izin baca dan
+        tulis akan didahulukan daripada izin baca/tulis. Juga,
+        izin tingkat path akan didahulukan daripada izin tingkat penyedia.
+    </dd>
+    <dt>
+        Izin sementara
+    </dt>
+    <dd>
+        Tingkat izin yang memberikan akses sementara ke aplikasi, sekalipun aplikasi itu
+        tidak memiliki izin yang biasanya diminta. Fitur akses
+         sementara mengurangi jumlah izin yang harus diminta aplikasi dalam
+        manifesnya. Bila Anda mengaktifkan izin sementara, satu-satunya aplikasi yang memerlukan
+        izin "permanen" untuk penyedia adalah aplikasi yang mengakses terus-menerus semua
+        data Anda.
+        <p>
+            Perhatikan izin yang Anda perlukan untuk mengimplementasikan penyedia dan aplikasi email, bila Anda
+            ingin memperbolehkan aplikasi penampil gambar dari luar menampilkan lampiran foto dari
+            penyedia Anda. Untuk memberikan akses yang diperlukan kepada penampil gambar tanpa mengharuskan izin,
+            siapkan izin sementara untuk URI konten bagi foto. Desainlah aplikasi email Anda agar
+            bila pengguna ingin menampilkan foto, aplikasi itu akan mengirim intent berisi
+            URI konten foto dan flag izin ke penampil gambar. Penampil gambar nanti bisa
+            melakukan query penyedia email untuk mengambil foto, sekalipun penampil itu tidak
+            memiliki izin baca normal untuk penyedia Anda.
+        </p>
+        <p>
+            Untuk mengaktifkan izin sementara, atur atribut
+            <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">
+            android:grantUriPermissions</a></code> dari
+            elemen <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
+            &lt;provider&gt;</a></code>, atau tambahkan satu atau beberapa elemen anak
+            <code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">
+            &lt;grant-uri-permission&gt;</a></code> ke
+            elemen <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
+            &lt;provider&gt;</a></code> Anda. Jika menggunakan izin sementara, Anda harus memanggil
+            {@link android.content.Context#revokeUriPermission(Uri, int)
+            Context.revokeUriPermission()} kapan saja Anda menghilangkan dukungan untuk URI konten dari
+            penyedia, dan URI konten dikaitkan dengan izin sementara.
+        </p>
+        <p>
+            Nilai atribut menentukan seberapa banyak penyedia Anda yang dijadikan bisa diakses.
+            Jika atribut diatur ke <code>true</code>, maka sistem akan memberikan
+            izin sementara kepada seluruh penyedia, dengan mengesampingkan izin lain yang diharuskan
+            oleh izin tingkat penyedia atau tingkat path.
+        </p>
+        <p>
+            Jika flag ini diatur ke <code>false</code>, maka Anda harus menambahkan elemen-elemen anak
+            <code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">
+            &lt;grant-uri-permission&gt;</a></code> ke
+            elemen <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
+            &lt;provider&gt;</a></code> Anda. Tiap elemen anak menetapkan URI konten atau
+            URI yang telah diberi akses sementara.
+        </p>
+        <p>
+            Untuk mendelegasikan akses sementara ke sebuah aplikasi, intent harus berisi
+            {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION} atau flag
+            {@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION}, atau keduanya. Keduanya
+            diatur dengan metode {@link android.content.Intent#setFlags(int) setFlags()}.
+        </p>
+        <p>
+            Jika atribut <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">
+            android:grantUriPermissions</a></code> tidak ada, atribut ini diasumsikan sebagai
+            <code>false</code>.
+        </p>
+    </dd>
+</dl>
+
+
+
+<!-- The Provider Element -->
+<h2 id="ProviderElement">Elemen &lt;provider&gt;</h2>
+<p>
+    Seperti halnya komponen {@link android.app.Activity} dan {@link android.app.Service},
+    subkelas {@link android.content.ContentProvider}
+    harus didefinisikan dalam file manifes untuk aplikasinya, dengan menggunakan elemen
+    <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
+    &lt;provider&gt;</a></code>. Sistem Android mendapatkan informasi berikut dari
+    elemen:
+<dl>
+    <dt>
+        Otoritas
+        (<a href="{@docRoot}guide/topics/manifest/provider-element.html#auth">{@code
+        android:authorities}</a>)
+    </dt>
+    <dd>
+        Nama-nama simbolik yang mengidentifikasi seluruh penyedia dalam sistem. Atribut
+        ini dijelaskan lebih detail di bagian
+        <a href="#ContentURI">Mendesain URI Konten</a>.
+    </dd>
+    <dt>
+        Nama kelas penyedia
+        (<code>
+<a href="{@docRoot}guide/topics/manifest/provider-element.html#nm">android:name</a>
+        </code>)
+    </dt>
+    <dd>
+        Kelas yang mengimplementasikan {@link android.content.ContentProvider}. Kelas ini
+        dijelaskan lebih detail di bagian
+        <a href="#ContentProvider">Mengimplementasikan Kelas ContentProvider</a>.
+    </dd>
+    <dt>
+        Izin
+    </dt>
+    <dd>
+        Atribut-atribut yang menetapkan izin yang harus dimiliki aplikasi lain untuk mengakses
+        data penyedia:
+        <ul>
+            <li>
+                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">
+                android:grantUriPermssions</a></code>: Flag izin sementara.
+            </li>
+            <li>
+                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn">
+                android:permission</a></code>: Izin baca/tulis tunggal untuk tingkat penyedia.
+            </li>
+            <li>
+                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#rprmsn">
+                android:readPermission</a></code>: Izin baca untuk tingkat penyedia.
+            </li>
+            <li>
+                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#wprmsn">
+                android:writePermission</a></code>: Izin tulis untuk tingkat penyedia.
+            </li>
+        </ul>
+        <p>
+            Izin dan atribut-atribut yang sesuai dijelaskan lebih detail
+            di bagian
+            <a href="#Permissions">Mengimplementasikan Izin Penyedia Konten</a>.
+        </p>
+    </dd>
+    <dt>
+        Atribut-atribut startup dan kontrol
+    </dt>
+    <dd>
+        Atribut-atribut ini menentukan cara dan waktu sistem Android memulai penyedia,
+        karakteristik proses penyedia, dan pengaturan runtime lainnya:
+        <ul>
+            <li>
+                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#enabled">
+                android:enabled</a></code>: Flag yang memperbolehkan sistem untuk memulai penyedia.
+            </li>
+              <li>
+                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#exported">
+                android:exported</a></code>: Flag yang memperbolehkan aplikasi lain untuk menggunakan penyedia ini.
+            </li>
+            <li>
+                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#init">
+                android:initOrder</a></code>: Urutan yang digunakan untuk memulai penyedia ini,
+                relatif terhadap penyedia lain dalam proses yang sama.
+            </li>
+            <li>
+                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#multi">
+                android:multiProcess</a></code>: Flag yang memperbolehkan sistem untuk memulai penyedia
+                dalam proses yang sama dengan proses klien pemanggil.
+            </li>
+            <li>
+                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#proc">
+                android:process</a></code>: Nama proses tempat penyedia harus
+                berjalan.
+            </li>
+            <li>
+                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#sync">
+                android:syncable</a></code>: Flag yang menunjukkan bahwa data penyedia harus
+                disinkronkan dengan data di server.
+            </li>
+        </ul>
+        <p>
+            Atribut-atribut ini didokumentasikan dengan lengkap dalam topik panduan pengembang untuk elemen
+            <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
+            &lt;provider&gt;</a></code>.
+
+        </p>
+    </dd>
+    <dt>
+        Atribut-atribut informatif
+    </dt>
+    <dd>
+        Ikon dan label opsional untuk penyedia:
+        <ul>
+            <li>
+                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#icon">
+                android:icon</a></code>: Sumber daya drawable, berisi ikon untuk penyedia.
+                Ikon ini muncul di sebelah label penyedia dalam daftar aplikasi dalam menu
+                <em>Settings</em> &gt; <em>Apps</em> &gt; <em>All</em>.
+            </li>
+            <li>
+                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#label">
+                android:label</a></code>: Label informatif yang menjelaskan penyedia atau
+                datanya, atau keduanya. Label ini muncul dalam daftar aplikasi di
+                <em>Settings</em> &gt; <em>Apps</em> &gt; <em>All</em>.
+            </li>
+        </ul>
+        <p>
+            Atribut-atribut ini didokumentasikan dengan lengkap dalam topik panduan pengembang untuk elemen
+            <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
+            &lt;provider&gt;</a></code>.
+        </p>
+    </dd>
+</dl>
+
+<!-- Intent Access -->
+<h2 id="Intents">Intent dan Akses Data</h2>
+<p>
+    Aplikasi bisa mengakses penyedia konten secara tidak langsung dengan sebuah {@link android.content.Intent}.
+    Aplikasi tidak memanggil satu pun dari metode-metode {@link android.content.ContentResolver} atau
+    {@link android.content.ContentProvider}. Sebagai gantinya, aplikasi mengirim intent yang memulai aktivitas,
+    yang sering kali merupakan bagian dari aplikasi penyedia sendiri. Aktivitas tujuan bertugas
+    mengambil dan menampilkan data dalam UI-nya. Bergantung pada tindakan dalam intent,
+    aktivitas tujuan juga bisa meminta pengguna untuk membuat modifikasi pada data penyedia.
+    Intent juga bisa berisi data "ekstra" yang menampilkan aktivitas tujuan
+    dalam UI; pengguna nanti memiliki pilihan untuk mengubah data ini sebelum menggunakannya untuk mengubah
+    data di penyedia.
+</p>
+<p>
+
+</p>
+<p>
+    Anda mungkin perlu menggunakan akses intent guna membantu memastikan integritas data. Penyedia Anda mungkin bergantung
+    pada data yang disisipkan, diperbarui, dan dihapusnya sesuai dengan logika bisnis yang didefinisikan dengan ketat. Jika
+    demikian halnya, memperbolehkan aplikasi lain mengubah data Anda secara langsung bisa menyebabkan
+    data yang tidak sah. Jika Anda ingin pengembang menggunakan akses intent, pastikan untuk mendokumentasikannya secara saksama.
+    Jelaskan kepada mereka alasan akses intent yang menggunakan UI aplikasi Anda sendiri adalah lebih baik daripada mencoba
+    memodifikasi data dengan kode mereka.
+</p>
+<p>
+    Menangani sebuah intent masuk yang ingin memodifikasi data penyedia Anda tidak berbeda dengan
+    menangani intent lainnya. Anda bisa mengetahui selengkapnya tentang penggunaan intent dengan membaca topik
+    <a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter Intent</a>.
+</p>
diff --git a/docs/html-intl/intl/id/guide/topics/providers/content-providers.jd b/docs/html-intl/intl/id/guide/topics/providers/content-providers.jd
new file mode 100644
index 0000000..2dcd55e
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/providers/content-providers.jd
@@ -0,0 +1,108 @@
+page.title=Penyedia konten
+@jd:body
+<div id="qv-wrapper">
+<div id="qv">
+
+
+<!-- In this document -->
+<h2>Topik</h2>
+<ol>
+    <li>
+        <a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
+        Dasar-Dasar Penyedia Konten</a>
+    </li>
+    <li>
+        <a href="{@docRoot}guide/topics/providers/content-provider-creating.html">
+        Membuat Penyedia Konten</a>
+    </li>
+    <li>
+        <a href="{@docRoot}guide/topics/providers/calendar-provider.html">Penyedia Kalender</a>
+    </li>
+    <li>
+        <a href="{@docRoot}guide/topics/providers/contacts-provider.html">Penyedia Kontak</a>
+    </li>
+</ol>
+
+    <!-- Related Samples -->
+<h2>Contoh-Contoh Terkait</h2>
+    <ol>
+        <li>
+            <a href="{@docRoot}resources/samples/ContactManager/index.html">
+            Aplikasi Contact Manager</a>
+        </li>
+        <li>
+        <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/List2.html">
+        "Kursor (Orang)"
+        </a>
+        </li>
+        <li>
+        <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/List7.html">
+        "Kursor (Telepon)"</a>
+        </li>
+        <li>
+            <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">
+            Contoh Adaptor Sinkronisasi</a>
+        </li>
+    </ol>
+</div>
+</div>
+<p>
+    Penyedia konten mengelola akses ke set data terstruktur. Penyedia ini membungkus
+ data, dan menyediakan mekanisme untuk mendefinisikan keamanan data. Penyedia konten adalah antarmuka
+ standar yang menghubungkan data dalam satu proses dengan kode yang berjalan dalam proses lain.
+</p>
+<p>
+    Bila Anda ingin mengakses data di penyedia konten, Anda menggunakan
+ {@link android.content.ContentResolver} objek dalam
+ {@link android.content.Context} aplikasi untuk berkomunikasi dengan penyedia sebagai klien.
+    Objek {@link android.content.ContentResolver} berkomunikasi dengan objek penyedia, yakni
+ instance kelas yang mengimplementasikan {@link android.content.ContentProvider}. Objek penyedia
+ menerima permintaan data dari klien, melakukan tindakan yang diminta, dan
+ mengembalikan hasilnya.
+</p>
+<p>
+    Anda tidak perlu mengembangkan penyedia sendiri jika tidak bermaksud untuk berbagi data dengan
+ aplikasi lain. Akan tetapi, Anda memerlukan penyedia buatan sendiri untuk menyediakan saran pencarian custom
+ dalam aplikasi Anda sendiri. Anda juga memerlukan penyedia sendiri jika ingin menyalin dan
+menempelkan data atau file yang kompleks dari aplikasi Anda ke aplikasi lain.
+</p>
+<p>
+    Android sendiri berisi penyedia konten yang mengelola data seperti informasi audio, video, gambar, dan
+ kontak pribadi. Anda bisa melihat sebagian informasi ini tercantum dalam dokumentasi
+ acuan untuk paket
+ <code><a href="{@docRoot}reference/android/provider/package-summary.html">android.provider</a>
+    </code>. Dengan beberapa batasan, semua penyedia ini bisa diakses oleh aplikasi Android
+ apa saja.
+</p><p>
+    Topik-topik berikut menjelaskan penyedia konten secara lebih detail:
+</p>
+<dl>
+    <dt>
+        <strong><a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
+        Dasar-Dasar Penyedia Konten</a></strong>
+    </dt>
+    <dd>
+        Cara mengakses data di penyedia konten bila data disusun dalam tabel.
+    </dd>
+    <dt>
+        <strong><a href="{@docRoot}guide/topics/providers/content-provider-creating.html">
+        Membuat Penyedia Konten</a></strong>
+    </dt>
+    <dd>
+        Cara membuat penyedia konten sendiri.
+    </dd>
+    <dt>
+        <strong><a href="{@docRoot}guide/topics/providers/calendar-provider.html">
+        Penyedia Kalender</a></strong>
+    </dt>
+    <dd>
+        Cara mengakses Penyedia Kalender yang merupakan bagian dari platform Android.
+    </dd>
+    <dt>
+        <strong><a href="{@docRoot}guide/topics/providers/contacts-provider.html">
+        Penyedia Kontak</a></strong>
+    </dt>
+    <dd>
+        Cara mengakses Penyedia Kontak yang merupakan bagian dari platform Android.
+    </dd>
+</dl>
diff --git a/docs/html-intl/intl/id/guide/topics/providers/document-provider.jd b/docs/html-intl/intl/id/guide/topics/providers/document-provider.jd
new file mode 100644
index 0000000..f857467
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/providers/document-provider.jd
@@ -0,0 +1,916 @@
+page.title=Storage Access Framework
+@jd:body
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>Dalam dokumen ini
+ <a href="#" onclick="hideNestedItems('#toc44',this);return false;" class="header-toggle">
+        <span class="more">tampilkan maksimal</span>
+        <span class="less" style="display:none">tampilkan minimal</span></a></h2>
+<ol id="toc44" class="hide-nested">
+    <li>
+        <a href="#overview">Ikhtisar</a>
+    </li>
+    <li>
+        <a href="#flow">Arus Kontrol</a>
+    </li>
+    <li>
+        <a href="#client">Menulis Aplikasi Klien</a>
+        <ol>
+        <li><a href="#search">Mencari dokumen</a></li>
+        <li><a href="#process">Memproses hasil</a></li>
+        <li><a href="#metadata">Memeriksa metadata dokumen</a></li>
+        <li><a href="#open">Membuka dokumen</a></li>
+        <li><a href="#create">Membuat dokumen baru</a></li>
+        <li><a href="#delete">Menghapus dokumen</a></li>
+        <li><a href="#edit">Mengedit dokumen</a></li>
+        <li><a href="#permissions">Mempertahankan izin</a></li>
+        </ol>
+    </li>
+    <li><a href="#custom">Menulis Penyedia Dokumen Custom</a>
+        <ol>
+        <li><a href="#manifest">Manifes</a></li>
+        <li><a href="#contract">Kontrak</a></li>
+        <li><a href="#subclass">Subkelas DocumentsProvider</a></li>
+        <li><a href="#security">Keamanan</a></li>
+        </ol>
+    </li>
+
+</ol>
+<h2>Kelas-kelas utama</h2>
+<ol>
+    <li>{@link android.provider.DocumentsProvider}</li>
+    <li>{@link android.provider.DocumentsContract}</li>
+</ol>
+
+<h2>Video</h2>
+
+<ol>
+    <li><a href="http://www.youtube.com/watch?v=zxHVeXbK1P4">
+DevBytes: Android 4.4 Storage Access Framework: Penyedia</a></li>
+     <li><a href="http://www.youtube.com/watch?v=UFj9AEz0DHQ">
+DevBytes: Android 4.4 Storage Access Framework: Klien</a></li>
+</ol>
+
+
+<h2>Contoh Kode</h2>
+
+<ol>
+    <li><a href="{@docRoot}samples/StorageProvider/index.html">
+Penyedia Penyimpanan</a></li>
+     <li><a href="{@docRoot}samples/StorageClient/index.html">
+Klien Penyimpanan</a></li>
+</ol>
+
+<h2>Lihat Juga</h2>
+<ol>
+    <li>
+        <a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
+        Dasar-Dasar Penyedia Konten
+        </a>
+    </li>
+</ol>
+
+</div>
+</div>
+
+
+<p>Android 4.4 (API level 19) memperkenalkan Storage Access Framework (SAF, Kerangka Kerja Akses Penyimpanan). SAF
+ memudahkan pengguna menyusuri dan membuka dokumen, gambar, dan file lainnya
+di semua penyedia penyimpanan dokumen pilihannya. UI standar yang mudah digunakan
+memungkinkan pengguna menyusuri file dan mengakses yang terbaru dengan cara konsisten di antara berbagai aplikasi dan penyedia.</p>
+
+<p>Layanan penyimpanan cloud atau lokal bisa dilibatkan dalam ekosistem ini dengan mengimplementasikan sebuah
+{@link android.provider.DocumentsProvider} yang membungkus layanannya. Aplikasi klien
+yang memerlukan akses ke dokumen sebuah penyedia bisa berintegrasi dengan SAF cukup dengan beberapa
+baris kode.</p>
+
+<p>SAF terdiri dari berikut ini:</p>
+
+<ul>
+<li><strong>Penyedia dokumen</strong>&mdash;Penyedia konten yang memungkinkan
+layanan penyimpanan (seperti Google Drive) untuk menampilkan file yang dikelolanya. Penyedia dokumen
+diimplementasikan sebagai subkelas dari kelas {@link android.provider.DocumentsProvider}.
+Skema penyedia dokumen berdasarkan hierarki file biasa,
+walaupun cara penyedia dokumen Anda secara fisik menyimpan data adalah terserah Anda.
+Platform Android terdiri dari beberapa penyedia dokumen bawaan, seperti
+Downloads, Images, dan Videos.</li>
+
+<li><strong>Aplikasi klien</strong>&mdash;Aplikasi custom yang memanggil intent
+{@link android.content.Intent#ACTION_OPEN_DOCUMENT} dan/atau
+{@link android.content.Intent#ACTION_CREATE_DOCUMENT} dan menerima
+file yang dihasilkan penyedia dokumen.</li>
+
+<li><strong>Picker</strong>&mdash;UI sistem yang memungkinkan pengguna mengakses dokumen dari semua
+penyedia dokumen yang memenuhi kriteria pencarian aplikasi klien.</li>
+</ul>
+
+<p>Beberapa fitur yang disediakan oleh SAF adalah sebagai berikut:</p>
+<ul>
+<li>Memungkinkan pengguna menyusuri konten dari semua penyedia dokumen, bukan hanya satu aplikasi.</li>
+<li>Memungkinkan aplikasi Anda memiliki akses jangka panjang dan tetap ke
+ dokumen yang dimiliki oleh penyedia dokumen. Melalui akses ini pengguna bisa menambah, mengedit,
+ menyimpan, dan menghapus file pada penyedia.</li>
+<li>Mendukung banyak akun pengguna dan akar jangka pendek seperti penyedia penyimpanan
+USB, yang hanya muncul jika drive itu dipasang. </li>
+</ul>
+
+<h2 id ="overview">Ikhtisar</h2>
+
+<p>SAF berpusat di seputar penyedia konten yang merupakan
+subkelas dari kelas {@link android.provider.DocumentsProvider}. Dalam <em>penyedia dokumen</em>, data
+distrukturkan sebagai hierarki file biasa:</p>
+<p><img src="{@docRoot}images/providers/storage_datamodel.png" alt="data model" /></p>
+<p class="img-caption"><strong>Gambar 1.</strong> Model data penyedia dokumen. Root menunjuk ke satu Document,
+yang nanti memulai pemekaran seluruh pohon.</p>
+
+<p>Perhatikan yang berikut ini:</p>
+<ul>
+
+<li>Setiap penyedia dokumen melaporkan satu atau beberapa
+"akar" yang merupakan titik awal penyusuran pohon dokumen.
+Masing-masing akar memiliki sebuah {@link android.provider.DocumentsContract.Root#COLUMN_ROOT_ID} yang unik,
+dan menunjuk ke satu dokumen (satu direktori)
+yang mewakili konten di bawah akar itu.
+Akar sengaja dibuat dinamis untuk mendukung kasus penggunaan seperti multiakun,
+perangkat penyimpanan USB jangka pendek, atau masuk/keluar pengguna.</li>
+
+<li>Di bawah tiap akar terdapat satu dokumen. Dokumen itu menunjuk ke dokumen-dokumen 1-ke-<em>N</em>,
+yang nanti masing-masing bisa menunjuk ke dokumen 1-ke-<em>N</em>. </li>
+
+<li>Tiap backend penyimpanan memunculkan
+masing-masing file dan direktori dengan mengacunya lewat sebuah
+{@link android.provider.DocumentsContract.Document#COLUMN_DOCUMENT_ID} yang unik.
+ID dokumen harus unik dan tidak berubah setelah dibuat, karena ID ini digunakan untuk
+URI persisten yang diberikan pada saat reboot perangkat.</li>
+
+
+<li>Dokumen bisa berupa file yang bisa dibuka (dengan tipe MIME tertentu), atau
+direktori yang berisi dokumen tambahan (dengan tipe MIME
+{@link android.provider.DocumentsContract.Document#MIME_TYPE_DIR}).</li>
+
+<li>Tiap dokumen bisa mempunyai kemampuan berbeda, sebagaimana yang dijelaskan oleh
+{@link android.provider.DocumentsContract.Document#COLUMN_FLAGS COLUMN_FLAGS}.
+Misalnya, {@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_WRITE},
+{@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_DELETE}, dan
+{@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_THUMBNAIL}.
+{@link android.provider.DocumentsContract.Document#COLUMN_DOCUMENT_ID} yang sama bisa
+dimasukkan dalam beberapa direktori.</li>
+</ul>
+
+<h2 id="flow">Arus Kontrol</h2>
+<p>Seperti dinyatakan di atas, model data penyedia dokumen dibuat berdasarkan hierarki file
+biasa. Akan tetapi, Anda bisa menyimpan secara fisik data dengan cara apa pun yang disukai,
+selama data bisa diakses melalui API {@link android.provider.DocumentsProvider}. Misalnya, Anda
+bisa menggunakan penyimpanan cloud berbasis tag untuk data Anda.</p>
+
+<p>Gambar 2 menampilkan contoh cara aplikasi foto bisa menggunakan SAF
+untuk mengakses data tersimpan:</p>
+<p><img src="{@docRoot}images/providers/storage_dataflow.png" alt="app" /></p>
+
+<p class="img-caption"><strong>Gambar 2.</strong> Arus Storage Access Framework</p>
+
+<p>Perhatikan yang berikut ini:</p>
+<ul>
+
+<li>Di SAF, penyedia dan klien tidak berinteraksi
+secara langsung. Klien meminta izin untuk berinteraksi
+dengan file (yakni, membaca, mengedit, membuat, atau menghapus file).</li>
+
+<li>Interaksi dimulai bila sebuah aplikasi (dalam contoh ini adalah aplikasi foto) mengeluarkan intent
+{@link android.content.Intent#ACTION_OPEN_DOCUMENT} atau {@link android.content.Intent#ACTION_CREATE_DOCUMENT}. Intent bisa berisi filter
+untuk mempersempit kriteria&mdash;misalnya, "beri saya semua file yang bisa dibuka
+yang memiliki tipe MIME 'gambar'".</li>
+
+<li>Setelah intent dibuat, picker sistem akan pergi ke setiap penyedia yang terdaftar
+dan menunjukkan kepada pengguna akar konten yang cocok.</li>
+
+<li>Picker memberi pengguna antarmuka standar untuk mengakses dokumen,
+walaupun penyedia dokumen dasar bisa sangat berbeda. Misalnya, gambar 2
+menunjukkan penyedia Google Drive, penyedia USB, dan penyedia cloud.</li>
+</ul>
+
+<p>Gambar 3 menunjukkan picker yang di digunakan pengguna mencari gambar telah memilih
+akun Google Drive:</p>
+
+<p><img src="{@docRoot}images/providers/storage_picker.png" width="340" alt="picker" style="border:2px solid #ddd" /></p>
+
+<p class="img-caption"><strong>Gambar 3.</strong> Picker</p>
+
+<p>Bila pengguna memilih Google Drive, gambar-gambar akan ditampilkan, seperti yang ditampilkan dalam
+gambar 4. Dari titik itu, pengguna bisa berinteraksi dengan gambar dengan cara apa pun
+yang didukung oleh penyedia dan aplikasi klien.
+
+<p><img src="{@docRoot}images/providers/storage_photos.png" width="340" alt="picker" style="border:2px solid #ddd" /></p>
+
+<p class="img-caption"><strong>Gambar 4.</strong> Gambar</p>
+
+<h2 id="client">Menulis Aplikasi Klien</h2>
+
+<p>Pada Android 4.3 dan yang lebih rendah, jika Anda ingin aplikasi mengambil file dari
+aplikasi lain, aplikasi Anda harus memanggil intent seperti {@link android.content.Intent#ACTION_PICK}
+atau {@link android.content.Intent#ACTION_GET_CONTENT}. Pengguna nanti harus memilih
+satu aplikasi yang akan digunakan untuk mengambil file dan aplikasi yang dipilih harus menyediakan antarmuka pengguna
+bagi untuk menyusuri dan mengambil dari file yang tersedia. </p>
+
+<p>Pada Android 4.4 dan yang lebih tinggi, Anda mempunyai opsi tambahan dalam menggunakan intent
+{@link android.content.Intent#ACTION_OPEN_DOCUMENT},
+yang menampilkan UI picker yang dikontrol oleh sistem yang memungkinkan pengguna
+menyusuri semua file yang disediakan aplikasi lain. Dari satu UI ini, pengguna
+bisa mengambil file dari aplikasi apa saja yang didukung.</p>
+
+<p>{@link android.content.Intent#ACTION_OPEN_DOCUMENT}
+tidak dimaksudkan untuk menjadi pengganti {@link android.content.Intent#ACTION_GET_CONTENT}.
+Yang harus Anda gunakan bergantung pada kebutuhan aplikasi:</p>
+
+<ul>
+<li>Gunakan {@link android.content.Intent#ACTION_GET_CONTENT} jika Anda ingin aplikasi
+cuma membaca/mengimpor data. Dengan pendekatan ini, aplikasi akan mengimpor salinan data,
+misalnya file gambar.</li>
+
+<li>Gunakan {@link android.content.Intent#ACTION_OPEN_DOCUMENT} jika Anda ingin aplikasi
+memiliki akses jangka panjang dan jangka pendek ke dokumen yang dimiliki oleh penyedia
+dokumen. Contohnya adalah aplikasi pengeditan foto yang memungkinkan pengguna mengedit
+gambar yang tersimpan dalam penyedia dokumen. </li>
+
+</ul>
+
+
+<p>Bagian ini menjelaskan cara menulis aplikasi klien berdasarkan
+{@link android.content.Intent#ACTION_OPEN_DOCUMENT} dan
+intent {@link android.content.Intent#ACTION_CREATE_DOCUMENT}.</p>
+
+
+<h3 id="search">Mencari dokumen</h3>
+
+<p>
+Cuplikan berikut menggunakan {@link android.content.Intent#ACTION_OPEN_DOCUMENT}
+untuk mencari penyedia dokumen yang
+berisi file gambar:</p>
+
+<pre>private static final int READ_REQUEST_CODE = 42;
+...
+/**
+ * Fires an intent to spin up the &quot;file chooser&quot; UI and select an image.
+ */
+public void performFileSearch() {
+
+    // ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's file
+    // browser.
+    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+
+    // Filter to only show results that can be &quot;opened&quot;, such as a
+    // file (as opposed to a list of contacts or timezones)
+    intent.addCategory(Intent.CATEGORY_OPENABLE);
+
+    // Filter to show only images, using the image MIME data type.
+    // If one wanted to search for ogg vorbis files, the type would be &quot;audio/ogg&quot;.
+    // To search for all documents available via installed storage providers,
+    // it would be &quot;*/*&quot;.
+    intent.setType(&quot;image/*&quot;);
+
+    startActivityForResult(intent, READ_REQUEST_CODE);
+}</pre>
+
+<p>Perhatikan yang berikut ini:</p>
+<ul>
+<li>Saat aplikasi mengeluarkan intent {@link android.content.Intent#ACTION_OPEN_DOCUMENT}
+, aplikasi akan menjalankan picker yang menampilkan semua penyedia dokumen yang cocok.</li>
+
+<li>Menambahkan kategori {@link android.content.Intent#CATEGORY_OPENABLE} ke
+intent akan menyaring hasil agar hanya menampilkan dokumen yang bisa dibuka, seperti file gambar.</li>
+
+<li>Pernyataan {@code intent.setType("image/*")} menyaring lebih jauh agar hanya
+menampilkan dokumen yang memiliki tipe data MIME gambar.</li>
+</ul>
+
+<h3 id="results">Memproses Hasil</h3>
+
+<p>Setelah pengguna memilih dokumen di picker,
+{@link android.app.Activity#onActivityResult onActivityResult()} akan dipanggil.
+URI yang menunjuk ke dokumen yang dipilih dimasukkan dalam parameter {@code resultData}
+. Ekstrak URI dengan {@link android.content.Intent#getData getData()}.
+Setelah mendapatkannya, Anda bisa menggunakannya untuk mengambil dokumen yang diinginkan pengguna. Misalnya
+:</p>
+
+<pre>&#64;Override
+public void onActivityResult(int requestCode, int resultCode,
+        Intent resultData) {
+
+    // The ACTION_OPEN_DOCUMENT intent was sent with the request code
+    // READ_REQUEST_CODE. If the request code seen here doesn't match, it's the
+    // response to some other intent, and the code below shouldn't run at all.
+
+    if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
+        // The document selected by the user won't be returned in the intent.
+        // Instead, a URI to that document will be contained in the return intent
+        // provided to this method as a parameter.
+        // Pull that URI using resultData.getData().
+        Uri uri = null;
+        if (resultData != null) {
+            uri = resultData.getData();
+            Log.i(TAG, "Uri: " + uri.toString());
+            showImage(uri);
+        }
+    }
+}
+</pre>
+
+<h3 id="metadata">Memeriksa metadata dokumen</h3>
+
+<p>Setelah Anda memiliki URI untuk dokumen, Anda akan mendapatkan akses ke metadatanya. Cuplikan
+ini memegang metadata sebuah dokumen yang disebutkan oleh URI, dan mencatatnya:</p>
+
+<pre>public void dumpImageMetaData(Uri uri) {
+
+    // The query, since it only applies to a single document, will only return
+    // one row. There's no need to filter, sort, or select fields, since we want
+    // all fields for one document.
+    Cursor cursor = getActivity().getContentResolver()
+            .query(uri, null, null, null, null, null);
+
+    try {
+    // moveToFirst() returns false if the cursor has 0 rows.  Very handy for
+    // &quot;if there's anything to look at, look at it&quot; conditionals.
+        if (cursor != null &amp;&amp; cursor.moveToFirst()) {
+
+            // Note it's called &quot;Display Name&quot;.  This is
+            // provider-specific, and might not necessarily be the file name.
+            String displayName = cursor.getString(
+                    cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
+            Log.i(TAG, &quot;Display Name: &quot; + displayName);
+
+            int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
+            // If the size is unknown, the value stored is null.  But since an
+            // int can't be null in Java, the behavior is implementation-specific,
+            // which is just a fancy term for &quot;unpredictable&quot;.  So as
+            // a rule, check if it's null before assigning to an int.  This will
+            // happen often:  The storage API allows for remote files, whose
+            // size might not be locally known.
+            String size = null;
+            if (!cursor.isNull(sizeIndex)) {
+                // Technically the column stores an int, but cursor.getString()
+                // will do the conversion automatically.
+                size = cursor.getString(sizeIndex);
+            } else {
+                size = &quot;Unknown&quot;;
+            }
+            Log.i(TAG, &quot;Size: &quot; + size);
+        }
+    } finally {
+        cursor.close();
+    }
+}
+</pre>
+
+<h3 id="open-client">Membuka dokumen</h3>
+
+<p>Setelah mendapatkan URI dokumen, Anda bisa membuka dokumen atau melakukan apa saja
+yang diinginkan padanya.</p>
+
+<h4>Bitmap</h4>
+
+<p>Berikut ini adalah contoh cara membuka {@link android.graphics.Bitmap}:</p>
+
+<pre>private Bitmap getBitmapFromUri(Uri uri) throws IOException {
+    ParcelFileDescriptor parcelFileDescriptor =
+            getContentResolver().openFileDescriptor(uri, "r");
+    FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
+    Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
+    parcelFileDescriptor.close();
+    return image;
+}
+</pre>
+
+<p>Perhatikan bahwa Anda tidak boleh melakukan operasi ini pada thread UI. Lakukan hal ini di latar belakang
+, dengan menggunakan {@link android.os.AsyncTask}. Setelah membuka bitmap, Anda
+bisa menampilkannya dalam {@link android.widget.ImageView}.
+</p>
+
+<h4>Mendapatkan InputStream</h4>
+
+<p>Berikut ini adalah contoh cara mendapatkan {@link java.io.InputStream} dari URI. Dalam cuplikan ini
+, baris-baris file dibaca ke dalam sebuah string:</p>
+
+<pre>private String readTextFromUri(Uri uri) throws IOException {
+    InputStream inputStream = getContentResolver().openInputStream(uri);
+    BufferedReader reader = new BufferedReader(new InputStreamReader(
+            inputStream));
+    StringBuilder stringBuilder = new StringBuilder();
+    String line;
+    while ((line = reader.readLine()) != null) {
+        stringBuilder.append(line);
+    }
+    fileInputStream.close();
+    parcelFileDescriptor.close();
+    return stringBuilder.toString();
+}
+</pre>
+
+<h3 id="create">Membuat dokumen baru</h3>
+
+<p>Aplikasi Anda bisa membuat dokumen baru dalam penyedia dokumen dengan menggunakan intent
+{@link android.content.Intent#ACTION_CREATE_DOCUMENT}
+. Untuk membuat file, Anda memberikan satu tipe MIME dan satu nama file pada intent, dan
+menjalankannya dengan kode permintaan yang unik. Selebihnya akan diurus untuk Anda:</p>
+
+
+<pre>
+// Here are some examples of how you might call this method.
+// The first parameter is the MIME type, and the second parameter is the name
+// of the file you are creating:
+//
+// createFile("text/plain", "foobar.txt");
+// createFile("image/png", "mypicture.png");
+
+// Unique request code.
+private static final int WRITE_REQUEST_CODE = 43;
+...
+private void createFile(String mimeType, String fileName) {
+    Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+
+    // Filter to only show results that can be &quot;opened&quot;, such as
+    // a file (as opposed to a list of contacts or timezones).
+    intent.addCategory(Intent.CATEGORY_OPENABLE);
+
+    // Create a file with the requested MIME type.
+    intent.setType(mimeType);
+    intent.putExtra(Intent.EXTRA_TITLE, fileName);
+    startActivityForResult(intent, WRITE_REQUEST_CODE);
+}
+</pre>
+
+<p>Setelah membuat dokumen baru, Anda bisa mendapatkan URI-nya dalam
+{@link android.app.Activity#onActivityResult onActivityResult()}, sehingga Anda
+bisa terus menulis ke dokumen itu.</p>
+
+<h3 id="delete">Menghapus dokumen</h3>
+
+<p>Jika Anda memiliki URI dokumen dan
+{@link android.provider.DocumentsContract.Document#COLUMN_FLAGS Document.COLUMN_FLAGS}
+ dokumen berisi
+{@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_DELETE SUPPORTS_DELETE},
+Anda bisa menghapus dokumen tersebut. Misalnya:</p>
+
+<pre>
+DocumentsContract.deleteDocument(getContentResolver(), uri);
+</pre>
+
+<h3 id="edit">Mengedit dokumen</h3>
+
+<p>Anda bisa menggunakan SAF untuk mengedit dokumen teks langsung di tempatnya.
+Cuplikan ini memicu
+intent {@link android.content.Intent#ACTION_OPEN_DOCUMENT} dan menggunakan
+kategori {@link android.content.Intent#CATEGORY_OPENABLE} untuk menampilkan
+dokumen yang bisa dibuka saja. Ini akan menyaring lebih jauh untuk menampilkan file teks saja:</p>
+
+<pre>
+private static final int EDIT_REQUEST_CODE = 44;
+/**
+ * Open a file for writing and append some text to it.
+ */
+ private void editDocument() {
+    // ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's
+    // file browser.
+    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+
+    // Filter to only show results that can be &quot;opened&quot;, such as a
+    // file (as opposed to a list of contacts or timezones).
+    intent.addCategory(Intent.CATEGORY_OPENABLE);
+
+    // Filter to show only text files.
+    intent.setType(&quot;text/plain&quot;);
+
+    startActivityForResult(intent, EDIT_REQUEST_CODE);
+}
+</pre>
+
+<p>Berikutnya, dari {@link android.app.Activity#onActivityResult onActivityResult()}
+(lihat <a href="#results">Memproses hasil</a>) Anda bisa memanggil kode untuk mengedit.
+Cuplikan berikut mendapatkan {@link java.io.FileOutputStream}
+dari {@link android.content.ContentResolver}. Secara default, snipet menggunakan mode “tulis”.
+Inilah praktik terbaik untuk meminta jumlah akses minimum yang Anda perlukan, jadi jangan meminta
+baca/tulis jika yang Anda perlukan hanyalah tulis:</p>
+
+<pre>private void alterDocument(Uri uri) {
+    try {
+        ParcelFileDescriptor pfd = getActivity().getContentResolver().
+                openFileDescriptor(uri, "w");
+        FileOutputStream fileOutputStream =
+                new FileOutputStream(pfd.getFileDescriptor());
+        fileOutputStream.write(("Overwritten by MyCloud at " +
+                System.currentTimeMillis() + "\n").getBytes());
+        // Let the document provider know you're done by closing the stream.
+        fileOutputStream.close();
+        pfd.close();
+    } catch (FileNotFoundException e) {
+        e.printStackTrace();
+    } catch (IOException e) {
+        e.printStackTrace();
+    }
+}</pre>
+
+<h3 id="permissions">Mempertahankan izin</h3>
+
+<p>Bila aplikasi Anda membuka file untuk membaca atau menulis, sistem akan memberi
+aplikasi Anda izin URI untuk file itu. Pemberian ini berlaku hingga perangkat pengguna di-restart.
+Namun anggaplah aplikasi Anda adalah aplikasi pengeditan gambar, dan Anda ingin pengguna bisa
+mengakses 5 gambar terakhir yang dieditnya, langsung dari aplikasi Anda. Jika perangkat pengguna telah
+di-restart, maka Anda harus mengirim pengguna kembali ke picker sistem untuk menemukan
+file, hal ini jelas tidak ideal.</p>
+
+<p>Untuk mencegah terjadinya hal ini, Anda bisa mempertahankan izin yang diberikan
+sistem ke aplikasi Anda. Secara efektif, aplikasi Anda akan "mengambil" pemberian izin URI yang bisa dipertahankan
+yang ditawarkan oleh sistem. Hal ini memberi pengguna akses kontinu ke file
+melalui aplikasi Anda, sekalipun perangkat telah di-restart:</p>
+
+
+<pre>final int takeFlags = intent.getFlags()
+            &amp; (Intent.FLAG_GRANT_READ_URI_PERMISSION
+            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+// Check for the freshest data.
+getContentResolver().takePersistableUriPermission(uri, takeFlags);</pre>
+
+<p>Ada satu langkah akhir. Anda mungkin telah menyimpan
+URI terbaru yang diakses aplikasi, namun URI itu mungkin tidak lagi valid,&mdash;aplikasi lain
+mungkin telah menghapus atau memodifikasi dokumen. Karena itu, Anda harus selalu memanggil
+{@code getContentResolver().takePersistableUriPermission()} untuk memeriksa
+data terbaru.</p>
+
+<h2 id="custom">Menulis Penyedia Dokumen Custom</h2>
+
+<p>
+Jika Anda sedang mengembangkan aplikasi yang menyediakan layanan penyimpanan untuk file (misalnya
+layanan penyimpanan cloud), Anda bisa menyediakan file melalui
+SAF dengan menulis penyedia dokumen custom.  Bagian ini menjelaskan
+caranya.</p>
+
+
+<h3 id="manifest">Manifes</h3>
+
+<p>Untuk mengimplementasikan penyedia dokumen custom, tambahkan yang berikut ini ke manifes aplikasi
+Anda:</p>
+<ul>
+
+<li>Target berupa API level 19 atau yang lebih tinggi.</li>
+
+<li>Elemen <code>&lt;provider&gt;</code> yang mendeklarasikan penyedia penyimpanan custom
+Anda. </li>
+
+<li>Nama penyedia Anda, yaitu nama kelasnya, termasuk nama paket.
+Misalnya: <code>com.example.android.storageprovider.MyCloudProvider</code>.</li>
+
+<li>Nama otoritas Anda, yaitu nama paket Anda (dalam contoh ini,
+<code>com.example.android.storageprovider</code>) plus tipe penyedia konten
+(<code>documents</code>). Misalnya, {@code com.example.android.storageprovider.documents}.</li>
+
+<li>Atribut <code>android:exported</code> yang diatur ke <code>&quot;true&quot;</code>.
+Anda harus mengekspor penyedia sehingga aplikasi lain bisa membacanya.</li>
+
+<li>Atribut <code>android:grantUriPermissions</code> yang diatur ke
+<code>&quot;true&quot;</code>. Pengaturan ini memungkinkan sistem memberi aplikasi lain akses
+ke konten dalam penyedia Anda. Untuk pembahasan cara mempertahankan pemberian bagi
+dokumen tertentu, lihat <a href="#permissions">Mempertahankan izin</a>.</li>
+
+<li>Izin {@code MANAGE_DOCUMENTS}. Secara default, penyedia tersedia
+bagi siapa saja. Menambahkan izin ini akan membatasi penyedia Anda pada sistem.
+Pembatasan ini penting untuk keamanan.</li>
+
+<li>Atribut {@code android:enabled} yang diatur ke nilai boolean didefinisikan dalam file
+sumber daya. Tujuan atribut ini adalah menonaktifkan penyedia pada perangkat yang menjalankan Android 4.3 atau yang lebih rendah.
+Misalnya, {@code android:enabled="@bool/atLeastKitKat"}. Selain
+memasukkan atribut ini dalam manifes, Anda perlu melakukan hal-hal berikut:
+<ul>
+<li>Dalam file sumber daya {@code bool.xml} Anda di bawah {@code res/values/}, tambahkan
+baris ini: <pre>&lt;bool name=&quot;atLeastKitKat&quot;&gt;false&lt;/bool&gt;</pre></li>
+
+<li>Dalam file sumber daya {@code bool.xml} Anda di bawah {@code res/values-v19/}, tambahkan
+baris ini: <pre>&lt;bool name=&quot;atLeastKitKat&quot;&gt;true&lt;/bool&gt;</pre></li>
+</ul></li>
+
+<li>Sebuah filter intent berisi tindakan
+{@code android.content.action.DOCUMENTS_PROVIDER}, agar penyedia Anda
+muncul dalam picker saat sistem mencari penyedia.</li>
+
+</ul>
+<p>Berikut ini adalah kutipan contoh manifes berisi penyedia yang:</p>
+
+<pre>&lt;manifest... &gt;
+    ...
+    &lt;uses-sdk
+        android:minSdkVersion=&quot;19&quot;
+        android:targetSdkVersion=&quot;19&quot; /&gt;
+        ....
+        &lt;provider
+            android:name=&quot;com.example.android.storageprovider.MyCloudProvider&quot;
+            android:authorities=&quot;com.example.android.storageprovider.documents&quot;
+            android:grantUriPermissions=&quot;true&quot;
+            android:exported=&quot;true&quot;
+            android:permission=&quot;android.permission.MANAGE_DOCUMENTS&quot;
+            android:enabled=&quot;&#64;bool/atLeastKitKat&quot;&gt;
+            &lt;intent-filter&gt;
+                &lt;action android:name=&quot;android.content.action.DOCUMENTS_PROVIDER&quot; /&gt;
+            &lt;/intent-filter&gt;
+        &lt;/provider&gt;
+    &lt;/application&gt;
+
+&lt;/manifest&gt;</pre>
+
+<h4 id="43">Mendukung perangkat yang menjalankan Android 4.3 dan yang lebih rendah</h4>
+
+<p>Intent
+{@link android.content.Intent#ACTION_OPEN_DOCUMENT} hanya tersedia
+pada perangkat yang menjalankan Android 4.4 dan yang lebih tinggi.
+Jika ingin aplikasi Anda mendukung {@link android.content.Intent#ACTION_GET_CONTENT}
+untuk mengakomodasi perangkat yang menjalankan Android 4.3 dan yang lebih rendah, Anda harus
+menonaktifkan filter inten {@link android.content.Intent#ACTION_GET_CONTENT} dalam
+manifes untuk perangkat yang menjalankan Android 4.4 atau yang lebih tinggi. Penyedia
+dokumen dan {@link android.content.Intent#ACTION_GET_CONTENT} harus dianggap
+saling eksklusif. Jika Anda mendukung keduanya sekaligus, aplikasi Anda akan
+muncul dua kali dalam UI picker sistem, yang menawarkan dua cara mengakses
+data tersimpan Anda. Hal ini akan membingungkan pengguna.</p>
+
+<p>Berikut ini adalah cara yang disarankan untuk menonaktifkan
+filter intent {@link android.content.Intent#ACTION_GET_CONTENT} untuk perangkat
+yang menjalankan Android versi 4.4 atau yang lebih tinggi:</p>
+
+<ol>
+<li>Dalam file sumber daya {@code bool.xml} Anda di bawah {@code res/values/}, tambahkan
+baris ini: <pre>&lt;bool name=&quot;atMostJellyBeanMR2&quot;&gt;true&lt;/bool&gt;</pre></li>
+
+<li>Dalam file sumber daya {@code bool.xml} Anda di bawah {@code res/values-v19/}, tambahkan
+baris ini: <pre>&lt;bool name=&quot;atMostJellyBeanMR2&quot;&gt;false&lt;/bool&gt;</pre></li>
+
+<li>Tambahkan
+<a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">alias
+aktivitas</a> untuk menonaktifkan filter intent {@link android.content.Intent#ACTION_GET_CONTENT}
+bagi versi 4.4 (API level 19) dan yang lebih tinggi. Misalnya:
+
+<pre>
+&lt;!-- This activity alias is added so that GET_CONTENT intent-filter
+     can be disabled for builds on API level 19 and higher. --&gt;
+&lt;activity-alias android:name=&quot;com.android.example.app.MyPicker&quot;
+        android:targetActivity=&quot;com.android.example.app.MyActivity&quot;
+        ...
+        android:enabled=&quot;@bool/atMostJellyBeanMR2&quot;&gt;
+    &lt;intent-filter&gt;
+        &lt;action android:name=&quot;android.intent.action.GET_CONTENT&quot; /&gt;
+        &lt;category android:name=&quot;android.intent.category.OPENABLE&quot; /&gt;
+        &lt;category android:name=&quot;android.intent.category.DEFAULT&quot; /&gt;
+        &lt;data android:mimeType=&quot;image/*&quot; /&gt;
+        &lt;data android:mimeType=&quot;video/*&quot; /&gt;
+    &lt;/intent-filter&gt;
+&lt;/activity-alias&gt;
+</pre>
+</li>
+</ol>
+<h3 id="contract">Kontrak</h3>
+
+<p>Biasanya bila Anda menulis penyedia konten custom, salah satu tugas adalah
+mengimplementasikan kelas kontrak, seperti dijelaskan dalam panduan pengembang
+<a href="{@docRoot}guide/topics/providers/content-provider-creating.html#ContractClass">
+Penyedia Konten</a>. Kelas kontrak adalah kelas {@code public final}
+yang berisi definisi konstanta untuk URI, nama kolom, tipe MIME, dan
+metadata lain yang berkenaan dengan penyedia. SAF
+menyediakan kelas-kelas kontrak ini untuk Anda, jadi Anda tidak perlu menulisnya
+sendiri:</p>
+
+<ul>
+   <li>{@link android.provider.DocumentsContract.Document}</li>
+   <li>{@link android.provider.DocumentsContract.Root}</li>
+</ul>
+
+<p>Misalnya, berikut ini adalah kolom-kolom yang bisa Anda hasilkan di kursor bila
+penyedia dokumen Anda membuat query dokumen atau akar:</p>
+
+<pre>private static final String[] DEFAULT_ROOT_PROJECTION =
+        new String[]{Root.COLUMN_ROOT_ID, Root.COLUMN_MIME_TYPES,
+        Root.COLUMN_FLAGS, Root.COLUMN_ICON, Root.COLUMN_TITLE,
+        Root.COLUMN_SUMMARY, Root.COLUMN_DOCUMENT_ID,
+        Root.COLUMN_AVAILABLE_BYTES,};
+private static final String[] DEFAULT_DOCUMENT_PROJECTION = new
+        String[]{Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE,
+        Document.COLUMN_DISPLAY_NAME, Document.COLUMN_LAST_MODIFIED,
+        Document.COLUMN_FLAGS, Document.COLUMN_SIZE,};
+</pre>
+
+<h3 id="subclass">Subkelas DocumentsProvider</h3>
+
+<p>Langkah berikutnya dalam menulis penyedia dokumen custom adalah menjadikan
+kelas abstrak sebagai subkelas {@link android.provider.DocumentsProvider}. Setidaknya, Anda perlu
+ mengimplementasikan metode berikut:</p>
+
+<ul>
+<li>{@link android.provider.DocumentsProvider#queryRoots queryRoots()}</li>
+
+<li>{@link android.provider.DocumentsProvider#queryChildDocuments queryChildDocuments()}</li>
+
+<li>{@link android.provider.DocumentsProvider#queryDocument queryDocument()}</li>
+
+<li>{@link android.provider.DocumentsProvider#openDocument openDocument()}</li>
+</ul>
+
+<p>Hanya inilah metode yang diwajibkan kepada Anda secara ketat untuk diimplementasikan, namun ada
+banyak lagi yang mungkin Anda inginkan. Lihat {@link android.provider.DocumentsProvider}
+untuk detailnya.</p>
+
+<h4 id="queryRoots">Mengimplementasikan queryRoots</h4>
+
+<p>Implementasi {@link android.provider.DocumentsProvider#queryRoots
+queryRoots()} oleh Anda harus menghasilkan {@link android.database.Cursor} yang menunjuk ke semua
+direktori akar penyedia dokumen, dengan menggunakan kolom-kolom yang didefinisikan dalam
+{@link android.provider.DocumentsContract.Root}.</p>
+
+<p>Dalam cuplikan berikut, parameter {@code projection} mewakili bidang-bidang
+tertentu yang ingin didapatkan kembali oleh pemanggil. Cuplikan ini membuat kursor baru
+dan menambahkan satu baris ke satu akar&mdash; kursor, satu direktori level atas, seperti
+Downloads atau Images.  Kebanyakan penyedia hanya mempunyai satu akar. Anda bisa mempunyai lebih dari satu,
+misalnya, jika ada banyak akun pengguna. Dalam hal itu, cukup tambahkan sebuah
+baris kedua ke kursor.</p>
+
+<pre>
+&#64;Override
+public Cursor queryRoots(String[] projection) throws FileNotFoundException {
+
+    // Create a cursor with either the requested fields, or the default
+    // projection if "projection" is null.
+    final MatrixCursor result =
+            new MatrixCursor(resolveRootProjection(projection));
+
+    // If user is not logged in, return an empty root cursor.  This removes our
+    // provider from the list entirely.
+    if (!isUserLoggedIn()) {
+        return result;
+    }
+
+    // It's possible to have multiple roots (e.g. for multiple accounts in the
+    // same app) -- just add multiple cursor rows.
+    // Construct one row for a root called &quot;MyCloud&quot;.
+    final MatrixCursor.RowBuilder row = result.newRow();
+    row.add(Root.COLUMN_ROOT_ID, ROOT);
+    row.add(Root.COLUMN_SUMMARY, getContext().getString(R.string.root_summary));
+
+    // FLAG_SUPPORTS_CREATE means at least one directory under the root supports
+    // creating documents. FLAG_SUPPORTS_RECENTS means your application's most
+    // recently used documents will show up in the &quot;Recents&quot; category.
+    // FLAG_SUPPORTS_SEARCH allows users to search all documents the application
+    // shares.
+    row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE |
+            Root.FLAG_SUPPORTS_RECENTS |
+            Root.FLAG_SUPPORTS_SEARCH);
+
+    // COLUMN_TITLE is the root title (e.g. Gallery, Drive).
+    row.add(Root.COLUMN_TITLE, getContext().getString(R.string.title));
+
+    // This document id cannot change once it's shared.
+    row.add(Root.COLUMN_DOCUMENT_ID, getDocIdForFile(mBaseDir));
+
+    // The child MIME types are used to filter the roots and only present to the
+    //  user roots that contain the desired type somewhere in their file hierarchy.
+    row.add(Root.COLUMN_MIME_TYPES, getChildMimeTypes(mBaseDir));
+    row.add(Root.COLUMN_AVAILABLE_BYTES, mBaseDir.getFreeSpace());
+    row.add(Root.COLUMN_ICON, R.drawable.ic_launcher);
+
+    return result;
+}</pre>
+
+<h4 id="queryChildDocuments">Mengimplementasikan queryChildDocuments</h4>
+
+<p>Implementasi
+{@link android.provider.DocumentsProvider#queryChildDocuments queryChildDocuments()}
+oleh Anda harus menghasilkan {@link android.database.Cursor} yang menunjuk ke semua file dalam
+direktori yang ditentukan, dengan menggunakan kolom-kolom yang didefinisikan dalam
+{@link android.provider.DocumentsContract.Document}.</p>
+
+<p>Metode ini akan dipanggil bila Anda memilih akar aplikasi dalam picker UI.
+Metode mengambil dokumen anak dari direktori di bawah akar.  Metode ini bisa dipanggil pada level apa saja dalam
+hierarki file, bukan hanya akar. Cuplikan ini
+membuat kursor baru dengan kolom-kolom yang diminta, lalu menambahkan informasi tentang
+setiap anak langsung dalam direktori induk ke kursor.
+Satu anak bisa berupa gambar, direktori lain&mdash;file apa saja:</p>
+
+<pre>&#64;Override
+public Cursor queryChildDocuments(String parentDocumentId, String[] projection,
+                              String sortOrder) throws FileNotFoundException {
+
+    final MatrixCursor result = new
+            MatrixCursor(resolveDocumentProjection(projection));
+    final File parent = getFileForDocId(parentDocumentId);
+    for (File file : parent.listFiles()) {
+        // Adds the file's display name, MIME type, size, and so on.
+        includeFile(result, null, file);
+    }
+    return result;
+}
+</pre>
+
+<h4 id="queryDocument">Mengimplementasikan queryDocument</h4>
+
+<p>Implementasi
+{@link android.provider.DocumentsProvider#queryDocument queryDocument()}
+oleh Anda harus menghasilkan {@link android.database.Cursor} yang menunjuk ke file yang disebutkan,
+dengan menggunakan kolom-kolom yang didefinisikan dalam {@link android.provider.DocumentsContract.Document}.
+</p>
+
+<p>Metode {@link android.provider.DocumentsProvider#queryDocument queryDocument()}
+menghasilkan informasi yang sama yang diteruskan dalam
+{@link android.provider.DocumentsProvider#queryChildDocuments queryChildDocuments()},
+namun untuk file tertentu:</p>
+
+
+<pre>&#64;Override
+public Cursor queryDocument(String documentId, String[] projection) throws
+        FileNotFoundException {
+
+    // Create a cursor with the requested projection, or the default projection.
+    final MatrixCursor result = new
+            MatrixCursor(resolveDocumentProjection(projection));
+    includeFile(result, documentId, null);
+    return result;
+}
+</pre>
+
+<h4 id="openDocument">Mengimplementasikan openDocument</h4>
+
+<p>Anda harus mengimplementasikan {@link android.provider.DocumentsProvider#openDocument
+openDocument()} untuk menghasilkan {@link android.os.ParcelFileDescriptor} yang mewakili
+file yang disebutkan. Aplikasi lain bisa menggunakan {@link android.os.ParcelFileDescriptor}
+yang dihasilkan untuk mengalirkan data. Sistem memanggil metode ini setelah pengguna memilih file
+dan aplikasi klien meminta akses ke file itu dengan memanggil
+{@link android.content.ContentResolver#openFileDescriptor openFileDescriptor()}.
+Misalnya:</p>
+
+<pre>&#64;Override
+public ParcelFileDescriptor openDocument(final String documentId,
+                                         final String mode,
+                                         CancellationSignal signal) throws
+        FileNotFoundException {
+    Log.v(TAG, &quot;openDocument, mode: &quot; + mode);
+    // It's OK to do network operations in this method to download the document,
+    // as long as you periodically check the CancellationSignal. If you have an
+    // extremely large file to transfer from the network, a better solution may
+    // be pipes or sockets (see ParcelFileDescriptor for helper methods).
+
+    final File file = getFileForDocId(documentId);
+
+    final boolean isWrite = (mode.indexOf('w') != -1);
+    if(isWrite) {
+        // Attach a close listener if the document is opened in write mode.
+        try {
+            Handler handler = new Handler(getContext().getMainLooper());
+            return ParcelFileDescriptor.open(file, accessMode, handler,
+                        new ParcelFileDescriptor.OnCloseListener() {
+                &#64;Override
+                public void onClose(IOException e) {
+
+                    // Update the file with the cloud server. The client is done
+                    // writing.
+                    Log.i(TAG, &quot;A file with id &quot; +
+                    documentId + &quot; has been closed!
+                    Time to &quot; +
+                    &quot;update the server.&quot;);
+                }
+
+            });
+        } catch (IOException e) {
+            throw new FileNotFoundException(&quot;Failed to open document with id &quot;
+            + documentId + &quot; and mode &quot; + mode);
+        }
+    } else {
+        return ParcelFileDescriptor.open(file, accessMode);
+    }
+}
+</pre>
+
+<h3 id="security">Keamanan</h3>
+
+<p>Anggaplah penyedia dokumen Anda sebuah layanan penyimpanan cloud yang dilindungi kata sandi
+dan Anda ingin memastikan bahwa pengguna sudah login sebelum Anda mulai berbagi file mereka.
+Apakah yang harus dilakukan aplikasi Anda jika pengguna tidak login?  Solusinya adalah menghasilkan
+akar nol dalam implementasi {@link android.provider.DocumentsProvider#queryRoots
+queryRoots()} Anda. Yakni, sebuah kursor akar kosong:</p>
+
+<pre>
+public Cursor queryRoots(String[] projection) throws FileNotFoundException {
+...
+    // If user is not logged in, return an empty root cursor.  This removes our
+    // provider from the list entirely.
+    if (!isUserLoggedIn()) {
+        return result;
+}
+</pre>
+
+<p>Langkah lainnya adalah memanggil {@code getContentResolver().notifyChange()}.
+Ingat {@link android.provider.DocumentsContract}?  Kita menggunakannya untuk membuat
+URI ini. Cuplikan berikut memberi tahu sistem untuk membuat query akar penyedia dokumen Anda
+kapan saja status login pengguna berubah. Jika pengguna tidak
+login, panggilan ke {@link android.provider.DocumentsProvider#queryRoots queryRoots()} akan menghasilkan
+kursor kosong, seperti yang ditampilkan di atas. Cara ini akan memastikan bahwa dokumen penyedia hanya
+tersedia jika pengguna login ke penyedia itu.</p>
+
+<pre>private void onLoginButtonClick() {
+    loginOrLogout();
+    getContentResolver().notifyChange(DocumentsContract
+            .buildRootsUri(AUTHORITY), null);
+}
+</pre>
\ No newline at end of file
diff --git a/docs/html-intl/intl/id/guide/topics/resources/accessing-resources.jd b/docs/html-intl/intl/id/guide/topics/resources/accessing-resources.jd
new file mode 100644
index 0000000..6774557
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/resources/accessing-resources.jd
@@ -0,0 +1,337 @@
+page.title=Mengakses Sumber Daya
+parent.title=Sumber Daya Aplikasi
+parent.link=index.html
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>Tampilan Cepat</h2>
+  <ul>
+    <li>Sumber daya bisa diacu dari kode dengan menggunakan integer dari {@code R.java}, seperti
+{@code R.drawable.myimage}</li>
+    <li>Sumber daya bisa diacu dari sumber daya dengan menggunakan sintaks XML khusus, seperti {@code
+&#64;drawable/myimage}</li>
+    <li>Anda juga bisa mengakses sumber daya aplikasi Anda dengan berbagai metode di
+{@link android.content.res.Resources}</li>
+  </ul>
+
+  <h2>Kelas-Kelas Utama</h2>
+  <ol>
+    <li>{@link android.content.res.Resources}</li>
+  </ol>
+
+  <h2>Dalam dokumen ini</h2>
+  <ol>
+    <li><a href="#ResourcesFromCode">Mengakses Sumber Daya dari Kode</a></li>
+    <li><a href="#ResourcesFromXml">Mengakses Sumber Daya dari XML</a>
+      <ol>
+        <li><a href="#ReferencesToThemeAttributes">Mengacu atribut gaya</a></li>
+      </ol>
+    </li>
+    <li><a href="#PlatformResources">Mengakses Sumber Daya Platform</a></li>
+  </ol>
+
+  <h2>Lihat juga</h2>
+  <ol>
+    <li><a href="providing-resources.html">Menyediakan Sumber Daya</a></li>
+    <li><a href="available-resources.html">Tipe Sumber Daya</a></li>
+  </ol>
+</div>
+</div>
+
+
+
+
+<p>Setelah Anda menyediakan sumber daya dalam aplikasi Anda (yang dibicarakan di <a href="providing-resources.html">Menyediakan Sumber Daya</a>), Anda bisa menerapkannya dengan
+mengacu ID sumber dayanya. Semua ID sumber daya didefinisikan di kelas {@code R} proyek Anda, yang
+dihasilkan oleh alat {@code aapt} secara otomatis.</p>
+
+<p>Bila aplikasi Anda dikompilasi, {@code aapt} akan membuat kelas {@code R}, yang berisi
+ID sumber daya untuk semua sumber daya dalam direktori {@code
+res/} Anda. Untuk masing-masing tipe sumber daya, ada subkelas {@code R} (misalnya,
+{@code R.drawable} untuk semua sumber daya yang bisa ditarik), dan untuk masing-masing sumber daya dari tipe itu, ada satu integer statis
+ (misalnya, {@code R.drawable.icon}). Integer ini adalah ID sumber daya yang bisa Anda gunakan
+untuk mengambil sumber daya Anda.</p>
+
+<p>Walaupun kelas {@code R} adalah tempat menyebutkan ID sumber daya, Anda tidak perlu
+melihat ke sana untuk menemukan ID sumber daya. ID sumber daya selalu terdiri dari:</p>
+<ul>
+  <li><em>Tipe sumber daya</em>: Masing-masing sumber daya dikelompokkan menjadi "tipe", misalnya {@code
+string}, {@code drawable}, dan {@code layout}. Untuk mengetahui selengkapnya tentang berbagai tipe, lihat <a href="available-resources.html">Tipe Sumber Daya</a>.
+  </li>
+  <li><em>Nama sumber daya</em>, bisa berupa: nama file,
+tidak termasuk ekstensi; atau nilai dalam atribut {@code android:name} XML, jika
+sumber daya itu sebuah nilai sederhana (misalnya sebuah string).</li>
+</ul>
+
+<p>Ada dua cara untuk mengakses sumber daya:</p>
+<ul>
+  <li><strong>Dalam kode:</strong> Menggunakan integer statis dari subkelas dari kelas {@code R}
+, misalnya:
+    <pre class="classic no-pretty-print">R.string.hello</pre>
+    <p>{@code string} adalah tipe sumber daya dan {@code hello} adalah nama sumber daya. Ada banyak
+API Android yang bisa mengakses sumber daya Anda bila Anda menyediakan ID sumber daya dengan format ini. Lihat
+<a href="#ResourcesFromCode">Mengakses Sumber Daya dalam Kode</a>.</p>
+  </li>
+  <li><strong>Dalam XML:</strong> Menggunakan sebuah sintaks XML khusus yang juga berkaitan dengan
+ID sumber daya yang didefinisikan dalam kelas {@code R}, misalnya:
+    <pre class="classic no-pretty-print">&#64;string/hello</pre>
+    <p>{@code string} adalah tipe sumber daya dan {@code hello} adalah nama sumber daya. Anda bisa menggunakan
+sintaks ini dalam sumber daya XML di mana saja Anda ingin menyediakan sebuah nilai dalam sebuah sumber daya. Lihat <a href="#ResourcesFromXml">Mengakses Sumber Daya dari XML</a>.</p>
+  </li>
+</ul>
+
+
+
+<h2 id="ResourcesFromCode">Mengakses Sumber Daya dalam Kode </h2>
+
+<p>Anda bisa menggunakan sumber daya dalam kode dengan menyalurkan ID sumber daya sebagai sebuah parameter metode. Misalnya,
+ Anda bisa mengatur sebuah {@link android.widget.ImageView} agar menggunakan sumber daya{@code res/drawable/myimage.png}
+dengan menggunakan {@link android.widget.ImageView#setImageResource(int) setImageResource()}:</p>
+<pre>
+ImageView imageView = (ImageView) findViewById(R.id.myimageview);
+imageView.setImageResource(<strong>R.drawable.myimage</strong>);
+</pre>
+
+<p>Anda juga bisa mengambil tiap sumber daya dengan menggunakan berbagai metode di {@link
+android.content.res.Resources}, di mana Anda bisa mendapatkan instance
+ {@link android.content.Context#getResources()}.</p>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<h2>Akses ke File Asli</h2>
+
+<p>Walaupun tidak lazim, Anda mungkin perlu mengakses file dan direktori asli Anda. Jika demikian, maka
+menyimpan file Anda di {@code res/} tidak akan berhasil, karena satu-satunya cara untuk membaca sebuah sumber daya dari
+{@code res/} adalah dengan ID sumber daya. Sebagai gantinya, Anda bisa menyimpan sumber daya dalam direktori
+{@code assets/}.</p>
+<p>File yang tersimpan di direktori {@code assets/} <em>tidak</em> diberi ID
+sumber daya, sehingga Anda tidak bisa mengacunya melalui kelas {@code R} atau dari sumber daya XML. Sebagai gantinya, Anda bisa melakukan
+query file di direktori {@code assets/} seperti sebuah sistem file biasa dan membaca data mentah dengan menggunakan
+{@link android.content.res.AssetManager}.</p>
+<p>Akan tetapi, jika yang Anda butuhkan hanya kemampuan membaca data mentah (misalnya sebuah file video atau audio),
+maka simpanlah file itu di direktori {@code res/raw/} dan baca aliran byte dengan menggunakan {@link
+android.content.res.Resources#openRawResource(int) openRawResource()}.</p>
+
+</div>
+</div>
+
+
+<h3>Sintaks</h3>
+
+<p>Inilah sintaks untuk mengacu sumber daya dalam kode:</p>
+
+<pre class="classic no-pretty-print">
+[<em>&lt;package_name&gt;</em>.]R.<em>&lt;resource_type&gt;</em>.<em>&lt;resource_name&gt;</em>
+</pre>
+
+<ul>
+  <li><em> {@code &lt;package_name&gt;}</em>adalah nama paket yang di dalamnya terdapat sumber daya (tidak
+dibutuhkan bila mengacu sumber daya dari paket Anda sendiri).</li>
+  <li><em>{@code &lt;resource_type&gt;}</em> adalah subkelas {@code R} untuk tipe sumber daya.</li>
+  <li><em>{@code &lt;resource_name&gt;}</em> bisa berupa nama file sumber daya
+tanpa ekstensi atau nilai atribut {@code android:name} dalam elemen XML (untuk nilai
+sederhana).</li>
+</ul>
+<p>Lihat <a href="available-resources.html">Tipe Sumber Daya</a> untuk
+informasi selengkapnya tentang masing-masing tipe sumber daya dan cara mengacunya.</p>
+
+
+<h3>Kasus penggunaan</h3>
+
+<p>Ada banyak metode yang menerima parameter ID sumber daya dan Anda bisa mengambil sumber daya dengan menggunakan
+metode di {@link android.content.res.Resources}. Anda bisa mengambil instance {@link
+android.content.res.Resources} dengan {@link android.content.Context#getResources
+Context.getResources()}.</p>
+
+
+<p>Berikut adalah beberapa contoh cara mengakses sumber daya dalam kode:</p>
+
+<pre>
+// Load a background for the current screen from a drawable resource
+{@link android.app.Activity#getWindow()}.{@link
+android.view.Window#setBackgroundDrawableResource(int)
+setBackgroundDrawableResource}(<strong>R.drawable.my_background_image</strong>) ;
+
+// Set the Activity title by getting a string from the Resources object, because
+//  this method requires a CharSequence rather than a resource ID
+{@link android.app.Activity#getWindow()}.{@link android.view.Window#setTitle(CharSequence)
+setTitle}(getResources().{@link android.content.res.Resources#getText(int)
+getText}(<strong>R.string.main_title</strong>));
+
+// Load a custom layout for the current screen
+{@link android.app.Activity#setContentView(int)
+setContentView}(<strong>R.layout.main_screen</strong>);
+
+// Set a slide in animation by getting an Animation from the Resources object
+mFlipper.{@link android.widget.ViewAnimator#setInAnimation(Animation)
+setInAnimation}(AnimationUtils.loadAnimation(this,
+        <strong>R.anim.hyperspace_in</strong>));
+
+// Set the text on a TextView object using a resource ID
+TextView msgTextView = (TextView) findViewById(<strong>R.id.msg</strong>);
+msgTextView.{@link android.widget.TextView#setText(int)
+setText}(<strong>R.string.hello_message</strong>);
+</pre>
+
+
+<p class="caution"><strong>Perhatian:</strong> Anda tidak boleh memodifikasi file {@code
+R.java} secara manual&mdash;, ini dihasilkan oleh alat {@code aapt} bila proyek Anda telah
+dikompilasi. Perubahan apa pun akan ditimpa bila nanti Anda mengompilasi.</p>
+
+
+
+<h2 id="ResourcesFromXml">Mengakses Sumber Daya dari XML</h2>
+
+<p>Anda bisa mendefinisikan nilai untuk beberapa atribut dan elemen XML dengan menggunakan
+acuan ke sumber daya yang ada. Anda akan sering melakukannya saat membuat file layout, untuk
+memasok string dan gambar bagi widget Anda.</p>
+
+<p>Misalnya, jika Anda menambahkan sebuah {@link android.widget.Button} ke layout, Anda harus menggunakan
+sebuah <a href="string-resource.html">sumber daya string</a> bagi teks tombolnya:</p>
+
+<pre>
+&lt;Button
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:text="<strong>@string/submit</strong>" /&gt;
+</pre>
+
+
+<h3>Sintaks</h3>
+
+<p>Berikut adalah sintaks untuk mengacu sumber daya di sumber daya XML:</p>
+
+<pre class="classic no-pretty-print">
+&#64;[<em>&lt;package_name&gt;</em>:]<em>&lt;resource_type&gt;</em>/<em>&lt;resource_name&gt;</em>
+</pre>
+
+<ul>
+  <li>{@code &lt;package_name&gt;} adalah nama paket yang di dalamnya terdapat sumber daya (tidak
+dibutuhkan bila mengacu sumber daya dari paket yang sama)</li>
+  <li>{@code &lt;resource_type&gt;} adalah subkelas
+{@code R} untuk tipe sumber daya</li>
+  <li>{@code &lt;resource_name&gt;} bisa berupa nama file sumber daya
+tanpa ekstensi atau nilai atribut {@code android:name} dalam elemen XML (untuk nilai
+sederhana).</li>
+</ul>
+
+<p>Lihat <a href="available-resources.html">Tipe Sumber Daya</a> untuk
+informasi selengkapnya tentang masing-masing tipe sumber daya dan cara mengacunya.</p>
+
+
+<h3>Kasus penggunaan</h3>
+
+<p>Dalam beberapa kasus, Anda harus menggunakan sumber daya untuk suatu nilai dalam XML (misalnya, untuk menerapkan gambar yang bisa ditarik
+pada widget), namun Anda juga bisa menggunakan sumber daya di XML mana saja yang menerima nilai sederhana. Misalnya, jika
+Anda mempunyai file sumber daya berikut yang berisi <a href="more-resources.html#Color">sumber daya warna</a> dan <a href="string-resource.html">sumber daya string</a>:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;resources>
+   &lt;color name="opaque_red">#f00&lt;/color>
+   &lt;string name="hello">Hello!&lt;/string>
+&lt;/resources>
+</pre>
+
+<p>Anda bisa menggunakan sumber daya ini dalam file layout berikut untuk mengatur warna teks dan
+string teks:</p>
+
+<pre>
+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
+&lt;EditText xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
+    android:layout_width=&quot;fill_parent&quot;
+    android:layout_height=&quot;fill_parent&quot;
+    android:textColor=&quot;<strong>&#64;color/opaque_red</strong>&quot;
+    android:text=&quot;<strong>&#64;string/hello</strong>&quot; /&gt;
+</pre>
+
+<p>Dalam hal ini, Anda tidak perlu menyebutkan nama paket dalam sumber daya acuan karena
+sumber daya berasal dari paket Anda sendiri. Untuk
+mengacu sumber daya sistem, Anda perlu memasukkan nama paketnya. Misalnya:</p>
+
+<pre>
+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
+&lt;EditText xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
+    android:layout_width=&quot;fill_parent&quot;
+    android:layout_height=&quot;fill_parent&quot;
+    android:textColor=&quot;<strong>&#64;android:color/secondary_text_dark</strong>&quot;
+    android:text=&quot;&#64;string/hello&quot; /&gt;
+</pre>
+
+<p class="note"><strong>Catatan:</strong> Anda harus menggunakan sumber daya string sepanjang
+waktu, sehingga aplikasi Anda bisa dilokalkan untuk bahasa lain.
+Untuk informasi tentang cara menciptakan
+sumber daya alternatif (seperti string lokal), lihat <a href="providing-resources.html#AlternativeResources">Menyediakan Sumber Daya Alternatif
+</a>. Untuk panduan lengkap melokalkan aplikasi Anda ke bahasa lain,
+lihat <a href="localization.html">Pelokalan</a>.</p>
+
+<p>Anda bahkan bisa menggunakan sumber daya dalam XML untuk membuat alias. Misalnya, Anda bisa membuat
+sumber daya yang bisa ditarik yang merupakan alias bagi sumber daya yang bisa ditarik lainnya:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/other_drawable" />
+</pre>
+
+<p>Hal ini terdengar berlebihan, namun bisa sangat berguna saat menggunakan sumber daya alternatif. Baca selengkapnya tentang
+<a href="providing-resources.html#AliasResources">Membuat sumber daya alias</a>.</p>
+
+
+
+<h3 id="ReferencesToThemeAttributes">Mengacu atribut gaya</h3>
+
+<p>Sumber daya atribut gaya memungkinkan Anda mengacu nilai
+suatu atribut dalam tema yang diterapkan saat ini. Dengan mengacu sebuah atribut gaya memungkinkan Anda
+menyesuaikan tampilan elemen UI dengan mengatur gayanya agar cocok dengan beragam variasi standar yang dipasok oleh
+tema saat ini, sebagai ganti memasok nilai yang ditanamkan (hard-coded). Mengacu sebuah atribut gaya
+pada dasarnya adalah "gunakan gaya yang didefinisikan oleh atribut ini, dalam tema saat ini".</p>
+
+<p>Untuk mengacu sebuah atribut gaya, sintaks namanya hampir sama dengan format sumber daya normal
+, namun sebagai ganti simbol @ ({@code @}), gunakan sebuah tanda tanya ({@code ?}), dan
+porsi tipe sumber daya bersifat opsional. Sebagai contoh:</p>
+
+<pre class="classic">
+?[<em>&lt;package_name&gt;</em>:][<em>&lt;resource_type&gt;</em>/]<em>&lt;resource_name&gt;</em>
+</pre>
+
+<p>Misalnya, begini cara Anda mengacu suatu atribut untuk mengatur warna teks agar cocok dengan
+warna teks "utama" tema sistem:</p>
+
+<pre>
+&lt;EditText id=&quot;text&quot;
+    android:layout_width=&quot;fill_parent&quot;
+    android:layout_height=&quot;wrap_content&quot;
+    android:textColor=&quot;<strong>?android:textColorSecondary</strong>&quot;
+    android:text=&quot;&#64;string/hello_world&quot; /&gt;
+</pre>
+
+<p>Di sini, atribut {@code android:textColor} menyebutkan nama atribut gaya
+dalam tema saat ini. Android kini menggunakan nilai yang diterapkan pada atribut gaya {@code android:textColorSecondary}
+sebagai nilai untuk {@code android:textColor} dalam widget ini. Karena alat sumber daya
+mengetahui bahwa atribut sumber daya diharapkan dalam konteks ini,
+maka Anda tidak perlu menyatakan tipenyanya secara eksplisit (yang akan berupa
+<code>?android:attr/textColorSecondary</code>)&mdash;Anda bisa mengecualikan tipe {@code attr}.</p>
+
+
+
+
+<h2 id="PlatformResources">Mengakses Sumber Daya Platform</h2>
+
+<p>Android berisi sejumlah sumber daya standar, seperti gaya, tema, dan layout. Untuk
+mengakses semua sumber daya ini, tetapkan acuan sumber daya Anda dengan nama paket
+<code>android</code>. Misalnya, Android menyediakan sumber daya layout yang bisa Anda gunakan untuk
+item daftar dalam{@link android.widget.ListAdapter}:</p>
+
+<pre>
+{@link android.app.ListActivity#setListAdapter(ListAdapter)
+setListAdapter}(new {@link
+android.widget.ArrayAdapter}&lt;String&gt;(this, <strong>android.R.layout.simple_list_item_1</strong>, myarray));
+</pre>
+
+<p>Dalam contoh ini, {@link android.R.layout#simple_list_item_1} adalah sumber daya layout yang didefinisikan oleh
+platform untuk item di {@link android.widget.ListView}. Anda bisa menggunakannya sebagai ganti menciptakan
+layout sendiri untuk item daftar. Untuk informasi selengkapnya, lihat panduan pengembang
+<a href="{@docRoot}guide/topics/ui/layout/listview.html">List View</a>.</p>
+
diff --git a/docs/html-intl/intl/id/guide/topics/resources/overview.jd b/docs/html-intl/intl/id/guide/topics/resources/overview.jd
new file mode 100644
index 0000000..def4932
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/resources/overview.jd
@@ -0,0 +1,103 @@
+page.title=Ikhtisar Sumber Daya
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>Topik</h2>
+  <ol>
+    <li><a href="providing-resources.html">Menyediakan Sumber Daya</a></li>
+    <li><a href="accessing-resources.html">Mengakses Sumber Daya</a></li>
+    <li><a href="runtime-changes.html">Menangani Perubahan Runtime</a></li>
+    <li><a href="localization.html">Pelokalan</a></li>
+  </ol>
+
+  <h2>Acuan</h2>
+  <ol>
+    <li><a href="available-resources.html">Tipe Sumber Daya</a></li>
+  </ol>
+</div>
+</div>
+
+
+<p>Anda harus selalu mengeksternalkan sumber daya seperti gambar dan string dari kode
+aplikasi, agar Anda bisa memeliharanya secara independen. Mengeksternalkan
+sumber daya juga membuat Anda dapat menyediakan sumber daya alternatif yang mendukung konfigurasi
+perangkat tertentu seperti bahasa atau ukuran layar yang berbeda, yang semakin penting
+seiring semakin banyak tersedianya perangkat berbasis Android dengan konfigurasi berbeda. Untuk
+memberikan kompatibilitas dengan konfigurasi berbeda, Anda harus menata sumber daya dalam
+direktori {@code res/} proyek Anda, menggunakan berbagai subdirektori yang mengelompokkan sumber daya menurut tipe
+dan konfigurasinya.</p>
+
+<div class="figure" style="width:429px">
+<img src="{@docRoot}images/resources/resource_devices_diagram1.png" height="167" alt="" />
+<p class="img-caption">
+<strong>Gambar 1.</strong> Dua perangkat berbeda, masing-masing menggunakan layout default
+(aplikasi tidak menyediakan layout alternatif).</p>
+</div>
+
+<div class="figure" style="width:429px">
+<img src="{@docRoot}images/resources/resource_devices_diagram2.png" height="167" alt="" />
+<p class="img-caption">
+<strong>Gambar 2.</strong> Dua perangkat berbeda, masing-masing menggunakan layout berbeda yang tersedia untuk
+ukuran layar berbeda.</p>
+</div>
+
+<p>Bagi setiap tipe sumber daya, Anda bisa menetapkan sumber daya <em>default</em> dan sumber daya
+<em>alternatif</em> untuk aplikasi Anda:</p>
+<ul>
+  <li>Sumber daya default adalah sumber daya yang harus digunakan apa pun
+konfigurasi perangkatnya atau jika tidak ada sumber daya alternatif yang sesuai
+dengan konfigurasi saat ini.</li>
+  <li>Sumber daya alternatif adalah sumber daya yang Anda desain untuk digunakan dengan
+konfigurasi tertentu. Untuk menetapkan bahwa satu kelompok sumber daya ditujukan bagi konfigurasi tertentu,
+tambahkan qualifier konfigurasi yang sesuai ke nama direktori.</li>
+</ul>
+
+<p>Misalnya, walaupun layout
+UI default Anda disimpan dalam direktori {@code res/layout/}, Anda dapat menetapkan layout berbeda
+untuk digunakan saat layar dalam orientasi lanskap, dengan menyimpannya dalam direktori {@code res/layout-land/}
+. Android secara otomatis memberlakukan sumber daya yang sesuai dengan mencocokkan konfigurasi perangkat
+saat ini dengan nama direktori sumber daya.</p>
+
+<p>Gambar 1 mengilustrasikan cara sistem memberlakukan layout yang sama untuk
+dua perangkat berbeda saat sumber daya alternatif tidak tersedia. Gambar 2 menunjukkan
+aplikasi yang sama saat menambahkan sumber daya layout alternatif untuk layar yang lebih besar.</p>
+
+<p>Dokumen-dokumen berikut berisi panduan lengkap mengenai cara menata sumber daya aplikasi,
+menetapkan sumber daya alternatif, mengaksesnya dalam aplikasi, dan banyak lagi:</p>
+
+<dl>
+  <dt><strong><a href="providing-resources.html">Menyediakan Sumber Daya</a></strong></dt>
+  <dd>Jenis sumber daya yang dapat Anda sediakan dalam aplikasi, tempat menyimpannya, dan cara membuat sumber daya
+alternatif untuk konfigurasi perangkat tertentu.</dd>
+  <dt><strong><a href="accessing-resources.html">Mengakses Sumber Daya</a></strong></dt>
+  <dd>Cara menggunakan sumber daya yang telah Anda sediakan, baik dengan mengacunya dari kode
+aplikasi Anda atau dari sumber daya XML lainnya.</dd>
+  <dt><strong><a href="runtime-changes.html">Menangani Perubahan Runtime</a></strong></dt>
+  <dd>Cara mengelola perubahan konfigurasi yang terjadi saat Aktivitas Anda berjalan.</dd>
+  <dt><strong><a href="localization.html">Pelokalan</a></strong></dt>
+  <dd>Panduan dari pengalaman untuk melokalkan aplikasi menggunakan sumber daya alternatif. Walaupun ini
+hanya satu penggunaan tertentu dari sumber daya alternatif, hal ini sangat penting dalam meraih pengguna lebih
+banyak.</dd>
+  <dt><strong><a href="available-resources.html">Tipe Sumber Daya</a></strong></dt>
+  <dd>Acuan dari berbagai tipe sumber daya yang dapat Anda sediakan, menjelaskan elemen-elemen XML,
+atribut, dan sintaksnya. Misalnya, acuan ini menunjukkan kepada Anda cara membuat sumber daya untuk
+menu aplikasi, drawable, animasi, dan lainnya.</dd>
+</dl>
+
+<!--
+<h2>Raw Assets</h2>
+
+<p>An alternative to saving files in {@code res/} is to save files in the {@code
+assets/} directory. This should only be necessary if you need direct access to original files and
+directories by name. Files saved in the {@code assets/} directory will not be given a resource
+ID, so you can't reference them through the {@code R} class or from XML resources. Instead, you can
+query data in the {@code assets/} directory like an ordinary file system, search through the
+directory and
+read raw data using {@link android.content.res.AssetManager}. For example, this can be more useful
+when dealing with textures for a game. However, if you only need to read raw data from a file
+(such as a video or audio file), then you should save files into the {@code res/raw/} directory and
+then read a stream of bytes using {@link android.content.res.Resources#openRawResource(int)}. This
+is uncommon, but if you need direct access to original files in {@code assets/}, refer to the {@link
+android.content.res.AssetManager} documentation.</p>
+-->
diff --git a/docs/html-intl/intl/id/guide/topics/resources/providing-resources.jd b/docs/html-intl/intl/id/guide/topics/resources/providing-resources.jd
new file mode 100644
index 0000000..9bccd24
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/resources/providing-resources.jd
@@ -0,0 +1,1094 @@
+page.title=Menyediakan Sumber Daya
+parent.title=Sumber Daya Aplikasi
+parent.link=index.html
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>Tampilan Cepat</h2>
+  <ul>
+    <li>Berbagai tipe sumber daya termasuk dalam subdirektori {@code res/}</li>
+    <li>Sumber daya alternatif menyediakan file sumber daya dengan konfigurasi tertentu</li>
+    <li>Sertakan selalu sumber daya default agar aplikasi Anda tidak bergantung pada
+konfigurasi perangkat tertentu</li>
+  </ul>
+  <h2>Dalam dokumen ini</h2>
+  <ol>
+    <li><a href="#ResourceTypes">Mengelompokkan Tipe Sumber Daya</a></li>
+    <li><a href="#AlternativeResources">Menyediakan Sumber Daya Alternatif</a>
+      <ol>
+        <li><a href="#QualifierRules">Aturan penamaan qualifier</a></li>
+        <li><a href="#AliasResources">Membuat sumber daya alias</a></li>
+      </ol>
+    </li>
+    <li><a href="#Compatibility">Menyediakan Kompatibilitas Perangkat Terbaik dengan Sumber Daya</a></li>
+    <li><a href="#BestMatch">Cara Android Menemukan Sumber Daya yang Paling Cocok</a></li>
+  </ol>
+
+  <h2>Lihat juga</h2>
+  <ol>
+    <li><a href="accessing-resources.html">Mengakses Sumber Daya</a></li>
+    <li><a href="available-resources.html">Tipe Sumber Daya</a></li>
+    <li><a href="{@docRoot}guide/practices/screens_support.html">Mendukung Beberapa
+Layar</a></li>
+  </ol>
+</div>
+</div>
+
+<p>Anda harus selalu mengeksternalkan sumber daya aplikasi seperti gambar dan string dari kode
+, agar Anda bisa memeliharanya secara independen. Anda juga harus menyediakan sumber daya alternatif untuk
+konfigurasi perangkat tertentu, dengan mengelompokkannya dalam direktori sumber daya bernama khusus. Saat
+runtime, Android menggunakan sumber daya yang sesuai berdasarkan konfigurasi saat ini. Misalnya, Anda mungkin
+ingin menyediakan layout UI berbeda bergantung pada ukuran layar atau string berbeda bergantung pada
+pengaturan bahasa.</p>
+
+<p>Setelah mengeksternalkan sumber daya aplikasi, Anda dapat mengaksesnya menggunakan
+ID sumber daya yang dibuat dalam kelas {@code R} proyek Anda. Cara menggunakan
+sumber daya dalam aplikasi dibahas dalam <a href="accessing-resources.html">Mengakses
+Sumber Daya</a>. Dokumen ini menampilkan cara mengelompokkan sumber daya
+dalam proyek Android Anda dan menyediakan sumber daya alternatif untuk konfigurasi perangkat tertentu.</p>
+
+
+<h2 id="ResourceTypes">Mengelompokkan Tipe Sumber Daya</h2>
+
+<p>Anda harus menempatkan setiap tipe sumber daya dalam subdirektori spesifik pada direktori
+{@code res/} proyek. Misalnya, inilah hierarki file untuk proyek sederhana:</p>
+
+<pre class="classic no-pretty-print">
+MyProject/
+    src/  <span style="color:black">
+        MyActivity.java  </span>
+    res/
+        drawable/  <span style="color:black">
+            graphic.png  </span>
+        layout/  <span style="color:black">
+            main.xml
+            info.xml</span>
+        mipmap/  <span style="color:black">
+            icon.png </span>
+        values/  <span style="color:black">
+            strings.xml  </span>
+</pre>
+
+<p>Seperti yang Anda lihat dalam contoh ini, direktori {@code res/} berisi semua sumber daya (dalam
+subdirektori): sumber daya gambar, dua sumber daya layout, direktori {@code mipmap/} untuk ikon
+launcher, dan satu file sumber daya string. Nama direktori
+sumber daya penting dan dijelaskan dalam tabel 1.</p>
+
+<p class="note"><strong>Catatan:</strong> Untuk informasi selengkapnya tentang menggunakan folder mipmap, lihat
+<a href="{@docRoot}tools/projects/index.html#mipmap">Mengelola Ikhtisar Proyek</a>.</p>
+
+<p class="table-caption" id="table1"><strong>Tabel 1.</strong> Direktori sumber daya
+didukung dalam direktori proyek {@code res/}.</p>
+
+<table>
+  <tr>
+    <th scope="col">Direktori</th>
+    <th scope="col">Tipe Sumber Daya</th>
+  </tr>
+
+  <tr>
+    <td><code>animator/</code></td>
+    <td>File XML yang mendefinisikan <a href="{@docRoot}guide/topics/graphics/prop-animation.html">animasi
+properti</a>.</td>
+  </tr>
+
+  <tr>
+    <td><code>anim/</code></td>
+    <td>File XML yang mendefinisikan <a href="{@docRoot}guide/topics/graphics/view-animation.html#tween-animation">animasi
+tween</a>. (Animasi properti juga dapat disimpan dalam direktori ini, namun
+direktori {@code animator/} lebih disukai bagi animasi properti agar kedua tipe
+ini dapat dibedakan.)</td>
+  </tr>
+
+  <tr>
+    <td><code>color/</code></td>
+    <td>File XML yang mendefinisikan daftar status warna. Lihat <a href="color-list-resource.html">Sumber Daya
+Daftar Status Warna</a></td>
+  </tr>
+
+  <tr>
+    <td><code>drawable/</code></td>
+
+    <td><p>File bitmap ({@code .png}, {@code .9.png}, {@code .jpg}, {@code .gif}) atau file XML yang
+dikompilasi menjadi subtipe sumber daya drawable berikut:</p>
+      <ul>
+        <li>File bitmap</li>
+        <li>Nine-Patches (bitmap yang dapat diubah ukurannya)</li>
+        <li>Daftar status</li>
+        <li>Bentuk</li>
+        <li>Drawable animasi</li>
+        <li>Drawable lainnya</li>
+      </ul>
+      <p>Lihat <a href="drawable-resource.html">Sumber Daya Drawable</a>.</p>
+    </td>
+  </tr>
+
+  <tr>
+    <td><code>mipmap/</code></td>
+    <td>File drawable untuk densitas ikon launcher yang berbeda. Untuk informasi selengkapnya tentang
+ mengelola ikon launcher dengan folder {@code mipmap/}, lihat
+<a href="{@docRoot}tools/project/index.html#mipmap">Mengelola Ikhtisar Proyek</a>.</td>
+  </tr>
+
+  <tr>
+    <td><code>layout/</code></td>
+    <td>File XML yang mendefinisikan layout antarmuka pengguna.
+        Lihat <a href="layout-resource.html">Sumber Daya Layout</a>.</td>
+  </tr>
+
+  <tr>
+    <td><code>menu/</code></td>
+    <td>File XML yang mendefinisikan menu aplikasi, seperti Menu Opsi, Menu Konteks, atau Sub
+Menu. Lihat <a href="menu-resource.html">Sumber Daya Menu</a>.</td>
+  </tr>
+
+  <tr>
+    <td><code>raw/</code></td>
+    <td><p>File tak didukung yang akan disimpan dalam bentuk mentah. Untuk membuka sumber daya ini dengan
+{@link java.io.InputStream} mentah, panggil {@link android.content.res.Resources#openRawResource(int)
+Resources.openRawResource()} dengan ID sumber daya, yaitu {@code R.raw.<em>filename</em>}.</p>
+      <p>Akan tetapi, jika Anda butuh akses ke nama file asli dan hierarki file, Anda bisa mempertimbangkan
+untuk menyimpan beberapa sumber daya dalam direktori {@code
+assets/} (sebagai ganti {@code res/raw/}). File dalam {@code assets/} tidak diberi
+ID sumber daya, jadi Anda bisa membacanya hanya dengan menggunakan {@link android.content.res.AssetManager}.</p></td>
+  </tr>
+
+  <tr>
+    <td><code>values/</code></td>
+    <td><p>File XML yang berisi nilai-nilai sederhana, seperti string, integer, dan warna.</p>
+      <p>Walaupun file sumber daya XML dalam subdirektori {@code res/} lainnya mendefinisikan satu sumber daya
+berdasarkan nama file XML, file dalam direktori {@code values/} menggambarkan beberapa sumber daya.
+Untuk file dalam direktori ini, setiap anak elemen {@code &lt;resources&gt;} mendefinisikan satu sumber
+daya. Misalnya, elemen {@code &lt;string&gt;} membuat sumber daya
+{@code R.string} dan elemen {@code &lt;color&gt;} membuat sumber daya {@code R.color}
+.</p>
+      <p>Karena setiap sumber daya didefinisikan dengan elemen XML-nya sendiri, Anda bisa bebas menamai file
+ini dan menempatkan tipe sumber daya berbeda dalam satu file. Akan tetapi, agar jelas, Anda mungkin
+perlu menempatkan tipe sumber daya unik dalam file berbeda. Misalnya, berikut ini adalah beberapa ketentuan
+penamaan file untuk sumber daya yang dapat Anda buat dalam direktori ini:</p>
+      <ul>
+        <li>arrays.xml untuk larik sumber daya tipe (<a href="more-resources.html#TypedArray">larik bertipe</a>).</li>
+        <li>colors.xml untuk <a href="more-resources.html#Color">nilai warna</a></li>
+        <li>dimens.xml untuk <a href="more-resources.html#Dimension">nilai dimensi</a>.</li>
+        <li>strings.xml untuk <a href="string-resource.html">nilai
+string</a>.</li>
+        <li>styles.xml untuk <a href="style-resource.html">gaya</a>.</li>
+      </ul>
+      <p>Lihat <a href="string-resource.html">Sumber Daya String</a>,
+        <a href="style-resource.html">Sumber Daya Gaya</a>, dan
+        <a href="more-resources.html">Tipe Sumber Daya Lainnya</a>.</p>
+    </td>
+  </tr>
+
+  <tr>
+    <td><code>xml/</code></td>
+    <td>File XML tak didukung yang bisa dibaca saat runtime dengan memanggil {@link
+android.content.res.Resources#getXml(int) Resources.getXML()}. Berbagai file konfigurasi XML
+harus disimpan di sini, seperti <a href="{@docRoot}guide/topics/search/searchable-config.html">konfigurasi yang dapat dicari</a>.
+<!-- or preferences configuration. --></td>
+  </tr>
+</table>
+
+<p class="caution"><strong>Perhatian:</strong> Jangan menyimpan file sumber daya secara langsung dalam
+direktori {@code res/}&mdash; karena akan menyebabkan kesalahan compiler.</p>
+
+<p>Untuk informasi selengkapnya tentang tipe sumber daya tertentu, lihat dokumentasi <a href="available-resources.html">Tipe Sumber Daya</a>.</p>
+
+<p>Sumber daya yang disimpan dalam subdirektori yang didefinisikan dalam tabel 1 adalah sumber daya
+"default" Anda. Berarti sumber daya ini mendefinisikan desain default dan konten untuk aplikasi Anda.
+Akan tetapi, beberapa tipe perangkat berbasis Android mungkin memanggil tipe sumber daya yang berbeda.
+Misalnya, jika perangkat memiliki layar yang lebih besar daripada layar normal, maka Anda harus
+menyediakan sumber daya layout berbeda yang memanfaatkan ruang layar yang lebih besar. Atau, jika perangkat
+memiliki pengaturan bahasa berbeda, maka Anda harus menyediakan sumber daya string berbeda yang menerjemahkan teks dalam
+antarmuka pengguna Anda. Untuk menyediakan sumber daya berbeda ini bagi
+konfigurasi perangkat yang berbeda, Anda harus menyediakan sumber daya alternatif, selain sumber
+daya default.</p>
+
+
+<h2 id="AlternativeResources">Menyediakan Sumber Daya Alternatif</h2>
+
+
+<div class="figure" style="width:429px">
+<img src="{@docRoot}images/resources/resource_devices_diagram2.png" height="167" alt="" />
+<p class="img-caption">
+<strong>Gambar 1.</strong> Dua perangkat berbeda, masing-masing menggunakan sumber daya layout berbeda.</p>
+</div>
+
+<p>Hampir setiap aplikasi harus menyediakan sumber daya alternatif untuk mendukung konfigurasi
+perangkat tertentu. Misalnya, Anda harus menyertakan sumber daya drawable alternatif untuk densitas layar
+berbeda dan sumber daya string alternatif untuk bahasa yang berbeda. Saat runtime, Android
+akan mendeteksi konfigurasi perangkat aktif dan memuat
+sumber daya yang sesuai untuk aplikasi Anda.</p>
+
+<p>Untuk menyebutkan alternatif konfigurasi tertentu untuk satu set sumber daya:</p>
+<ol>
+  <li>Buat direktori baru dalam {@code res/} yang dinamai dalam bentuk {@code
+<em>&lt;resources_name&gt;</em>-<em>&lt;config_qualifier&gt;</em>}.
+    <ul>
+      <li><em>{@code &lt;resources_name&gt;}</em> adalah nama direktori dari sumber daya default
+terkait (didefinisikan dalam tabel 1).</li>
+      <li><em>{@code &lt;qualifier&gt;}</em> adalah nama yang menetapkan konfigurasi individu
+yang akan digunakan sumber daya ini (didefinisikan dalam tabel 2).</li>
+    </ul>
+    <p>Anda bisa menambahkan lebih dari satu <em>{@code &lt;qualifier&gt;}</em>. Pisahkan masing-masing
+dengan tanda hubung.</p>
+    <p class="caution"><strong>Perhatian:</strong> Saat menambahkan beberapa qualifier, Anda
+harus menempatkannya dalam urutan yang sama dengan yang tercantum dalam tabel 2. Jika urutan qualifier
+salah, sumber daya akan diabaikan.</p>
+  </li>
+  <li>Simpan masing-masing sumber daya alternatif dalam direktori baru ini. File sumber daya harus dinamai
+sama persis dengan file sumber daya default.</li>
+</ol>
+
+<p>Misalnya, berikut ini beberapa sumber daya default dan sumber daya alternatif:</p>
+
+<pre class="classic no-pretty-print">
+res/
+    drawable/   <span style="color:black">
+        icon.png
+        background.png    </span>
+    drawable-hdpi/  <span style="color:black">
+        icon.png
+        background.png  </span>
+</pre>
+
+<p>Qualifier {@code hdpi} menunjukkan bahwa sumber daya dalam direktori itu diperuntukkan bagi perangkat dengan
+layar densitas tinggi. Gambar di masing-masing direktori drawable memiliki ukuran untuk densitas layar
+tertentu, namun nama filenya persis
+sama. Dengan demikian, ID sumber daya yang Anda gunakan untuk mengacu gambar {@code icon.png} atau @code
+background.png} selalu sama, namun Android memilih
+versi masing-masing sumber daya yang paling cocok dengan perangkat saat ini, dengan membandingkan informasi konfigurasi
+perangkat dengan qualifier dalam nama direktori sumber daya.</p>
+
+<p>Android mendukung beberapa qualifier konfigurasi dan Anda dapat
+menambahkan beberapa qualifier ke satu nama direktori, dengan memisahkan setiap qualifier dengan tanda hubung. Tabel 2
+berisi daftar qualifier konfigurasi yang valid, dalam urutan prioritas&mdash;jika Anda menggunakan beberapa
+qualifier sebagai direktori sumber daya, Anda harus menambahkannya ke nama direktori sesuai urutan
+yang tercantum dalam tabel.</p>
+
+
+<p class="table-caption" id="table2"><strong>Tabel 2.</strong> Nama-nama
+qualifier konfigurasi.</p>
+<table>
+    <tr>
+        <th>Konfigurasi</th>
+        <th>Nilai-nilai Qualifier</th>
+        <th>Keterangan</th>
+    </tr>
+    <tr id="MccQualifier">
+      <td>MCC dan MNC</td>
+      <td>Contoh:<br/>
+        <code>mcc310</code><br/>
+        <code><nobr>mcc310-mnc004</nobr></code><br/>
+        <code>mcc208-mnc00</code><br/>
+        dll.
+      </td>
+      <td>
+        <p>Kode negara seluler (MCC), bisa diikuti dengan kode jaringan seluler (MNC)
+ dari kartu SIM dalam perangkat. Misalnya, <code>mcc310</code> adalah AS untuk operator mana saja,
+ <code>mcc310-mnc004</code> adalah AS untuk Verizon, dan <code>mcc208-mnc00</code> Prancis untuk
+Orange.</p>
+        <p>Jika perangkat menggunakan koneksi radio (ponsel GSM), nilai-nilai MCC dan MNC berasal
+dari kartu SIM.</p>
+        <p>Anda juga dapat menggunakan MNC saja (misalnya, untuk menyertakan sumber daya legal
+spesifik untuk negara itu di aplikasi Anda). Jika Anda perlu menetapkan hanya berdasarkan bahasa, maka gunakan qualifier
+<em>bahasa dan wilayah</em> sebagai gantinya (akan dibahas nanti). Jika Anda memutuskan untuk menggunakan qualifier MCC dan
+MNC, Anda harus melakukannya dengan hati-hati dan menguji apakah qualifier itu berjalan sesuai harapan.</p>
+        <p>Lihat juga bidang konfigurasi {@link
+android.content.res.Configuration#mcc}, dan {@link
+android.content.res.Configuration#mnc}, yang masing-masing menunjukkan kode negara seluler saat ini
+dan kode jaringan seluler.</p>
+      </td>
+    </tr>
+    <tr id="LocaleQualifier">
+      <td>Bahasa dan wilayah</td>
+      <td>Contoh:<br/>
+        <code>en</code><br/>
+        <code>fr</code><br/>
+        <code>en-rUS</code><br/>
+        <code>fr-rFR</code><br/>
+        <code>fr-rCA</code><br/>
+        dll.
+      </td>
+      <td><p>Bahasa didefinisikan oleh kode bahasa dua huruf <a href="http://www.loc.gov/standards/iso639-2/php/code_list.php">ISO
+639-1</a>, bisa juga diikuti dengan kode wilayah
+dua huruf <a href="http://www.iso.org/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html">ISO
+3166-1-alpha-2</a> (diawali dengan huruf kecil "{@code r}").
+        </p><p>
+        Kode <em>tidak</em> membedakan huruf besar atau kecil; awalan {@code r} akan digunakan untuk
+membedakan bagian wilayah.
+        Anda tidak bisa menetapkan wilayah saja.</p>
+        <p>Ini bisa berubah selama masa pakai
+aplikasi Anda jika pengguna mengubah bahasanya dalam pengaturan sistem. Lihat <a href="runtime-changes.html">Menangani Perubahan Runtime</a> untuk informasi tentang
+bagaimana hal ini dapat memengaruhi aplikasi Anda selama runtime.</p>
+        <p>Lihat <a href="localization.html">Pelokalan</a> untuk panduan lengkap melokalkan
+aplikasi Anda ke bahasa lain.</p>
+        <p>Lihat juga bidang konfigurasi {@link android.content.res.Configuration#locale} yang menunjukkan
+bahasa setempat yang digunakan saat ini.</p>
+      </td>
+    </tr>
+    <tr id="LayoutDirectionQualifier">
+      <td>Arah Layout</td>
+      <td><code>ldrtl</code><br/>
+        <code>ldltr</code><br/>
+      </td>
+      <td><p>Arah layout aplikasi Anda. {@code ldrtl} berarti "arah layout dari kanan ke kiri".
+ {@code ldltr} berarti "arah layout dari kiri ke kanan" dan merupakan nilai implisit default.
+      </p>
+      <p>Ini bisa berlaku untuk sumber daya mana pun seperti layout, drawable, atau nilai-nilai.
+      </p>
+      <p>Misalnya, jika Anda ingin memberikan beberapa layout khusus untuk bahasa Arab dan beberapa
+layout umum untuk setiap bahasa lainnya yang menggunakan "kanan-ke-kiri" lainnya (seperti bahasa Persia atau Ibrani) maka Anda akan memiliki:
+      </p>
+<pre class="classic no-pretty-print">
+res/
+    layout/   <span style="color:black">
+        main.xml  </span>(Default layout)
+    layout-ar/  <span style="color:black">
+        main.xml  </span>(Specific layout for Arabic)
+    layout-ldrtl/  <span style="color:black">
+        main.xml  </span>(Any "right-to-left" language, except
+                  for Arabic, because the "ar" language qualifier
+                  has a higher precedence.)
+</pre>
+        <p class="note"><strong>Catatan:</strong> Untuk mengaktifkan fitur
+layout kanan-ke-kiri untuk aplikasi, Anda harus mengatur <a href="{@docRoot}guide/topics/manifest/application-element.html#supportsrtl">{@code
+        supportsRtl}</a> ke {@code "true"} dan mengatur <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> ke 17 atau yang lebih tinggi.</p>
+        <p><em>Ditambahkan dalam API level 17.</em></p>
+      </td>
+    </tr>
+    <tr id="SmallestScreenWidthQualifier">
+      <td>smallestWidth</td>
+      <td><code>sw&lt;N&gt;dp</code><br/><br/>
+        Contoh:<br/>
+        <code>sw320dp</code><br/>
+        <code>sw600dp</code><br/>
+        <code>sw720dp</code><br/>
+        dll.
+      </td>
+      <td>
+        <p>Ukuran dasar layar, sebagaimana yang ditunjukkan oleh dimensi terpendek dari area layar
+yang tersedia. Secara spesifik, smallestWidth perangkat adalah yang terpendek dari
+tinggi dan lebar layar yang tersedia (Anda dapat menganggapnya sebagai "lebar terkecil yang memungkinkan" untuk layar). Anda bisa
+menggunakan qualifier ini untuk memastikan bahwa, apa pun orientasi layar saat ini, aplikasi
+Anda memiliki paling tidak {@code &lt;N&gt;} dps dari lebar yang tersedia untuk UI-nya.</p>
+        <p>Misalnya, jika layout mengharuskan dimensi layar terkecilnya setiap saat paling tidak
+600 dp, maka Anda dapat menggunakan qualifer ini untuk membuat sumber daya layout, {@code
+res/layout-sw600dp/}. Sistem akan menggunakan sumber daya ini hanya bila dimensi layar terkecil yang
+tersedia paling tidak 600 dp, tanpa mempertimbangkan apakah sisi 600 dp adalah tinggi atau
+lebar yang dipersepsikan pengguna. SmallestWidth adalah karakteristik ukuran layar tetap dari perangkat; <strong>smallestWidth
+perangkat tidak berubah saat orientasi layar berubah</strong>.</p>
+        <p>SmallestWidth perangkat memperhitungkan dekorasi layar dan UI sistem. Misalnya
+, jika perangkat memiliki beberapa elemen UI persisten pada layar yang menghitung ruang di sepanjang
+sumbu smallestWidth, sistem akan mendeklarasikan smallestWidth lebih kecil daripada ukuran layar sebenarnya,
+karena itu adalah piksel layar yang tidak tersedia untuk UI Anda. Sehingga nilai yang Anda
+gunakan haruslah merupakan dimensi terkecil sebenarnya yang <em>dibutuhkan oleh layout Anda</em> (biasanya, nilai ini adalah
+"lebar terkecil" yang didukung layout Anda, apa pun orientasi layar saat ini).</p>
+        <p>Sebagian nilai yang mungkin Anda gunakan untuk ukuran layar umum:</p>
+        <ul>
+          <li>320, untuk perangkat berkonfigurasi layar seperti:
+            <ul>
+              <li>240x320 ldpi (handset QVGA)</li>
+              <li>320x480 mdpi (handset)</li>
+              <li>480x800 hdpi (handset densitas tinggi)</li>
+            </ul>
+          </li>
+          <li>480, untuk layar seperti 480x800 mdpi (tablet/handset).</li>
+          <li>600, untuk layar seperti 600x1024 mdpi (tablet 7").</li>
+          <li>720, untuk layar seperti 720x1280 mdpi (tablet 10").</li>
+        </ul>
+        <p>Bila aplikasi Anda menyediakan beberapa direktori sumber daya dengan nilai yang berbeda untuk
+qualifier smallestWidth terkecil, sistem akan menggunakan nilai terdekat dengan (tanpa melebihi)
+smallestWidth perangkat. </p>
+        <p><em>Ditambahkan dalam API level 13.</em></p>
+        <p>Lihat juga atribut <a href="{@docRoot}guide/topics/manifest/supports-screens-element.html#requiresSmallest">{@code
+android:requiresSmallestWidthDp}</a>, yang mendeklarasikan smallestWidth minimum yang
+kompatibel dengan aplikasi Anda, dan bidang konfigurasi {@link
+android.content.res.Configuration#smallestScreenWidthDp}, yang menyimpan nilai
+smallestWidth perangkat.</p>
+        <p>Untuk informasi selengkapnya tentang mendesain untuk layar berbeda dan menggunakan
+qualifier ini, lihat panduan pengembang <a href="{@docRoot}guide/practices/screens_support.html">Mendukung
+Multi Layar</a>.</p>
+      </td>
+    </tr>
+    <tr id="ScreenWidthQualifier">
+      <td>Lebar yang tersedia</td>
+      <td><code>w&lt;N&gt;dp</code><br/><br/>
+        Contoh:<br/>
+        <code>w720dp</code><br/>
+        <code>w1024dp</code><br/>
+        dll.
+      </td>
+      <td>
+        <p>Menetapkan lebar layar minimum yang tersedia, di unit {@code dp} yang
+menggunakan sumber daya&mdash;yang didefinisikan oleh nilai <code>&lt;N&gt;</code>.  Nilai konfigurasi ini
+ akan berubah bila orientasi
+berubah antara lanskap dan potret agar cocok dengan lebar sebenarnya saat ini.</p>
+        <p>Bila aplikasi Anda menyediakan beberapa direktori sumber daya dengan nilai yang berbeda
+ untuk konfigurasi ini, sistem akan menggunakan nilai terdekat dengan (tanpa melebihi)
+ lebar layar perangkat saat ini.  Nilai
+di sini memperhitungkan dekorasi layar akun, jadi jika perangkat memiliki beberapa
+elemen UI persisten di tepi kiri atau kanan, layar
+menggunakan nilai lebar yang lebih kecil daripada ukuran layar sebenarnya, yang memperhitungkan
+elemen UI ini dan mengurangi ruang aplikasi yang tersedia.</p>
+        <p><em>Ditambahkan dalam API level 13.</em></p>
+        <p>Lihat juga bidang konfigurasi {@link android.content.res.Configuration#screenWidthDp}
+ yang menyimpan lebar layar saat ini.</p>
+        <p>Untuk informasi selengkapnya tentang mendesain untuk layar berbeda dan menggunakan
+qualifier ini, lihat panduan pengembang <a href="{@docRoot}guide/practices/screens_support.html">Mendukung
+Multi Layar</a>.</p>
+      </td>
+    </tr>
+    <tr id="ScreenHeightQualifier">
+      <td>Tinggi yang tersedia</td>
+      <td><code>h&lt;N&gt;dp</code><br/><br/>
+        Contoh:<br/>
+        <code>h720dp</code><br/>
+        <code>h1024dp</code><br/>
+        dll.
+      </td>
+      <td>
+        <p>Menetapkan tinggi layar minimum yang tersedia, dalam satuan "dp" yang harus digunakan
+sumber daya &mdash;bersama nilai yang didefinisikan oleh <code>&lt;N&gt;</code>.  Nilai konfigurasi ini
+ akan berubah saat orientasi
+berubah antara lanskap dan potret agar cocok dengan tinggi sebenarnya saat ini.</p>
+        <p>Bila aplikasi menyediakan beberapa direktori sumber daya dengan nilai yang berbeda
+ untuk konfigurasi ini, sistem akan menggunakan nilai yang terdekat dengan (tanpa melebihi)
+ tinggi layar perangkat saat ini.  Nilai
+di sini memperhitungkan dekorasi layar akun, jadi jika perangkat memiliki beberapa
+elemen UI persisten di tepi atas atau bawah, layar akan
+menggunakan nilai tinggi yang lebih kecil daripada ukuran layar sebenarnya, memperhitungkan
+elemen UI ini dan mengurangi ruang aplikasi yang tersedia.  Dekorasi
+layar yang tidak tetap (misalnya baris status (status-bar) telepon yang bisa
+disembunyikan saat layar penuh) di sini <em>tidak</em> diperhitungkan, demikian pula
+dekorasi jendela seperti baris judul (title-bar)atau baris tindakan (action-bar), jadi aplikasi harus disiapkan
+untuk menangani ruang yang agak lebih kecil daripada yang ditetapkan.
+        <p><em>Ditambahkan dalam API level 13.</em></p>
+        <p>Lihat juga bidang konfigurasi {@link android.content.res.Configuration#screenHeightDp}
+ yang menyimpan lebar layar saat ini.</p>
+        <p>Untuk informasi selengkapnya tentang mendesain untuk layar berbeda dan menggunakan
+qualifier ini, lihat panduan pengembang <a href="{@docRoot}guide/practices/screens_support.html">Mendukung
+Multi Layar</a>.</p>
+      </td>
+    </tr>
+    <tr id="ScreenSizeQualifier">
+      <td>Ukuran layar</td>
+      <td>
+        <code>small</code><br/>
+        <code>normal</code><br/>
+        <code>large</code><br/>
+        <code>xlarge</code>
+      </td>
+      <td>
+        <ul class="nolist">
+        <li>{@code small}: Layar yang berukuran serupa dengan
+layar QVGA densitas rendah. Ukuran layout minimum untuk layar kecil
+adalah sekitar 320x426 satuan dp.  Misalnya QVGA densitas rendah
+dan VGA densitas tinggi.</li>
+        <li>{@code normal}: Layar yang berukuran serupa dengan
+layar HVGA densitas sedang. Ukuran layout minimum untuk
+layar normal adalah sekitar 320x470 satuan dp.  Contoh layar seperti itu adalah
+WQVGA densitas rendah, HVGA densitas sedang, WVGA
+     densitas tinggi.</li>
+        <li>{@code large}: Layar yang berukuran serupa dengan
+layar VGA densitas sedang.
+        Ukuran layout minimum untuk layar besar adalah sekitar 480x640 satuan dp.
+        Misalnya layar VGA dan WVGA densitas sedang.</li>
+        <li>{@code xlarge}: Layar yang jauh lebih besar dari layar HVGA
+densitas sedang tradisional. Ukuran layout minimum untuk
+layar ekstra besar adalah sekitar 720x960 satuan dp.  Perangkat dengan layar ekstra besar
+seringkali terlalu besar untuk dibawa dalam saku dan kemungkinan besar
+ berupa perangkat bergaya tablet. <em>Ditambahkan dalam API level 9.</em></li>
+        </ul>
+        <p class="note"><strong>Catatan:</strong> Menggunakan qualifier ukuran tidak berarti bahwa
+sumber daya <em>hanya</em> untuk layar ukuran itu saja. Jika Anda tidak menyediakan sumber
+daya alternatif dengan qualifier yang lebih cocok dengan konfigurasi perangkat saat ini, sistem dapat menggunakan sumber daya
+mana saja yang <a href="#BestMatch">paling cocok</a>.</p>
+        <p class="caution"><strong>Perhatian:</strong> Jika semua sumber daya Anda menggunakan
+qualifier yang berukuran <em>lebih besar</em> daripada layar saat ini, sistem <strong>tidak</strong> akan menggunakannya dan aplikasi
+Anda akan crash saat runtime (misalnya, jika semua sumber daya layout ditandai dengan qualifier {@code
+xlarge}, namun perangkat memiliki ukuran layar normal).</p>
+        <p><em>Ditambahkan dalam API level 4.</em></p>
+
+        <p>Lihat <a href="{@docRoot}guide/practices/screens_support.html">Mendukung Beberapa
+Layar</a> untuk informasi selengkapnya.</p>
+        <p>Lihat juga bidang konfigurasi {@link android.content.res.Configuration#screenLayout},
+ yang menunjukkan apakah layar berukuran kecil, normal, atau
+besar.</p>
+      </td>
+    </tr>
+    <tr id="ScreenAspectQualifier">
+      <td>Aspek layar</td>
+      <td>
+        <code>long</code><br/>
+        <code>notlong</code>
+      </td>
+      <td>
+        <ul class="nolist">
+          <li>{@code long}: Layar panjang, seperti WQVGA, WVGA, FWVGA</li>
+          <li>{@code notlong}: Layar tidak panjang, seperti QVGA, HVGA, dan VGA</li>
+        </ul>
+        <p><em>Ditambahkan dalam API level 4.</em></p>
+        <p>Ini berdasarkan sepenuhnya pada rasio aspek layar (layar "panjang" lebih lebar). Ini
+tidak ada kaitannya dengan orientasi layar.</p>
+        <p>Lihat juga bidang konfigurasi {@link android.content.res.Configuration#screenLayout},
+ yang menunjukkan apakah layar panjang.</p>
+      </td>
+    </tr>
+    <tr id="OrientationQualifier">
+      <td>Orientasi layar</td>
+      <td>
+        <code>port</code><br/>
+        <code>land</code>  <!-- <br/>
+        <code>square</code>  -->
+      </td>
+      <td>
+        <ul class="nolist">
+          <li>{@code port}: Perangkat dalam orientasi potret (vertikal)</li>
+          <li>{@code land}: Perangkat dalam orientasi lanskap (horizontal)</li>
+          <!-- Square mode is currently not used. -->
+        </ul>
+        <p>Ini bisa berubah selama masa pakai aplikasi Anda jika pengguna memutar
+layar. Lihat <a href="runtime-changes.html">Menangani Perubahan Runtime</a> untuk
+ informasi tentang bagaimana hal ini memengaruhi aplikasi Anda selama runtime.</p>
+        <p>Lihat juga bidang konfigurasi {@link android.content.res.Configuration#orientation},
+yang menunjukkan orientasi perangkat saat ini.</p>
+      </td>
+    </tr>
+    <tr id="UiModeQualifier">
+      <td>Mode UI</td>
+      <td>
+        <code>car</code><br/>
+        <code>desk</code><br/>
+        <code>television</code><br/>
+        <code>appliance</code>
+        <code>watch</code>
+      </td>
+      <td>
+        <ul class="nolist">
+          <li>{@code car}: Perangkat sedang menampilkan di dudukan perangkat di mobil</li>
+          <li>{@code desk}: Perangkat sedang menampilkan di dudukan perangkat di meja</li>
+          <li>{@code television}: Perangkat sedang menampilkan di televisi, yang menyediakan
+pengalaman "sepuluh kaki" dengan UI-nya pada layar besar yang berada jauh dari pengguna,
+terutama diorientasikan seputar DPAD atau
+interaksi non-pointer lainnya</li>
+          <li>{@code appliance}: Perangkat berlaku sebagai
+alat, tanpa tampilan</li>
+          <li>{@code watch}: Perangkat memiliki tampilan dan dikenakan di pergelangan tangan</li>
+        </ul>
+        <p><em>Ditambahkan dalam API level 8, televisi ditambahkan dalam API 13, jam ditambahkan dalam API 20.</em></p>
+        <p>Untuk informasi tentang cara aplikasi merespons saat perangkat dimasukkan
+ke dalam atau dilepaskan dari dudukannya, bacalah <a href="{@docRoot}training/monitoring-device-state/docking-monitoring.html">Menentukan
+dan Memantau Kondisi dan Tipe Dudukan</a>.</p>
+        <p>Ini bisa berubah selama masa pakai aplikasi jika pengguna menempatkan perangkat di
+dudukannya. Anda dapat mengaktifkan atau menonaktifkan sebagian mode ini menggunakan {@link
+android.app.UiModeManager}. Lihat <a href="runtime-changes.html">Menangani Perubahan Runtime</a> untuk
+informasi tentang bagaimana hal ini memengaruhi aplikasi Anda selama runtime.</p>
+      </td>
+    </tr>
+    <tr id="NightQualifier">
+      <td>Mode malam</td>
+      <td>
+        <code>night</code><br/>
+        <code>notnight</code>
+      </td>
+      <td>
+        <ul class="nolist">
+          <li>{@code night}: Waktu malam</li>
+          <li>{@code notnight}: Waktu siang</li>
+        </ul>
+        <p><em>Ditambahkan dalam API level 8.</em></p>
+        <p>Ini bisa berubah selama masa pakai aplikasi jika mode malam dibiarkan dalam
+mode otomatis (default), dalam hal ini perubahan mode berdasarkan pada waktu hari.  Anda dapat mengaktifkan
+atau menonaktifkan mode ini menggunakan {@link android.app.UiModeManager}. Lihat <a href="runtime-changes.html">Menangani Perubahan Runtime</a> untuk informasi tentang bagaimana hal ini memengaruhi
+aplikasi Anda selama runtime.</p>
+      </td>
+    </tr>
+    <tr id="DensityQualifier">
+      <td>Densitas piksel layar (dpi)</td>
+      <td>
+        <code>ldpi</code><br/>
+        <code>mdpi</code><br/>
+        <code>hdpi</code><br/>
+        <code>xhdpi</code><br/>
+        <code>xxhdpi</code><br/>
+        <code>xxxhdpi</code><br/>
+        <code>nodpi</code><br/>
+        <code>tvdpi</code>
+      </td>
+      <td>
+        <ul class="nolist">
+          <li>{@code ldpi}: Layar densitas rendah; sekitar 120 dpi.</li>
+          <li>{@code mdpi}: Layar densitas sedang (pada HVGA tradisional); sekitar 160 dpi.
+</li>
+          <li>{@code hdpi}: Layar densitas tinggi; sekitar 240 dpi.</li>
+          <li>{@code xhdpi}: Layar densitas ekstra tinggi; sekitar 320 dpi. <em>Ditambahkan dalam API
+Level 8.</em></li>
+          <li>{@code xxhdpi}: Layar densitas ekstra-ekstra-tinggi; sekitar 480 dpi. <em>Ditambahkan dalam API
+Level 16.</em></li>
+          <li>{@code xxxhdpi}: Densitas ekstra-ekstra-ekstra-tinggi (hanya ikon launcher,
+lihat <a href="{@docRoot}guide/practices/screens_support.html#xxxhdpi-note">catatan</a>
+ dalam <em>Mendukung Beberapa Layar</em>); sekitar 640 dpi. <em>Ditambahkan dalam API
+Level 18.</em></li>
+          <li>{@code nodpi}: Ini bisa digunakan untuk sumber daya bitmap yang tidak ingin Anda
+skalakan agar sama dengan densitas perangkat.</li>
+          <li>{@code tvdpi}: Layar antara mdpi dan hdpi; sekitar 213 dpi. Ini
+tidak dianggap sebagai kelompok densitas "utama". Sebagian besar ditujukan untuk televisi dan kebanyakan
+aplikasi tidak memerlukannya &mdash;asalkan sumber daya mdpi dan hdpi cukup untuk sebagian besar aplikasi dan
+sistem akan menskalakan sebagaimana mestinya. Qualifier ini diperkenalkan pada API level 13.</li>
+        </ul>
+        <p>Terdapat rasio skala 3:4:6:8:12:16 antara enam densitas utama (dengan mengabaikan densitas
+tvdpi). Jadi bitmap 9x9 di ldpi adalah 12x12 di mdpi, 18x18 di hdpi, 24x24 di xhdpi dan seterusnya.
+</p>
+        <p>Jika Anda memutuskan bahwa sumber daya gambar tidak terlihat cukup baik di televisi
+atau perangkat tertentu lainnya dan ingin mencoba sumber daya tvdpi, faktor skalanya adalah 1,33*mdpi. Misalnya,
+gambar 100px x 100px untuk layar mdpi harus 133px x 133px untuk tvdpi.</p>
+        <p class="note"><strong>Catatan:</strong> Menggunakan qualifier densitas tidak berarti bahwa
+sumber daya <em>hanya</em> untuk layar dengan ukuran itu saja. Jika Anda tidak menyediakan sumber
+daya alternatif dengan qualifier yang lebih cocok dengan konfigurasi perangkat saat ini, sistem dapat menggunakan sumber daya
+mana saja yang <a href="#BestMatch">paling cocok</a>.</p>
+        <p>Lihat <a href="{@docRoot}guide/practices/screens_support.html">Mendukung Beberapa
+Layar</a> untuk informasi selengkapnya tentang cara menangani densitas layar yang berbeda dan cara Android
+menurunkan skala bitmap Anda agar sesuai dengan densitas saat ini.</p>
+       </td>
+    </tr>
+    <tr id="TouchscreenQualifier">
+      <td>Tipe layar sentuh</td>
+      <td>
+        <code>notouch</code><br/>
+        <code>finger</code>
+      </td>
+      <td>
+        <ul class="nolist">
+          <li>{@code notouch}: Perangkat tidak memiliki layar sentuh.</li>
+          <li>{@code finger}: Perangkat memiliki layar sentuh yang dimaksudkan untuk
+digunakan melalui interaksi dengan jari pengguna.</li>
+        </ul>
+        <p>Lihat juga bidang konfigurasi {@link android.content.res.Configuration#touchscreen}, yang
+menunjukkan tipe layar sentuh pada perangkat.</p>
+      </td>
+    </tr>
+    <tr id="KeyboardAvailQualifier">
+      <td>Ketersediaan keyboard</td>
+      <td>
+        <code>keysexposed</code><br/>
+        <code>keyshidden</code><br/>
+        <code>keyssoft</code>
+      </td>
+      <td>
+        <ul class="nolist">
+          <li>{@code keysexposed}: Perangkat menyediakan keyboard. Jika perangkat mengaktifkan
+keyboard perangkat lunak (kemungkinan), ini dapat digunakan bahkan saat keyboard fisik
+<em>tidak</em> diekspos kepada pengguna, meskipun perangkat tidak memiliki keyboard fisik. Jika keyboard
+perangkat lunak tidak disediakan atau dinonaktifkan, maka ini hanya digunakan bila
+keyboard fisik diekspos.</li>
+          <li>{@code keyshidden}: Perangkat memiliki keyboard fisik yang tersedia
+tetapi tersembunyi <em>dan</em> perangkat <em>tidak</em> mengaktifkan keyboard perangkat lunak.</li>
+          <li>{@code keyssoft}: Perangkat mengaktifkan keyboard perangkat lunak,
+baik itu terlihat maupun tidak.</li>
+        </ul>
+        <p>Jika Anda menyediakan sumber daya <code>keysexposed</code>, namun bukan sumber daya <code>keyssoft</code>
+, sistem akan menggunakan sumber daya <code>keysexposed</code> baik keyboard
+terlihat atau tidak, asalkan sistem telah mengaktifkan keyboard perangkat lunak.</p>
+        <p>Ini bisa berubah selama masa pakai aplikasi jika pengguna membuka keyboard
+fisik. Lihat <a href="runtime-changes.html">Menangani Perubahan Runtime</a> untuk informasi tentang bagaimana
+hal ini memengaruhi aplikasi Anda selama runtime.</p>
+        <p>Lihat juga bidang konfigurasi {@link
+android.content.res.Configuration#hardKeyboardHidden} dan {@link
+android.content.res.Configuration#keyboardHidden}, yang menunjukkan visibilitas
+keyboard fisik dan visibilitas segala jenis keyboard (termasuk keyboard perangkat lunak), masing-masing.</p>
+      </td>
+    </tr>
+    <tr id="ImeQualifier">
+      <td>Metode input teks utama</td>
+      <td>
+        <code>nokeys</code><br/>
+        <code>qwerty</code><br/>
+        <code>12key</code>
+      </td>
+      <td>
+        <ul class="nolist">
+          <li>{@code nokeys}: Perangkat tidak memiliki tombol fisik untuk input teks.</li>
+          <li>{@code qwerty}: Perangkat memiliki keyboard fisik qwerty, baik terlihat maupun tidak pada
+pengguna
+.</li>
+          <li>{@code 12key}: Perangkat memiliki keyboard fisik 12 tombol, baik terlihat maupun tidak
+pada pengguna.</li>
+        </ul>
+        <p>Lihat juga bidang konfigurasi {@link android.content.res.Configuration#keyboard},
+yang menunjukkan metode utama input teks yang tersedia.</p>
+      </td>
+    </tr>
+    <tr id="NavAvailQualifier">
+      <td>Ketersediaan tombol navigasi</td>
+      <td>
+        <code>navexposed</code><br/>
+        <code>navhidden</code>
+      </td>
+      <td>
+        <ul class="nolist">
+          <li>{@code navexposed}: Tombol navigasi tersedia bagi pengguna.</li>
+          <li>{@code navhidden}: Tombol navigasi tidak tersedia (misalnya di balik penutup yang
+ditutup).</li>
+        </ul>
+        <p>Ini bisa berubah selama masa pakai aplikasi jika pengguna menyingkap tombol
+navigasi. Lihat <a href="runtime-changes.html">Menangani Perubahan Runtime</a> untuk
+informasi tentang bagaimana hal ini memengaruhi aplikasi Anda selama runtime.</p>
+        <p>Lihat juga bidang konfigurasi {@link android.content.res.Configuration#navigationHidden}, yang menunjukkan
+apakah tombol navigasi disembunyikan.</p>
+      </td>
+    </tr>
+    <tr id="NavigationQualifier">
+      <td>Metode navigasi non-sentuh utama</td>
+      <td>
+        <code>nonav</code><br/>
+        <code>dpad</code><br/>
+        <code>trackball</code><br/>
+        <code>wheel</code>
+      </td>
+      <td>
+        <ul class="nolist">
+          <li>{@code nonav}: Perangkat tidak memiliki fasilitas navigasi selain menggunakan
+layar sentuh.</li>
+          <li>{@code dpad}: Perangkat memiliki pad pengarah (directional pad / d-pad) untuk navigasi.</li>
+          <li>{@code trackball}: Perangkat memiliki trackball untuk navigasi.</li>
+          <li>{@code wheel}: Perangkat memiliki roda pengarah (directional wheel) untuk navigasi (tidak umum).</li>
+        </ul>
+        <p>Lihat juga bidang konfigurasi {@link android.content.res.Configuration#navigation},
+yang menunjukkan tipe metode navigasi yang tersedia.</p>
+      </td>
+    </tr>
+<!-- DEPRECATED
+    <tr>
+      <td>Screen dimensions</td>
+      <td>Examples:<br/>
+        <code>320x240</code><br/>
+        <code>640x480</code><br/>
+        etc.
+      </td>
+      <td>
+        <p>The larger dimension must be specified first. <strong>This configuration is deprecated
+and should not be used</strong>. Instead use "screen size," "wider/taller screens," and "screen
+orientation" described above.</p>
+      </td>
+    </tr>
+-->
+    <tr id="VersionQualifier">
+      <td>Versi Platform (level API)</td>
+      <td>Contoh:<br/>
+        <code>v3</code><br/>
+        <code>v4</code><br/>
+        <code>v7</code><br/>
+        dll.</td>
+      <td>
+        <p>Level API yang didukung perangkat. Misalnya, <code>v1</code> untuk API level
+1 (perangkat dengan Android 1.0 atau yang lebih tinggi) dan <code>v4</code> untuk API level 4 (perangkat dengan Android
+1.6 atau yang lebih tinggi). Lihat dokumen <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">Level API Android</a> untuk informasi selengkapnya
+tentang nilai-nilai ini.</p>
+      </td>
+    </tr>
+</table>
+
+
+<p class="note"><strong>Catatan:</strong> Sebagian qualifier konfigurasi telah ditambahkan sejak Android
+1.0, jadi tidak semua versi Android mendukung semua qualifier. Menggunakan qualifier baru secara implisit
+akan menambahkan qualifier versi platform sehingga perangkat yang lebih lama pasti mengabaikannya. Misalnya, menggunakan qualifier
+<code>w600dp</code> secara otomatis akan menyertakan qualifier <code>v13</code>, karena
+qualifier lebar yang tersedia baru di API level 13. Untuk menghindari masalah, selalu sertakan satu set
+sumber daya default (satu set sumber daya <em>tanpa qualifier</em>). Untuk informasi selengkapnya, lihat
+bagian tentang <a href="#Compatibility">Menyediakan Kompatibilitas Perangkat Terbaik dengan
+Sumber Daya</a>.</p>
+
+
+
+<h3 id="QualifierRules">Aturan penamaan qualifier</h3>
+
+<p>Inilah beberapa aturan tentang penggunaan nama qualifier konfigurasi:</p>
+
+<ul>
+    <li>Anda bisa menetapkan beberapa qualifier untuk satu set sumber daya, yang dipisahkan dengan tanda hubung. Misalnya,
+<code>drawable-en-rUS-land</code> berlaku untuk perangkat bahasa Inggris-AS dalam orientasi
+lanskap.</li>
+    <li>Qualifier harus dalam urutan seperti yang tercantum dalam <a href="#table2">tabel 2</a>.
+Misalnya:
+      <ul>
+        <li>Salah: <code>drawable-hdpi-port/</code></li>
+        <li>Benar: <code>drawable-port-hdpi/</code></li>
+      </ul>
+    </li>
+    <li>Direktori sumber daya alternatif tidak bisa digunakan. Misalnya, Anda tidak bisa memiliki
+<code>res/drawable/drawable-en/</code>.</li>
+    <li>Nilai tidak membedakan huruf besar maupun kecil.  Compiler sumber daya mengubah nama direktori
+menjadi huruf kecil sebelum pemrosesan untuk menghindari masalah pada sistem file yang membedakan
+huruf kecil dan besar. Setiap penggunaan huruf besar dalam nama hanyalah demi keterbacaan.</li>
+    <li>Hanya didukung satu nilai untuk setiap tipe qualifier. Misalnya, jika Anda ingin menggunakan
+file drawable yang sama untuk Spanyol dan Prancis, Anda <em>tidak bisa</em> memiliki direktori bernama
+<code>drawable-rES-rFR/</code>. Sebagai gantinya, Anda perlu dua direktori sumber daya, seperti
+<code>drawable-rES/</code> dan <code>drawable-rFR/</code>, berisi file yang sesuai.
+Akan tetapi, Anda tidak harus benar-benar menggandakan file yang sama di kedua lokasi. Sebagai gantinya, Anda
+bisa membuat alias ke satu sumber daya. Lihat <a href="#AliasResources">Membuat
+sumber daya alias</a> di bawah ini.</li>
+</ul>
+
+<p>Setelah Anda menyimpan sumber daya alternatif ke dalam direktori yang diberi nama dengan
+qualifier ini, Android secara otomatis menerapkan sumber daya dalam
+aplikasi Anda berdasarkan pada konfigurasi perangkat saat ini. Setiap kali sumber daya diminta, Android akan memeriksa direktori sumber daya
+alternatif berisi file sumber daya yang diminta, lalu <a href="#BestMatch">mencari sumber daya yang
+paling cocok</a>(dibahas di bawah). Jika tidak ada sumber daya alternatif yang cocok
+dengan konfigurasi perangkat tertentu, Android akan menggunakan sumber daya default terkait (set
+sumber daya untuk tipe sumber daya tertentu yang tidak termasuk qualifier
+konfigurasi).</p>
+
+
+
+<h3 id="AliasResources">Membuat sumber daya alias</h3>
+
+<p>Bila memiliki sumber daya yang ingin Anda gunakan untuk lebih dari satu konfigurasi
+perangkat (namun tidak ingin menyediakannya sebagai sumber daya default), Anda tidak perlu menempatkan sumber daya
+yang sama di lebih dari satu direktori sumber daya alternatif. Sebagai gantinya, (dalam beberapa kasus) Anda bisa membuat
+sumber daya alternatif
+yang berfungsi sebagai alias untuk sumber daya yang disimpan dalam direktori sumber daya default.</p>
+
+<p class="note"><strong>Catatan:</strong> Tidak semua sumber daya menawarkan mekanisme yang memungkinkan Anda
+membuat alias ke sumber daya lain. Khususnya, animasi, menu, raw, dan
+sumber daya lain yang tidak ditetapkan dalam direktori {@code xml/} tidak menawarkan fitur ini.</p>
+
+<p>Misalnya, bayangkan Anda memiliki ikon aplikasi {@code icon.png}, dan membutuhkan versi uniknya
+untuk lokal berbeda. Akan tetapi, dua lokal, bahasa Inggris-Kanada dan bahasa Prancis-Kanada, harus menggunakan
+versi yang sama. Anda mungkin berasumsi bahwa Anda perlu menyalin gambar
+yang sama ke dalam direktori sumber daya baik untuk bahasa Inggris-Kanada maupun bahasa Prancis-Kanada, namun
+bukan demikian. Sebagai gantinya, Anda bisa menyimpan gambar yang sama-sama digunakan sebagai {@code icon_ca.png} (nama
+apa saja selain {@code icon.png}) dan memasukkannya
+dalam direktori default {@code res/drawable/}. Lalu buat file {@code icon.xml} dalam {@code
+res/drawable-en-rCA/} dan {@code res/drawable-fr-rCA/} yang mengacu ke sumber daya {@code icon_ca.png}
+yang menggunakan elemen {@code &lt;bitmap&gt;}. Hal ini memungkinkan Anda menyimpan satu versi saja dari
+file PNG dan dua file XML kecil yang menunjuk ke sana. (Contoh file XML ditampilkan di bawah.)</p>
+
+
+<h4>Drawable</h4>
+
+<p>Untuk membuat alias ke drawable yang ada, gunakan elemen {@code &lt;bitmap&gt;}.
+Misalnya:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/icon_ca" />
+</pre>
+
+<p>Jika Anda menyimpan file ini sebagai {@code icon.xml} (dalam direktori sumber daya alternatif, seperti
+{@code res/drawable-en-rCA/}), maka file akan dikompilasi menjadi sumber daya yang dapat Anda acu
+sebagai {@code R.drawable.icon}, namun sebenarnya merupakan alias untuk sumber daya {@code
+R.drawable.icon_ca} (yang disimpan dalam {@code res/drawable/}).</p>
+
+
+<h4>Layout</h4>
+
+<p>Untuk membuat alias ke layout yang ada, gunakan elemen {@code &lt;include&gt;},
+yang dibungkus dalam {@code &lt;merge&gt;}. Misalnya:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;merge>
+    &lt;include layout="@layout/main_ltr"/>
+&lt;/merge>
+</pre>
+
+<p>Jika Anda menyimpan file ini sebagai {@code main.xml}, file akan dikompilasi menjadi sumber daya yang dapat Anda acu
+sebagai {@code R.layout.main}, namun sebenarnya merupakan alias untuk sumber daya {@code R.layout.main_ltr}
+.</p>
+
+
+<h4>String dan nilai-nilai sederhana lainnya</h4>
+
+<p>Untuk membuat alias ke string yang ada, cukup gunakan ID sumber daya
+dari string yang diinginkan sebagai nilai untuk string baru. Misalnya:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;resources>
+    &lt;string name="hello">Hello&lt;/string>
+    &lt;string name="hi">@string/hello&lt;/string>
+&lt;/resources>
+</pre>
+
+<p>Sumber daya {@code R.string.hi} sekarang merupakan alias untuk {@code R.string.hello}.</p>
+
+<p> <a href="{@docRoot}guide/topics/resources/more-resources.html">Nilai sederhana lainnya</a> sama
+cara kerjanya. Misalnya, sebuah warna:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;resources>
+    &lt;color name="yellow">#f00&lt;/color>
+    &lt;color name="highlight">@color/red&lt;/color>
+&lt;/resources>
+</pre>
+
+
+
+
+<h2 id="Compatibility">Menyediakan Kompatibilitas Perangkat Terbaik dengan Sumber Daya</h2>
+
+<p>Agar aplikasi Anda mendukung beberapa konfigurasi perangkat,
+Anda harus selalu menyediakan sumber daya default untuk setiap tipe sumber daya yang menggunakan aplikasi Anda.</p>
+
+<p>Misalnya, jika aplikasi Anda mendukung beberapa bahasa, sertakan selalu direktori {@code
+values/} (tempat string Anda disimpan) <em>tanpa</em> <a href="#LocaleQualifier">qualifier bahasa dan wilayah</a>. Jika sebaliknya Anda menempatkan semua file
+string dalam direktori yang memiliki qualifier bahasa dan wilayah, maka aplikasi Anda akan crash saat berjalan
+pada perangkat yang telah diatur ke bahasa yang tidak didukung string Anda. Namun asalkan Anda menyediakan sumber daya default
+{@code values/}, aplikasi akan berjalan lancar (meskipun pengguna
+tidak memahami bahasa itu&mdash;, ini lebih baik daripada crash).</p>
+
+<p>Demikian pula, jika Anda menyediakan sumber daya layout berbeda berdasarkan orientasi layar, Anda harus
+memilih satu orientasi sebagai default. Misalnya, sebagai ganti menyediakan sumber daya dalam {@code
+layout-land/} untuk lanskap dan {@code layout-port/} untuk potret, biarkan salah satu sebagai default, seperti
+{@code layout/} untuk lanskap dan {@code layout-port/} untuk potret.</p>
+
+<p>Sumber daya default perlu disediakan bukan hanya karena aplikasi mungkin berjalan pada
+konfigurasi yang belum Anda antisipasi, namun juga karena versi baru Android terkadang menambahkan
+qualifier konfigurasi yang tidak didukung oleh versi lama. Jika Anda menggunakan qualifier sumber daya baru,
+namun mempertahankan kompatibilitas kode dengan versi Android yang lebih lama, maka saat versi lama
+Android menjalankan aplikasi, aplikasi itu akan crash jika Anda tidak menyediakan sumber daya default, aplikasi
+tidak bisa menggunakan sumber daya yang dinamai dengan qualifier baru. Misalnya, jika <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+minSdkVersion}</a> Anda diatur ke 4, dan Anda memenuhi syarat semua sumber daya drawable dengan menggunakan <a href="#NightQualifier">mode malam</a> ({@code night} atau {@code notnight}, yang ditambahkan di API
+Level 8), maka perangkat API level 4 tidak bisa mengakses sumber daya drawable dan akan crash. Dalam hal
+ini, Anda mungkin ingin {@code notnight} menjadi sumber daya default, jadi Anda harus mengecualikan
+qualifier itu agar sumber daya drawable Anda ada dalam {@code drawable/} atau {@code drawable-night/}.</p>
+
+<p>Jadi, agar bisa menyediakan kompatibilitas perangkat terbaik, sediakan selalu sumber daya
+default untuk sumber daya yang diperlukan aplikasi Anda untuk berjalan dengan benar. Selanjutnya buatlah sumber daya
+alternatif untuk konfigurasi perangkat tertentu dengan menggunakan qualifier konfigurasi.</p>
+
+<p>Ada satu eksepsi untuk aturan ini: Jika <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> aplikasi Anda adalah 4 atau
+lebih, Anda <em>tidak</em> memerlukan sumber daya drawable default saat menyediakan sumber daya
+drawable alternatif dengan qualifier <a href="#DensityQualifier">densitas layar</a>. Tanpa sumber daya
+drawable default sekali pun, Android bisa menemukan yang paling cocok di antara densitas layar alternatif dan menskalakan
+bitmap sesuai kebutuhan. Akan tetapi, demi pengalaman terbaik pada semua jenis perangkat, Anda harus
+menyediakan drawable alternatif untuk ketiga tipe densitas.</p>
+
+
+
+<h2 id="BestMatch">Cara Android Menemukan Sumber Daya yang Paling Cocok</h2>
+
+<p>Saat Anda meminta sumber daya yang Anda berikan alternatifnya, Android akan memilih
+sumber daya alternatif yang akan digunakan saat runtime, bergantung pada konfigurasi perangkat saat ini. Untuk
+mendemonstrasikan cara Android memilih sumber daya alternatif, anggaplah direktori drawable berikut
+masing-masing berisi versi berbeda dari gambar yang sama:</p>
+
+<pre class="classic no-pretty-print">
+drawable/
+drawable-en/
+drawable-fr-rCA/
+drawable-en-port/
+drawable-en-notouch-12key/
+drawable-port-ldpi/
+drawable-port-notouch-12key/
+</pre>
+
+<p>Dan anggaplah yang berikut ini merupakan konfigurasi perangkatnya:</p>
+
+<p style="margin-left:1em;">
+Lokal = <code>en-GB</code> <br/>
+Orientasi layar = <code>port</code> <br/>
+Densitas piksel layar = <code>hdpi</code> <br/>
+Tipe layar sentuh = <code>notouch</code> <br/>
+Metode input teks utama = <code>12key</code>
+</p>
+
+<p>Dengan membandingkan konfigurasi perangkat dengan sumber daya alternatif yang tersedia, Android akan memilih
+drawable dari {@code drawable-en-port}.</p>
+
+<p>Sistem akan menentukan keputusannya mengenai sumber daya yang akan digunakan dengan logika
+berikut:</p>
+
+
+<div class="figure" style="width:371px">
+<img src="{@docRoot}images/resources/res-selection-flowchart.png" alt="" height="471" />
+<p class="img-caption"><strong>Gambar 2.</strong> Bagan alur cara Android menemukan
+sumber daya yang paling cocok.</p>
+</div>
+
+
+<ol>
+  <li>Menghapus file sumber daya yang bertentangan dengan konfigurasi perangkat.
+    <p>Direktori <code>drawable-fr-rCA/</code> dihapus karena bertentangan
+dengan lokal <code>en-GB</code>.</p>
+<pre class="classic no-pretty-print">
+drawable/
+drawable-en/
+<strike>drawable-fr-rCA/</strike>
+drawable-en-port/
+drawable-en-notouch-12key/
+drawable-port-ldpi/
+drawable-port-notouch-12key/
+</pre>
+<p class="note"><strong>Eksepsi:</strong> Densitas piksel layar adalah satu qualifier yang
+tidak dihapus karena bertentangan. Meskipun densitas layar perangkat adalah hdpi,
+<code>drawable-port-ldpi/</code> tidak dihapus karena setiap densitas layar
+dianggap cocok untuk saat ini. Informasi selengkapnya tersedia dalam dokumen <a href="{@docRoot}guide/practices/screens_support.html">Mendukung Beberapa
+Layar</a>.</p></li>
+
+  <li>Pilih qualifier berkedudukan tertinggi (berikutnya) dalam daftar (<a href="#table2">tabel 2</a>).
+(Mulai dengan MCC, lalu pindah ke bawah.) </li>
+  <li>Apakah salah satu direktori sumber daya menyertakan qualifier ini?  </li>
+    <ul>
+      <li>Jika Tidak, kembali ke langkah 2 dan lihat qualifier berikutnya. (Dalam contoh,
+jawabannya adalah "tidak" hingga qualifier bahasa tercapai.)</li>
+      <li>Jika Ya, lanjutkan ke langkah 4.</li>
+    </ul>
+  </li>
+
+  <li>Hapus direktori sumber daya yang tidak menyertakan qualifier ini. Dalam contoh, sistem
+menghapus semua direktori yang tidak menyertakan qualifier bahasa:</li>
+<pre class="classic no-pretty-print">
+<strike>drawable/</strike>
+drawable-en/
+drawable-en-port/
+drawable-en-notouch-12key/
+<strike>drawable-port-ldpi/</strike>
+<strike>drawable-port-notouch-12key/</strike>
+</pre>
+<p class="note"><strong>Eksepsi:</strong> Jika qualifier yang dimaksud adalah densitas piksel layar,
+Android akan memilih opsi yang paling cocok dengan densitas layar perangkat.
+Secara umum, Android lebih suka menurunkan skala gambar asli yang lebih besar daripada menaikkan skala
+atas gambar asli yang lebih kecil. Lihat <a href="{@docRoot}guide/practices/screens_support.html">Mendukung Beberapa
+Layar</a>.</p>
+  </li>
+
+  <li>Kembali dan ulangi langkah 2, 3, dan 4 hingga tersisa satu direktori. Dalam contoh ini, orientasi
+layar adalah qualifier berikutnya yang memiliki kecocokan.
+Jadi, sumber daya yang tidak menetapkan orientasi layar akan dihapus:
+<pre class="classic no-pretty-print">
+<strike>drawable-en/</strike>
+drawable-en-port/
+<strike>drawable-en-notouch-12key/</strike>
+</pre>
+<p>Direktori yang tersisa adalah {@code drawable-en-port}.</p>
+  </li>
+</ol>
+
+<p>Meskipun prosedur dijalankan untuk setiap sumber daya yang diminta, sistem akan mengoptimalkan beberapa aspek
+lebih lanjut. Satu optimalisasi tersebut adalah bahwa setelah konfigurasi perangkat diketahui, sistem mungkin
+akan menghapus sumber daya alternatif yang sama sekali tidak cocok. Misalnya, jika bahasa konfigurasi
+adalah bahasa Inggris ("en"), maka setiap direktori sumber daya yang memiliki qualifier bahasa akan diatur ke
+selain bahasa Inggris tidak akan pernah disertakan dalam pool sumber daya yang diperiksa (meskipun
+direktori sumber daya <em>tanpa</em> qualifier bahasa masih disertakan).</p>
+
+<p>Saat memilih sumber daya berdasarkan qualifier ukuran layar, sistem akan menggunakan
+sumber daya yang didesain untuk layar yang lebih kecil daripada layar saat ini jika tidak ada sumber daya yang lebih cocok
+(misalnya, layar ukuran besar akan menggunakan sumber daya layar ukuran normal jika diperlukan). Akan tetapi,
+jika satu-satunya sumber daya yang tersedia <em>lebih besar</em> daripada layar saat ini, sistem
+<strong>tidak</strong> akan menggunakannya dan aplikasi Anda akan crash jika tidak ada sumber daya lain yang cocok dengan konfigurasi
+perangkat (misalnya, jika semua sumber daya layout ditandai dengan qualifier {@code xlarge},
+namun perangkat memiliki ukuran layar normal).</p>
+
+<p class="note"><strong>Catatan:</strong> <em>Kedudukan</em> qualifier (dalam <a href="#table2">tabel 2</a>) lebih penting
+daripada jumlah qualifier yang benar-benar pas dengan perangkat. Misalnya, dalam langkah 4 di atas, pilihan
+terakhir pada daftar berisi tiga qualifier yang bebar-benar cocok dengan perangkat (orientasi, tipe
+layar sentuh, dan metode input), sementara <code>drawable-en</code> hanya memiliki satu parameter yang cocok
+(bahasa). Akan tetapi, bahasa memiliki kedudukan lebih tinggi dari pada qualifier lainnya, sehingga
+<code>drawable-port-notouch-12key</code> tidak masuk.</p>
+
+<p>Untuk mengetahui selengkapnya tentang cara menggunakan sumber daya dalam aplikasi, lanjutkan ke <a href="accessing-resources.html">Mengakses Sumber Daya</a>.</p>
diff --git a/docs/html-intl/intl/id/guide/topics/resources/runtime-changes.jd b/docs/html-intl/intl/id/guide/topics/resources/runtime-changes.jd
new file mode 100644
index 0000000..09ad60c
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/resources/runtime-changes.jd
@@ -0,0 +1,281 @@
+page.title=Menangani Perubahan Runtime
+page.tags=aktivitas,daur hidup
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+  <h2>Dalam dokumen ini</h2>
+  <ol>
+    <li><a href="#RetainingAnObject">Mempertahankan Objek Selama Perubahan Konfigurasi</a></li>
+    <li><a href="#HandlingTheChange">Menangani Sendiri Perubahan Konfigurasi</a>
+  </ol>
+
+  <h2>Lihat juga</h2>
+  <ol>
+    <li><a href="providing-resources.html">Menyediakan Sumber Daya</a></li>
+    <li><a href="accessing-resources.html">Mengakses Sumber Daya</a></li>
+    <li><a href="http://android-developers.blogspot.com/2009/02/faster-screen-orientation-change.html">Perubahan
+ Orientasi Layar yang Lebih Cepat</a></li>
+  </ol>
+</div>
+</div>
+
+<p>Sebagian konfigurasi perangkat bisa berubah selama runtime
+(seperti orientasi layar, ketersediaan keyboard, dan bahasa). Saat perubahan demikian terjadi,
+Android akan me-restart
+{@link android.app.Activity} yang berjalan ({@link android.app.Activity#onDestroy()} dipanggil, diikuti oleh {@link
+android.app.Activity#onCreate(Bundle) onCreate()}). Perilaku restart didesain untuk membantu
+aplikasi Anda beradaptasi dengan konfigurasi baru melalui pemuatan kembali aplikasi Anda secara otomatis dengan
+sumber daya alternatif sumber yang sesuai dengan konfigurasi perangkat baru.</p>
+
+<p>Untuk menangani restart dengan benar, aktivitas Anda harus mengembalikan
+statusnya seperti semula melalui <a href="{@docRoot}guide/components/activities.html#Lifecycle">Daur hidup
+aktivitas</a> normal, dalam hal ini Android akan memanggil
+{@link android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()} sebelum menghentikan
+aktivitas Anda sehingga Anda dapat menyimpan data mengenai status aplikasi. Selanjutnya Anda bisa mengembalikan status
+selama {@link android.app.Activity#onCreate(Bundle) onCreate()} atau {@link
+android.app.Activity#onRestoreInstanceState(Bundle) onRestoreInstanceState()}.</p>
+
+<p>Untuk menguji bahwa aplikasi me-restart sendiri dengan status tak berubah, Anda harus
+memanggil perubahan konfigurasi (seperti mengubah orientasi layar) saat melakukan berbagai
+tugas dalam aplikasi. Aplikasi Anda harus dapat me-restart setiap saat tanpa kehilangan
+data pengguna atau status untuk menangani kejadian seperti perubahan konfigurasi atau bila pengguna menerima panggilan telepon
+masuk lalu kembali ke aplikasi setelah proses
+aplikasi Anda dimusnahkan. Untuk mengetahui cara mengembalikan status aktivitas, bacalah tentang <a href="{@docRoot}guide/components/activities.html#Lifecycle">Daur hidup aktivitas</a>.</p>
+
+<p>Akan tetapi, Anda mungkin menemui situasi ketika me-restart aplikasi dan
+mengembalikan data dalam jumlah besar malah menjadi mahal dan menghasilkan pengalaman pengguna yang buruk. Dalam situasi
+demikian, Anda memiliki dua opsi lain:</p>
+
+<ol type="a">
+  <li><a href="#RetainingAnObject">Mempertahankan objek selama perubahan konfigurasi</a>
+  <p>Izinkan aktivitas Anda me-restart saat konfigurasi berubah, namun bawa objek
+berstatus (stateful) ke instance baru aktivitas Anda.</p>
+
+  </li>
+  <li><a href="#HandlingTheChange">Menangani sendiri perubahan konfigurasi</a>
+  <p>Cegah sistem me-restart aktivitas selama perubahan konfigurasi
+tertentu, namun terima callback saat konfigurasi benar-benar berubah, agar Anda bisa memperbarui
+aktivitas secara manual bila diperlukan.</p>
+  </li>
+</ol>
+
+
+<h2 id="RetainingAnObject">Mempertahankan Objek Selama Perubahan Konfigurasi</h2>
+
+<p>Jika me-restart aktivitas mengharuskan pemulihan seperangkat data dalam jumlah besar, menghubungkan kembali koneksi
+jaringan, atau melakukan operasi intensif lainnya, maka restart penuh karena perubahan konfigurasi mungkin
+menjadi pengalaman pengguna yang lambat. Selain itu, Anda mungkin tidak bisa sepenuhnya mengembalikan status
+aktivitas dengan {@link android.os.Bundle} yang disimpan sistem untuk Anda dengan callback {@link
+android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()}&mdash;itu tidaklah
+didesain untuk membawa objek besar (seperti bitmap) dan data di dalamnya harus diserialkan kemudian
+dinon-serialkan, yang bisa menghabiskan banyak memori dan membuat perubahan konfigurasi menjadi lambat. Dalam situasi
+demikian, Anda bisa meringankan beban memulai kembali aktivitas Anda dengan mempertahankan {@link
+android.app.Fragment} saat aktivitas Anda di-restart karena perubahan konfigurasi. Fragmen ini
+bisa berisi acuan ke objek stateful yang ingin Anda pertahankan.</p>
+
+<p>Bila sistem Android menghentikan aktivitas Anda karena perubahan konfigurasi, fragmen
+aktivitas yang telah ditandai untuk dipertahankan tidak akan dimusnahkan. Anda dapat menambahkan fragmen tersebut ke
+aktivitas untuk mempertahankan objek stateful.</p>
+
+<p>Untuk mempertahankan objek stateful dalam fragmen selama perubahan konfigurasi runtime:</p>
+
+<ol>
+  <li>Perluas kelas {@link android.app.Fragment} dan deklarasikan referensi ke objek stateful
+Anda.</li>
+  <li>Panggil {@link android.app.Fragment#setRetainInstance(boolean)} saat fragmen dibuat.
+      </li>
+  <li>Tambahkan fragmen ke aktivitas.</li>
+  <li>Gunakan {@link android.app.FragmentManager} untuk mengambil fragmen saat aktivitas
+di-restart.</li>
+</ol>
+
+<p>Misalnya, definisikan fragmen sebagai berikut:</p>
+
+<pre>
+public class RetainedFragment extends Fragment {
+
+    // data object we want to retain
+    private MyDataObject data;
+
+    // this method is only called once for this fragment
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        // retain this fragment
+        setRetainInstance(true);
+    }
+
+    public void setData(MyDataObject data) {
+        this.data = data;
+    }
+
+    public MyDataObject getData() {
+        return data;
+    }
+}
+</pre>
+
+<p class="caution"><strong>Perhatian:</strong> Meskipun bisa menyimpan objek apa saja, Anda
+sama sekali tidak boleh meneruskan objek yang terkait dengan {@link android.app.Activity}, seperti {@link
+android.graphics.drawable.Drawable}, {@link android.widget.Adapter}, {@link android.view.View}
+atau objek lainnya mana pun yang terkait dengan {@link android.content.Context}. Jika Anda melakukannya, hal tersebut akan
+membocorkan semua tampilan dan sumber daya instance aktivitas semula. (Sumber daya yang bocor
+berarti bahwa aplikasi Anda tetap menyimpannya dan tidak bisa dijadikan kumpulan sampah, sehingga bisa banyak
+memori yang hilang.)</p>
+
+<p>Selanjutnya gunakan {@link android.app.FragmentManager} untuk menambahkan fragmen ke aktivitas.
+Anda bisa memperoleh objek data dari fragmen saat aktivitas memulai kembali selama perubahan
+konfigurasi runtime. Misalnya, definisikan aktivitas Anda sebagai berikut:</p>
+
+<pre>
+public class MyActivity extends Activity {
+
+    private RetainedFragment dataFragment;
+
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        // find the retained fragment on activity restarts
+        FragmentManager fm = getFragmentManager();
+        dataFragment = (DataFragment) fm.findFragmentByTag(“data”);
+
+        // create the fragment and data the first time
+        if (dataFragment == null) {
+            // add the fragment
+            dataFragment = new DataFragment();
+            fm.beginTransaction().add(dataFragment, “data”).commit();
+            // load the data from the web
+            dataFragment.setData(loadMyData());
+        }
+
+        // the data is available in dataFragment.getData()
+        ...
+    }
+
+    &#64;Override
+    public void onDestroy() {
+        super.onDestroy();
+        // store the data in the fragment
+        dataFragment.setData(collectMyLoadedData());
+    }
+}
+</pre>
+
+<p>Dalam contoh ini, {@link android.app.Activity#onCreate(Bundle) onCreate()} menambahkan fragmen
+atau mengembalikan referensinya. {@link android.app.Activity#onCreate(Bundle) onCreate()} juga
+menyimpan objek stateful dalam instance fragmen.
+{@link android.app.Activity#onDestroy() onDestroy()} akan memperbarui objek stateful dalam
+instance fragmen yang dipertahankan.</p>
+
+
+
+
+
+<h2 id="HandlingTheChange">Menangani Sendiri Perubahan Konfigurasi</h2>
+
+<p>Jika aplikasi Anda tidak memerlukan pembaruan sumber daya selama perubahan konfigurasi
+tertentu <em>dan</em> Anda memiliki keterbatasan kinerja yang mengharuskan Anda untuk
+menghindari restart aktivitas, maka Anda bisa mendeklarasikan agar aktivitas Anda menangani sendiri perubahan
+konfigurasinya, sehingga mencegah sistem me-restart aktivitas.</p>
+
+<p class="note"><strong>Catatan:</strong> Menangani sendiri perubahan konfigurasi bisa jauh lebih
+mempersulit penggunaan sumber daya alternatif, karena sistem tidak menerapkannya secara otomatis
+untuk Anda. Teknik ini harus dianggap sebagai usaha terakhir bila Anda harus menghindari restart
+karena perubahan konfigurasi dan tidak disarankan untuk sebagian besar aplikasi.</p>
+
+<p>Untuk mendeklarasikan agar aktivitas Anda menangani perubahan konfigurasi, edit elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a> yang sesuai
+dalam file manifes Anda agar menyertakan atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
+android:configChanges}</a> dengan nilai yang mewakili konfigurasi yang ingin
+ditangani. Nilai yang memungkinkan tercantum dalam dokumentasi untuk atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
+android:configChanges}</a> (nilai paling sering digunakan adalah {@code "orientation"} untuk
+mencegah restart saat orientasi layar berubah dan {@code "keyboardHidden"} untuk mencegah
+restart saat ketersediaan keyboard berubah).  Anda dapat mendeklarasikan beberapa nilai konfigurasi
+dalam atribut dengan memisahkannya menggunakan karakter pipa {@code |}.</p>
+
+<p>Misalnya, kode manifes berikut menyatakan aktivitas yang menangani
+perubahan orientasi layar maupun perubahan ketersediaan keyboard:</p>
+
+<pre>
+&lt;activity android:name=".MyActivity"
+          android:configChanges="orientation|keyboardHidden"
+          android:label="@string/app_name">
+</pre>
+
+<p>Sekarang, bila salah satu konfigurasi ini berubah, {@code MyActivity} tidak akan me-restart.
+Sebagai gantinya, {@code MyActivity} akan menerima panggilan ke {@link
+android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. Metode ini
+meneruskan objek {@link android.content.res.Configuration} yang menetapkan
+konfigurasi perangkat baru. Dengan membaca bidang-bidang dalam {@link android.content.res.Configuration},
+Anda dapat menentukan konfigurasi baru dan membuat perubahan yang sesuai dengan memperbarui
+sumber daya yang digunakan dalam antarmuka. Pada saat
+metode ini dipanggil, objek {@link android.content.res.Resources} aktivitas Anda akan diperbarui untuk
+mengembalikan sumber daya berdasarkan konfigurasi baru, jadi Anda bisa dengan mudah
+me-reset elemen UI tanpa membuat sistem me-restart aktivitas Anda.</p>
+
+<p class="caution"><strong>Perhatian:</strong> Mulai Android 3.2 (API level 13), <strong>
+"ukuran layar" juga berubah</strong> bila perangkat beralih orientasi antara potret
+dan lanskap. Jadi jika Anda tidak ingin runtime di-restart karena perubahan orientasi saat mengembangkan
+API level 13 atau yang lebih tinggi (sebagaimana dideklarasikan oleh atribut <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> dan <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a>
+), Anda harus menyertakan nilai {@code "screenSize"} selain nilai {@code
+"orientation"}. Yaitu Anda harus mendeklarasikan {@code
+android:configChanges="orientation|screenSize"}. Akan tetapi, jika aplikasi Anda menargetkan API level
+12 atau yang lebih rendah, maka aktivitas Anda akan selalu menangani sendiri perubahan konfigurasi ini (perubahan
+konfigurasi ini tidak me-restart aktivitas Anda, bahkan saat berjalan pada perangkat Android 3.2 atau yang lebih tinggi).</p>
+
+<p>Misalnya, implementasi {@link
+android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()} berikut akan
+memeriksa orientasi perangkat saat ini:</p>
+
+<pre>
+&#64;Override
+public void onConfigurationChanged(Configuration newConfig) {
+    super.onConfigurationChanged(newConfig);
+
+    // Checks the orientation of the screen
+    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
+    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
+        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
+    }
+}
+</pre>
+
+<p>Objek {@link android.content.res.Configuration} mewakili semua konfigurasi
+saat ini, tidak hanya konfigurasi yang telah berubah. Seringkali Anda tidak perlu memperhatikan dengan persis bagaimana
+konfigurasi berubah dan cukup menetapkan kembali semua sumber daya yang memberikan alternatif untuk
+konfigurasi sedang ditangani. Misalnya, karena objek {@link
+android.content.res.Resources} sekarang diperbarui, Anda dapat me-reset
+setiap {@link android.widget.ImageView} dengan {@link android.widget.ImageView#setImageResource(int)
+setImageResource()}
+dan sumber daya yang sesuai untuk konfigurasi baru yang digunakan (seperti dijelaskan dalam <a href="providing-resources.html#AlternateResources">Menyediakan Sumber Daya</a>).</p>
+
+<p>Perhatikan bahwa nilai-nilai dari bidang {@link
+android.content.res.Configuration} adalah integer yang sesuai dengan konstanta spesifik
+dari kelas {@link android.content.res.Configuration}. Untuk dokumentasi tentang konstanta
+yang harus digunakan di setiap bidang, lihat bidang yang sesuai dalam referensi {@link
+android.content.res.Configuration}.</p>
+
+<p class="note"><strong>Ingatlah:</strong> Saat mendeklarasikan aktivitas untuk menangani perubahan
+konfigurasi, Anda bertanggung jawab untuk me-reset setiap elemen yang alternatifnya Anda berikan. Jika Anda
+mendeklarasikan aktivitas untuk menangani perubahan orientasi dan memiliki gambar yang harus berubah
+antara lanskap dan potret, Anda harus menetapkan kembali setiap sumber daya elemen selama {@link
+android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}.</p>
+
+<p>Jika Anda tidak perlu memperbarui aplikasi berdasarkan perubahan
+konfigurasi ini, sebagai gantinya Anda bisa saja <em>tidak</em> mengimplementasikan {@link
+android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. Dalam
+hal ini, semua sumber daya yang digunakan sebelum perubahan konfigurasi akan tetap digunakan
+dan Anda hanya menghindari restart aktivitas. Akan tetapi, aplikasi Anda harus selalu
+bisa dimatikan dan di-restart dengan status sebelumnya tetap utuh, sehingga Anda jangan menganggap teknik
+ini sebagai jalan keluar untuk mempertahankan status selama daur hidup aktivitas normal. Tidak hanya
+karena ada perubahan konfigurasi lainnya yang tidak bisa Anda cegah untuk me-restart aplikasi, namun
+juga karena Anda harus menangani kejadian seperti saat pengguna meninggalkan aplikasi dan
+dimusnahkan sebelum pengguna kembali ke aplikasi.</p>
+
+<p>Untuk informasi selengkapnya tentang perubahan konfigurasi yang bisa Anda tangani dalam aktivitas, lihat dokumentasi <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
+android:configChanges}</a> dan kelas {@link android.content.res.Configuration}
+.</p>
diff --git a/docs/html-intl/intl/id/guide/topics/ui/controls.jd b/docs/html-intl/intl/id/guide/topics/ui/controls.jd
new file mode 100644
index 0000000..3ebf48b
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/ui/controls.jd
@@ -0,0 +1,90 @@
+page.title=Kontrol Input
+parent.title=Antarmuka Pengguna
+parent.link=index.html
+@jd:body
+
+<div class="figure" style="margin:0">
+  <img src="{@docRoot}images/ui/ui-controls.png" alt="" style="margin:0" />
+</div>
+
+<p>Kontrol input adalah komponen interaktif dalam antarmuka pengguna aplikasi Anda. Android menyediakan
+aneka ragam kontrol yang bisa Anda gunakan dalam UI, seperti tombol, bidang teks, bilah pencarian,
+kotak cek, tombol zoom, tombol toggle, dan masih banyak lagi.</p>
+
+<p>Menambahkan sebuah kontrol input ke UI adalah semudah menambahkan satu elemen XML ke <a href="{@docRoot}guide/topics/ui/declaring-layout.html">layout XML</a>. Misalnya, inilah sebuah
+layout dengan satu bidang teks dan satu tombol:</p>
+
+<pre style="clear:right">
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="horizontal">
+    &lt;EditText android:id="@+id/edit_message"
+        android:layout_weight="1"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:hint="@string/edit_message" />
+    &lt;Button android:id="@+id/button_send"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/button_send"
+        android:onClick="sendMessage" />
+&lt;/LinearLayout>
+</pre>
+
+<p>Tiap kontrol input mendukung satu set kejadian input sehingga Anda bisa menangani berbagai kejadian seperti saat
+pengguna memasukkan teks atau menyentuh tombol.</p>
+
+
+<h2 id="CommonControls">Kontrol Umum</h2>
+<p>Berikut adalah daftar beberapa kontrol umum yang bisa Anda gunakan dalam aplikasi. Ikuti tautan ini untuk mengetahui
+selengkapnya tentang penggunaannya masing-masing.</p>
+
+<p class="note"><strong>Catatan:</strong> Android menyediakan beberapa kontrol lain yang tidak tercantum
+di sini. Telusuri paket {@link android.widget} untuk mengetahui selengkapnya. Jika aplikasi Anda memerlukan
+semacam kontrol input tertentu, Anda bisa membangun <a href="{@docRoot}guide/topics/ui/custom-components.html">komponen custom</a> sendiri.</p>
+
+<table>
+    <tr>
+        <th scope="col">Tipe Kontrol</th>
+        <th scope="col">Keterangan</th>
+	<th scope="col">Kelas Terkait</th>
+    </tr>
+    <tr>
+        <td><a href="controls/button.html">Tombol</a></td>
+        <td>Tombol tekan yang bisa ditekan, atau diklik, oleh pengguna untuk melakukan suatu tindakan.</td>
+	<td>{@link android.widget.Button Button} </td>
+    </tr>
+    <tr>
+        <td><a href="controls/text.html">Bidang teks</a></td>
+        <td>Bidang teks yang bisa diedit. Anda bisa menggunakan widget <code>AutoCompleteTextView</code> untuk membuat widget entri teks yang menyediakan saran pelengkapan otomatis</td>
+	<td>{@link android.widget.EditText EditText}, {@link android.widget.AutoCompleteTextView}</td>
+    </tr>
+    <tr>
+        <td><a href="controls/checkbox.html">Kotak cek</a></td>
+        <td>Switch aktif/nonaktif yang bisa diubah oleh pengguna. Anda harus menggunakan kotak cek saat menampilkan sekumpulan opsi yang bisa dipilih pengguna dan bila keduanya mungkin terjadi bersamaan.</td>
+	<td>{@link android.widget.CheckBox CheckBox} </td>
+    </tr>
+    <tr>
+        <td><a href="controls/radiobutton.html">Tombol radio</a></td>
+        <td>Mirip dengan kotak cek, hanya saja cuma satu opsi yang bisa dipilih dalam kumpulan tersebut.</td>
+	<td>{@link android.widget.RadioGroup RadioGroup}
+	<br>{@link android.widget.RadioButton RadioButton} </td>
+    </tr>
+    <tr>
+        <td><a href="controls/togglebutton.html" style="white-space:nowrap">Tombol toggle</a></td>
+        <td>Tombol aktif/nonaktif dengan indikator cahaya.</td>
+	<td>{@link android.widget.ToggleButton ToggleButton} </td>
+    </tr>
+    <tr>
+        <td><a href="controls/spinner.html">Spinner</a></td>
+        <td>Daftar tarik-turun yang memungkinkan pengguna memilih salah satu dari serangkaian nilai.</td>
+	<td>{@link android.widget.Spinner Spinner} </td>
+    </tr>
+    <tr>
+        <td><a href="controls/pickers.html">Picker</a></td>
+        <td>Dialog bagi pengguna untuk memilih satu nilai dari satu kumpulan dengan menggunakan tombol naik/turun atau dengan gerakan mengusap. Gunakan widget <code>DatePicker</code>code&gt; untuk memasukkan nilai tanggal (bulan, hari, tahun) atau widget <code>TimePicker</code> untuk memasukkan nilai waktu (jam, menit, AM/PM), yang akan diformat secara otomatis untuk lokasi pengguna tersebut.</td>
+	<td>{@link android.widget.DatePicker}, {@link android.widget.TimePicker}</td>
+    </tr>
+</table>
diff --git a/docs/html-intl/intl/id/guide/topics/ui/declaring-layout.jd b/docs/html-intl/intl/id/guide/topics/ui/declaring-layout.jd
new file mode 100644
index 0000000..1c8a0d6
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/ui/declaring-layout.jd
@@ -0,0 +1,492 @@
+page.title=Layout
+page.tags=view,viewgroup
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>Dalam dokumen ini</h2>
+<ol>
+  <li><a href="#write">Tulis XML</a></li>
+  <li><a href="#load">Muat Sumber Daya XML</a></li>
+  <li><a href="#attributes">Atribut</a>
+    <ol>
+      <li><a href="#id">ID</a></li>
+      <li><a href="#layout-params">Parameter Layout</a></li>
+    </ol>
+  </li>
+  <li><a href="#Position">Posisi Layout</a></li>
+  <li><a href="#SizePaddingMargins">Ukuran, Pengisi, dan Margin</a></li>
+  <li><a href="#CommonLayouts">Layout Umum</a></li>
+  <li><a href="#AdapterViews">Membangun Layout dengan Adaptor</a>
+    <ol>
+      <li><a href="#FillingTheLayout">Mengisi tampilan adaptor dengan data</a></li>
+      <li><a href="#HandlingUserSelections">Menangani kejadian klik</a></li>
+    </ol>
+  </li>
+</ol>
+
+  <h2>Kelas-kelas utama</h2>
+  <ol>
+    <li>{@link android.view.View}</li>
+    <li>{@link android.view.ViewGroup}</li>
+    <li>{@link android.view.ViewGroup.LayoutParams}</li>
+  </ol>
+
+  <h2>Lihat juga</h2>
+  <ol>
+    <li><a href="{@docRoot}training/basics/firstapp/building-ui.html">Membangun Antarmuka Pengguna
+Sederhana</a></li> </div>
+</div>
+
+<p>Layout mendefinisikan struktur visual untuk antarmuka pengguna, seperti UI sebuah <a href="{@docRoot}guide/components/activities.html">aktivitas</a> atau <a href="{@docRoot}guide/topics/appwidgets/index.html">widget aplikasi</a>.
+Anda dapat mendeklarasikan layout dengan dua cara:</p>
+<ul>
+<li><strong>Deklarasikan elemen UI dalam XML</strong>. Android menyediakan sebuah kosakata XML
+sederhana yang sesuai dengan kelas dan subkelas View, seperti halnya untuk widget dan layout.</li>
+<li><strong>Buat instance elemen layout saat runtime</strong>. Aplikasi Anda
+bisa membuat objek View dan ViewGroup (dan memanipulasi propertinya) lewat program. </li>
+</ul>
+
+<p>Kerangka kerja Android memberi Anda fleksibilitas untuk menggunakan salah satu atau kedua metode ini guna mendeklarasikan dan mengelola UI aplikasi Anda. Misalnya, Anda bisa mendeklarasikan layout default aplikasi Anda dalam XML, termasuk elemen-elemen layar yang akan muncul di dalamnya dan di propertinya. Anda nanti bisa menambahkan kode dalam aplikasi yang akan memodifikasi status objek layar, termasuk yang dideklarasikan dalam XML, saat runtime. </p>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+  <ul>
+  <li><a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT
+  Plugin for Eclipse</a> menawarkan preview layout XML &mdash;
+ Anda dengan file XML yang dibuka, pilih tab <strong>Layout</strong>.</li>
+  <li>Anda juga harus mencoba alat
+  <a href="{@docRoot}tools/debugging/debugging-ui.html#hierarchyViewer">Hierarchy Viewer</a>,
+ untuk merunut layout &mdash; alat ini akan menampilkan nilai-nilai properti layout,
+  menggambar bentuk kerangka dengan indikator pengisi/margin, dan tampilan yang dirender penuh selagi
+  Anda merunut pada emulator atau perangkat.</li>
+  <li>Alat <a href="{@docRoot}tools/debugging/debugging-ui.html#layoutopt">layoutopt</a> memungkinkan
+  Anda menganalisis layout dan hierarki dengan untuk mengetahui ketidakefisienan atau masalah lainnya.</li>
+</div>
+</div>
+
+<p>Keuntungan mendeklarasikan UI dalam XML adalah karena hal ini memungkinkan Anda memisahkan penampilan aplikasi dari kode yang mengontrol perilakunya dengan lebih baik. Keterangan UI Anda bersifat eksternal bagi kode aplikasi Anda, yang berarti bahwa Anda bisa memodifikasi atau menyesuaikannya tanpa harus memodifikasi dan mengompilasi ulang kode sumber. Misalnya, Anda bisa membuat layout XML untuk berbagai orientasi layar, berbagai ukuran layar perangkat, dan berbagai bahasa. Selain itu, mendeklarasikan layout dalam XML akan mempermudah Anda memvisualisasikan struktur UI, sehingga lebih mudah merunut masalahnya. Karena itu, dokumen ini berfokus pada upaya mengajari Anda cara mendeklarasikan layout dalam XML. Jika Anda
+tertarik dalam membuat instance objek View saat runtime, lihat referensi kelas {@link android.view.ViewGroup} dan
+{@link android.view.View}.</p>
+
+<p>Secara umum, kosakata XML untuk mendeklarasikan elemen UI mengikuti dengan sangat mirip struktur serta penamaan kelas dan metode, dengan nama elemen dipadankan dengan nama kelas dan nama atribut dipadankan dengan metode. Sebenarnya, pemadanan ini kerap kali begitu jelas sehingga Anda bisa menebak atribut XML yang berpadanan dengan sebuah metode kelas, atau menebak kelas yang berpadanan dengan sebuah elemen XML. Akan tetapi, perhatikan bahwa tidak semua kosakata identik. Dalam beberapa kasus, ada sedikit perbedaan penamaan. Misalnya
+, elemen EditText memiliki atribut <code>text</code> yang berpadanan dengan
+<code>EditText.setText()</code>. </p>
+
+<p class="note"><strong>Tip:</strong> Ketahui selengkapnya berbagai tipe layout dalam <a href="{@docRoot}guide/topics/ui/layout-objects.html">Objek
+Layout Umum</a>. Ada juga sekumpulan tutorial tentang cara membangun berbagai layout dalam panduan tutorial
+<a href="{@docRoot}resources/tutorials/views/index.html">Hello Views</a>.</p>
+
+<h2 id="write">Tulis XML</h2>
+
+<p>Dengan menggunakan kosakata XML Android, Anda bisa mendesain secara cepat layout UI dan elemen layar yang dimuatnya, sama dengan cara membuat halaman web dalam HTML &mdash; dengan serangkaian elemen tersarang. </p>
+
+<p>Tiap file layout harus berisi persis satu elemen akar, yang harus berupa sebuah objek View atau ViewGroup. Setelah mendefinisikan elemen akar, Anda bisa menambahkan objek atau widget layout tambahan sebagai elemen anak untuk membangun hierarki View yang mendefinisikan layout Anda secara bertahap. Misalnya, inilah layout XML yang menggunakan {@link android.widget.LinearLayout}
+vertikal untuk menyimpan {@link android.widget.TextView} dan {@link android.widget.Button}:</p>
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:orientation="vertical" >
+    &lt;TextView android:id="@+id/text"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:text="Hello, I am a TextView" />
+    &lt;Button android:id="@+id/button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Hello, I am a Button" />
+&lt;/LinearLayout>
+</pre>
+
+<p>Setelah Anda mendeklarasikan layout dalam XML, simpanlah file dengan ekstensi <code>.xml</code>,
+dalam direktori <code>res/layout/</code> proyek Android, sehingga nanti bisa dikompilasi dengan benar. </p>
+
+<p>Informasi selengkapnya tentang sintaks untuk file XML layout tersedia dalam dokumen <a href="{@docRoot}guide/topics/resources/layout-resource.html">Sumber Daya Layout</a>.</p>
+
+<h2 id="load">Muat Sumber Daya XML</h2>
+
+<p>Saat mengompilasi aplikasi, masing-masing file layout XML akan dikompilasi dalam sebuah sumber daya
+{@link android.view.View}. Anda harus memuat sumber daya layout dari kode aplikasi, dalam implementasi
+callback {@link android.app.Activity#onCreate(android.os.Bundle) Activity.onCreate()}.
+Lakukan dengan memanggil <code>{@link android.app.Activity#setContentView(int) setContentView()}</code>,
+dengan meneruskan acuan ke sumber daya layout berupa:
+<code>R.layout.<em>layout_file_name</em></code>.
+Misalnya, jika XML layout Anda disimpan sebagai <code>main_layout.xml</code>, Anda akan memuatnya
+untuk Activity seperti ini:</p>
+<pre>
+public void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    setContentView(R.layout.main_layout);
+}
+</pre>
+
+<p>Metode callback <code>onCreate()</code> dalam Activity dipanggil oleh kerangka kerja Android saat
+Activity Anda dijalankan (lihat diskusi tentang daur hidup, dalam dokumen
+<a href="{@docRoot}guide/components/activities.html#Lifecycle">Aktivitas</a>
+).</p>
+
+
+<h2 id="attributes">Atribut</h2>
+
+<p>Setiap objek View dan ViewGroup mendukung variasi atribut XML-nya sendiri.
+Sebagian atribut bersifat spesifik untuk objek View (misalnya, TextView mendukung atribut <code>textSize</code>
+), namun atribut ini juga diwarisi oleh sembarang objek View yang dapat memperluas kelas ini.
+Sebagian atribut bersifat umum untuk semua objek View, karena diwarisi dari kelas View akar (seperti
+atribut <code>id</code>). Dan, atribut lain dianggap sebagai "parameter layout" yaitu
+atribut yang menjelaskan orientasi layout tertentu dari objek View, seperti yang didefinisikan oleh objek ViewGroup induk
+dari objek itu.</p>
+
+<h3 id="id">ID</h3>
+
+<p>Objek View apa saja dapat memiliki ID integer yang dikaitkan dengannya, untuk mengidentifikasi secara unik View dalam pohon.
+Bila aplikasi dikompilasi, ID ini akan diacu sebagai integer, namun ID biasanya
+ditetapkan dalam file XML layout sebagai string, dalam atribut <code>id</code>.
+Ini atribut XML yang umum untuk semua objek View
+(yang didefinisikan oleh kelas {@link android.view.View}) dan Anda akan sering sekali menggunakannya.
+Sintaks untuk ID dalam tag XML adalah:</p>
+<pre>android:id="&#64;+id/my_button"</pre>
+
+<p>Simbol "at" (@) pada awal string menunjukkan parser XML harus mengurai dan memperluas
+ID string selebihnya dan mengenalinya sebagai ID sumber daya. Simbol tanda tambah (+) berarti ini nama sumber daya baru yang harus
+dibuat dan ditambahkan ke sumber daya kita (dalam file <code>R.java</code>). Ada sejumlah sumber daya ID lain yang
+ditawarkan oleh kerangka kerja Android. Saat mengacu sebuah ID sumber daya Android, Anda tidak memerlukan simbol tanda tambah,
+namun harus menambahkan namespace paket <code>android</code>, sehingga:</p>
+<pre>android:id="&#64;android:id/empty"</pre>
+<p>Dengan namespace paket <code>android</code> yang tersedia, kita sekarang mengacu ID dari kelas sumber daya <code>android.R</code>
+, daripada kelas sumber daya lokal.</p>
+
+<p>Untuk membuat tampilan dan mengacunya dari aplikasi, pola yang umum adalah:</p>
+<ol>
+  <li>Mendefinisikan tampilan/widget dalam file layout dan memberinya ID unik:
+<pre>
+&lt;Button android:id="&#64;+id/my_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="&#64;string/my_button_text"/>
+</pre>
+  </li>
+  <li>Kemudian buat instance objek tampilan dan tangkap instance itu dari layout
+(biasanya dalam metode <code>{@link android.app.Activity#onCreate(Bundle) onCreate()}</code>):
+<pre>
+Button myButton = (Button) findViewById(R.id.my_button);
+</pre>
+  </li>
+</ol>
+<p>Mendefinisikan ID untuk objek tampilan adalah penting saat membuat {@link android.widget.RelativeLayout}.
+Dalam layout relatif, tampilan saudara bisa mendefinisikan layout secara relatif terhadap tampilan saudara lainnya,
+yang diacu melalui ID unik.</p>
+<p>ID tidak perlu unik di seluruh pohon, namun harus
+unik di bagian pohon yang Anda cari (yang mungkin sering kali seluruh pohon, jadi lebih baik
+benar-benar unik bila memungkinkan).</p>
+
+
+<h3 id="layout-params">Parameter Layout</h3>
+
+<p>Atribut layout XML bernama <code>layout_<em>something</em></code> mendefinisikan
+parameter layout View yang cocok untuk ViewGroup tempatnya berada.</p>
+
+<p>Setiap kelas ViewGroup mengimplementasikan kelas tersarang yang memperluas {@link
+android.view.ViewGroup.LayoutParams}. Subkelas ini
+berisi tipe properti yang mendefinisikan ukuran dan posisi masing-masing tampilan anak, sebagaimana
+mestinya untuk grup tampilan. Seperti yang bisa Anda lihat dalam gambar 1,
+grup tampilan induk mendefinisikan parameter layout untuk masing-masing tampilan anak (termasuk grup tampilan anak).</p>
+
+<img src="{@docRoot}images/layoutparams.png" alt="" />
+<p class="img-caption"><strong>Gambar 1.</strong> Visualisasi hierarki tampilan dengan parameter layout
+yang dikaitkan dengan tiap tampilan.</p>
+
+<p>Perhatikan bahwa setiap subkelas LayoutParams memiliki sintaksnya sendiri untuk menetapkan
+nilai-nilai. Tiap elemen anak harus mendefinisikan LayoutParams yang semestinya bagi induknya,
+meskipun elemen itu bisa juga mendefinisikan LayoutParams untuk anak-anaknya sendiri. </p>
+
+<p>Semua grup tampilan berisi lebar dan tinggi (<code>layout_width</code> dan
+<code>layout_height</code>), dan masing-masing tampilan harus mendefinisikannya. Banyak
+LayoutParams yang juga menyertakan margin dan border opsional. <p>
+
+<p>Anda bisa menetapkan lebar dan tinggi dengan ukuran persis, meskipun Anda mungkin
+tidak ingin sering-sering melakukannya. Lebih sering, Anda akan menggunakan salah satu konstanta ini untuk
+mengatur lebar atau tinggi: </p>
+
+<ul>
+  <li><var>wrap_content</var> memberi tahu tampilan Anda agar menyesuaikan sendiri ukurannya dengan dimensi
+yang dibutuhkan oleh isinya.</li>
+  <li><var>match_parent</var> (bernama <var>fill_parent</var> sebelum API Level 8)
+memberi tahu tampilan Anda agar menjadi sebesar yang diperbolehkan oleh grup tampilan induknya.</li>
+</ul>
+
+<p>Secara umum, menetapkan lebar dan tinggi layout dengan satuan mutlak seperti
+piksel tidaklah disarankan. Melainkan dengan menggunakan ukuran relatif seperti
+satuan piksel yang tidak bergantung pada kerapatan (<var>dp</var>), <var>wrap_content</var>, atau
+<var>match_parent</var>, adalah sebuah pendekatan yang lebih baik, karena membantu memastikan bahwa
+aplikasi Anda akan ditampilkan dengan benar pada berbagai ukuran layar perangkat.
+Tipe ukuran yang diterima didefinisikan dalam dokumen
+<a href="{@docRoot}guide/topics/resources/available-resources.html#dimension">
+Sumber Daya yang Tersedia</a>.</p>
+
+
+<h2 id="Position">Posisi Layout</h2>
+   <p>
+   Geometri tampilan adalah persegi panjang. Sebuah tampilan memiliki lokasi,
+   yang dinyatakan berupa sepasang koordinat <em>kiri</em> dan <em>atas</em>, dan
+   dua dimensi, yang dinyatakan berupa lebar dan tinggi. Satuan untuk lokasi
+   dan dimensi adalah piksel.
+   </p>
+
+   <p>
+   Lokasi tampilan dapat diambil dengan memanggil metode
+   {@link android.view.View#getLeft()} dan {@link android.view.View#getTop()}. Metode terdahulu menghasilkan koordinat kiri, atau X,
+   persegi panjang yang mewakili tampilan. Metode selanjutnya menghasilkan koordinat
+   atas, atau Y, persegi panjang yang mewakili tampilan. Kedua metode ini
+   menghasilkan lokasi tampilan relatif terhadap induknya. Misalnya,
+   bila <code>getLeft()</code> menghasilkan 20, berarti tampilan berlokasi 20 piksel ke
+   kanan dari tepi kiri induk langsungnya.
+   </p>
+
+   <p>
+   Selain itu, beberapa metode praktis ditawarkan untuk menghindari komputasi yang tidak perlu,
+   yakni {@link android.view.View#getRight()} dan {@link android.view.View#getBottom()}.
+   Kedua metode ini menghasilkan koordinat tepi kanan dan bawah
+   persegi panjang yang mewakili tampilan. Misalnya, memanggil {@link android.view.View#getRight()}
+   serupa dengan komputasi berikut: <code>getLeft() + getWidth()</code>.
+   </p>
+
+
+<h2 id="SizePaddingMargins">Ukuran, Pengisi, dan Margin</h2>
+   <p>
+   Ukuran tampilan dinyatakan dengan lebar dan tinggi. Tampilan sebenarnya
+   memiliki dua pasang nilai lebar dan tinggi.
+   </p>
+
+   <p>
+   Sepasang pertama disebut <em>lebar terukur</em> dan
+   <em>tinggi terukur</em>. Dimensi ini mendefinisikan seberapa besar tampilan yang diinginkan
+   dalam induknya. Dimensi
+   terukur bisa diperoleh dengan memanggil {@link android.view.View#getMeasuredWidth()}
+   dan {@link android.view.View#getMeasuredHeight()}.
+   </p>
+
+   <p>
+   Sepasang kedua cukup disebut dengan <em>lebar</em> dan <em>tinggi</em>, atau
+   kadang-kadang <em>lebar penggambaran</em> dan <em>tinggi penggambaran</em>. Dimensi-dimensi ini
+   mendefinisikan ukuran tampilan sebenarnya pada layar, saat digambar dan
+   setelah layout. Nilai-nilai ini mungkin, namun tidak harus, berbeda dengan
+   lebar dan tinggi terukur. Lebar dan tinggi bisa diperoleh dengan memanggil
+   {@link android.view.View#getWidth()} dan {@link android.view.View#getHeight()}.
+   </p>
+
+   <p>
+   Untuk mengukur dimensinya, tampilan akan memperhitungkan pengisinya (padding). Pengisi
+   dinyatakan dalam piksel untuk bagian kiri, atas, kanan, dan bawah tampilan.
+   Pengisi bisa digunakan untuk meng-offset isi tampilan dengan
+   piksel dalam jumlah tertentu. Misalnya, pengisi kiri sebesar 2 akan mendorong isi tampilan sebanyak
+   2 piksel ke kanan dari tepi kiri. Pengisi bisa diatur menggunakan
+   metode {@link android.view.View#setPadding(int, int, int, int)} dan diketahui dengan memanggil
+   {@link android.view.View#getPaddingLeft()}, {@link android.view.View#getPaddingTop()},
+   {@link android.view.View#getPaddingRight()}, dan {@link android.view.View#getPaddingBottom()}.
+   </p>
+
+   <p>
+   Meskipun bisa mendefinisikan pengisi, tampilan tidak menyediakan dukungan untuk
+   margin. Akan tetapi, grup tampilan menyediakan dukungan tersebut. Lihat
+   {@link android.view.ViewGroup} dan
+   {@link android.view.ViewGroup.MarginLayoutParams} untuk informasi lebih jauh.
+   </p>
+
+   <p>Untuk informasi selengkapnya tentang dimensi, lihat
+   <a href="{@docRoot}guide/topics/resources/more-resources.html#Dimension">Nilai-Nilai Dimensi</a>.
+   </p>
+
+
+
+
+
+
+<style type="text/css">
+div.layout {
+  float:left;
+  width:200px;
+  margin:0 0 20px 20px;
+}
+div.layout.first {
+  margin-left:0;
+  clear:left;
+}
+</style>
+
+
+
+
+<h2 id="CommonLayouts">Layout Umum</h2>
+
+<p>Tiap subkelas dari kelas {@link android.view.ViewGroup} menyediakan cara unik untuk menampilkan
+tampilan yang Anda sarangkan di dalamnya. Di bawah ini adalah beberapa tipe layout lebih umum yang dibuat
+ke dalam platform Android.</p>
+
+<p class="note"><strong>Catatan:</strong> Walaupun Anda bisa menyarangkan satu atau beberapa layout dalam
+layout lain untuk mendapatkan desain UI, Anda harus berusaha menjaga hierarki layout sedangkal
+mungkin. Layout Anda akan digambar lebih cepat jika memiliki layout tersarang yang lebih sedikit (hierarki tampilan yang melebar
+lebih baik daripada hierarki tampilan yang dalam).</p>
+
+<!--
+<h2 id="framelayout">FrameLayout</h2>
+<p>{@link android.widget.FrameLayout FrameLayout} is the simplest type of layout
+object. It's basically a blank space on your screen that you can
+later fill with a single object &mdash; for example, a picture that you'll swap in and out.
+All child elements of the FrameLayout are pinned to the top left corner of the screen; you cannot
+specify a different location for a child view. Subsequent child views will simply be drawn over
+previous ones,
+partially or totally obscuring them (unless the newer object is transparent).
+</p>
+-->
+
+
+<div class="layout first">
+  <h4><a href="layout/linear.html">Layout Linier</a></h4>
+  <a href="layout/linear.html"><img src="{@docRoot}images/ui/linearlayout-small.png" alt="" /></a>
+  <p>Layout yang mengatur anak-anaknya menjadi satu baris horizontal atau vertikal. Layout ini
+  akan membuat scrollbar jika panjang jendela melebihi panjang layar.</p>
+</div>
+
+<div class="layout">
+  <h4><a href="layout/relative.html">Layout Relatif</a></h4>
+  <a href="layout/relative.html"><img src="{@docRoot}images/ui/relativelayout-small.png" alt="" /></a>
+  <p>Memungkinkan Anda menentukan lokasi objek anak relatif terhadap satu sama lain (anak A di
+kiri anak B) atau terhadap induk (disejajarkan dengan atas induknya).</p>
+</div>
+
+<div class="layout">
+  <h4><a href="{@docRoot}guide/webapps/webview.html">Tampilan Web</a></h4>
+  <a href="{@docRoot}guide/webapps/webview.html"><img src="{@docRoot}images/ui/webview-small.png" alt="" /></a>
+  <p>Menampilkan halaman web.</p>
+</div>
+
+
+
+
+<h2 id="AdapterViews" style="clear:left">Membangun Layout dengan Adaptor</h2>
+
+<p>Bila isi layout bersifat dinamis atau tidak dipastikan sebelumnya, Anda bisa menggunakan layout yang menjadi
+subkelas {@link android.widget.AdapterView} untuk mengisi layout dengan tampilan saat runtime.
+Subkelas dari kelas {@link android.widget.AdapterView} menggunakan {@link android.widget.Adapter} untuk
+mengikat data ke layoutnya. {@link android.widget.Adapter} berfungsi sebagai penghubung antara sumber data
+dan layout{@link android.widget.AdapterView}&mdash;{@link android.widget.Adapter}
+menarik data (dari suatu sumber seperti larik (array) atau query database) dan mengubah setiap entri
+menjadi tampilan yang bisa ditambahkan ke dalam layout {@link android.widget.AdapterView}.</p>
+
+<p>Layout umum yang didukung oleh adaptor meliputi:</p>
+
+<div class="layout first">
+  <h4><a href="layout/listview.html">Tampilan Daftar</a></h4>
+  <a href="layout/listview.html"><img src="{@docRoot}images/ui/listview-small.png" alt="" /></a>
+  <p>Menampilkan daftar kolom tunggal yang bergulir.</p>
+</div>
+
+<div class="layout">
+  <h4><a href="layout/gridview.html">Tampilan Petak</a></h4>
+  <a href="layout/gridview.html"><img src="{@docRoot}images/ui/gridview-small.png" alt="" /></a>
+  <p>Menampilkan petak bergulir yang terdiri atas kolom dan baris.</p>
+</div>
+
+
+
+<h3 id="FillingTheLayout" style="clear:left">Mengisi tampilan adaptor dengan data</h3>
+
+<p>Anda bisa mengisi {@link android.widget.AdapterView} seperti {@link android.widget.ListView} atau
+{@link android.widget.GridView} dengan mengikat instance {@link android.widget.AdapterView} ke
+{@link android.widget.Adapter}, yang akan mengambil data dari sumber eksternal dan membuat {@link
+android.view.View} yang mewakili tiap entri data.</p>
+
+<p>Android menyediakan beberapa subkelas {@link android.widget.Adapter} yang berguna untuk
+menarik berbagai jenis data dan membangun tampilan untuk {@link android.widget.AdapterView}. Dua
+ adaptor yang paling umum adalah:</p>
+
+<dl>
+  <dt>{@link android.widget.ArrayAdapter}</dt>
+    <dd>Gunakan adaptor ini bila sumber data Anda berupa larik. Secara default, {@link
+android.widget.ArrayAdapter} akan membuat tampilan untuk tiap elemen larik dengan memanggil {@link
+java.lang.Object#toString()} pada tiap elemen dan menempatkan isinya dalam {@link
+android.widget.TextView}.
+      <p>Misalnya, jika Anda memiliki satu larik string yang ingin ditampilkan dalam {@link
+android.widget.ListView}, buatlah {@link android.widget.ArrayAdapter} baru dengan konstruktor
+untuk menentukan layout setiap string dan larik string:</p>
+<pre>
+ArrayAdapter&lt;String> adapter = new ArrayAdapter&lt;String>(this,
+        android.R.layout.simple_list_item_1, myStringArray);
+</pre>
+<p>Argumen-argumen untuk konstruktor ini adalah:</p>
+<ul>
+  <li>{@link android.content.Context} aplikasi Anda</li>
+  <li>Layout yang berisi {@link android.widget.TextView} untuk tiap string dalam larik</li>
+  <li>Larik string</li>
+</ul>
+<p>Kemudian tinggal panggil
+{@link android.widget.ListView#setAdapter setAdapter()} pada {@link android.widget.ListView} Anda:</p>
+<pre>
+ListView listView = (ListView) findViewById(R.id.listview);
+listView.setAdapter(adapter);
+</pre>
+
+      <p>Untuk menyesuaikan penampilan setiap item, Anda bisa mengesampingkan metode {@link
+java.lang.Object#toString()} bagi objek dalam larik Anda. Atau, untuk membuat tampilan tiap
+elemen selain {@link android.widget.TextView} (misalnya, jika Anda menginginkan
+{@link android.widget.ImageView} bagi setiap item larik), perluas kelas {@link
+android.widget.ArrayAdapter} dan kesampingkan {@link android.widget.ArrayAdapter#getView
+getView()} agar memberikan tipe tampilan yang Anda inginkan bagi tiap item.</p>
+
+</dd>
+
+  <dt>{@link android.widget.SimpleCursorAdapter}</dt>
+    <dd>Gunakan adaptor ini bila data Anda berasal dari {@link android.database.Cursor}. Saat
+menggunakan {@link android.widget.SimpleCursorAdapter}, Anda harus menentukan layout yang akan digunakan untuk tiap
+baris dalam {@link android.database.Cursor} dan di kolom mana di {@link android.database.Cursor}
+harus memasukkan tampilan layout. Misalnya, jika Anda ingin untuk membuat daftar
+nama orang dan nomor telepon, Anda bisa melakukan query yang menghasilkan {@link
+android.database.Cursor} yang berisi satu baris untuk tiap orang dan kolom-kolom untuk nama dan
+nomor. Selanjutnya Anda membuat larik string yang menentukan kolom dari {@link
+android.database.Cursor} yang Anda inginkan dalam layout untuk setiap hasil dan larik integer yang menentukan
+tampilan yang sesuai untuk menempatkan masing-masing kolom:</p>
+<pre>
+String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,
+                        ContactsContract.CommonDataKinds.Phone.NUMBER};
+int[] toViews = {R.id.display_name, R.id.phone_number};
+</pre>
+<p>Bila Anda membuat instance {@link android.widget.SimpleCursorAdapter}, teruskan layout yang akan digunakan untuk
+setiap hasil, {@link android.database.Cursor} yang berisi hasil tersebut, dan dua larik ini:</p>
+<pre>
+SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
+        R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);
+ListView listView = getListView();
+listView.setAdapter(adapter);
+</pre>
+<p>{@link android.widget.SimpleCursorAdapter} kemudian membuat tampilan untuk tiap baris dalam
+{@link android.database.Cursor} dengan layout yang disediakan dengan memasukkan setiap item {@code
+fromColumns} ke dalam tampilan {@code toViews} yang sesuai.</p></dd>
+</dl>
+
+
+<p>Jika, selama aplikasi berjalan, Anda mengubah data sumber yang dibaca oleh
+adaptor, maka Anda harus memanggil {@link android.widget.ArrayAdapter#notifyDataSetChanged()}. Hal ini akan
+memberi tahu tampilan yang bersangkutan bahwa data telah berubah dan tampilan harus memperbarui dirinya sendiri.</p>
+
+
+
+<h3 id="HandlingUserSelections">Menangani kejadian klik</h3>
+
+<p>Anda bisa merespons kejadian klik pada setiap item dalam {@link android.widget.AdapterView} dengan
+menerapkan antarmuka {@link android.widget.AdapterView.OnItemClickListener}. Misalnya:</p>
+
+<pre>
+// Create a message handling object as an anonymous class.
+private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {
+    public void onItemClick(AdapterView parent, View v, int position, long id) {
+        // Do something in response to the click
+    }
+};
+
+listView.setOnItemClickListener(mMessageClickedHandler);
+</pre>
+
+
+
diff --git a/docs/html-intl/intl/id/guide/topics/ui/dialogs.jd b/docs/html-intl/intl/id/guide/topics/ui/dialogs.jd
new file mode 100644
index 0000000..06a25ac
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/ui/dialogs.jd
@@ -0,0 +1,798 @@
+page.title=Dialog
+page.tags=alertdialog,dialogfragment
+
+@jd:body
+
+
+
+<div id="qv-wrapper">
+  <div id="qv">
+    <h2>Dalam dokumen ini</h2>
+<ol>
+  <li><a href="#DialogFragment">Membuat Fragmen Dialog</a></li>
+  <li><a href="#AlertDialog">Membuat Dialog Peringatan</a>
+    <ol>
+      <li><a href="#AddingButtons">Menambahkan tombol</a></li>
+      <li><a href="#AddingAList">Menambahkan daftar</a></li>
+      <li><a href="#CustomLayout">Membuat Layout Custom</a></li>
+    </ol>
+  </li>
+  <li><a href="#PassingEvents">Meneruskan Kejadian Kembali ke Host Dialog</a></li>
+  <li><a href="#ShowingADialog">Menampilkan Dialog</a></li>
+  <li><a href="#FullscreenDialog">Menampilkan Dialog sebagai Layar Penuh atau Fragmen Tertanam</a>
+    <ol>
+      <li><a href="#ActivityAsDialog">Menampilkan aktivitas sebagai dialog pada layar besar</a></li>
+    </ol>
+  </li>
+  <li><a href="#DismissingADialog">Menutup Dialog</a></li>
+</ol>
+
+    <h2>Kelas-kelas utama</h2>
+    <ol>
+      <li>{@link android.app.DialogFragment}</li>
+      <li>{@link android.app.AlertDialog}</li>
+    </ol>
+
+    <h2>Lihat juga</h2>
+    <ol>
+      <li><a href="{@docRoot}design/building-blocks/dialogs.html">Panduan desain dialog</a></li>
+      <li><a href="{@docRoot}guide/topics/ui/controls/pickers.html">Picker</a> (dialog Tanggal/Waktu)</li>
+    </ol>
+  </div>
+</div>
+
+<p>Dialog adalah jendela kecil yang meminta pengguna untuk
+membuat keputusan atau memasukkan informasi tambahan. Dialog tidak mengisi layar dan
+biasanya digunakan untuk kejadian modal yang mengharuskan pengguna untuk melakukan tindakan sebelum bisa melanjutkan.</p>
+
+<div class="note design">
+<p><strong>Desain Dialog</strong></p>
+  <p>Untuk informasi tentang cara mendesain dialog, termasuk saran
+  untuk bahasa, bacalah panduan Desain <a href="{@docRoot}design/building-blocks/dialogs.html">dialog</a>.</p>
+</div>
+
+<img src="{@docRoot}images/ui/dialogs.png" />
+
+<p>Kelas {@link android.app.Dialog} adalah kelas basis untuk dialog, namun Anda
+harus menghindari pembuatan instance {@link android.app.Dialog} secara langsung.
+Sebagai gantinya, gunakan salah satu subkelas berikut:</p>
+<dl>
+  <dt>{@link android.app.AlertDialog}</dt>
+  <dd>Dialog yang bisa menampilkan judul, hingga tiga tombol, daftar
+    item yang dapat dipilih, atau layout custom.</dd>
+  <dt>{@link android.app.DatePickerDialog} atau {@link android.app.TimePickerDialog}</dt>
+  <dd>Dialog berisi UI yang sudah didefinisikan dan memungkinkan pengguna memilih tanggal atau waktu.</dd>
+</dl>
+
+<div class="sidebox">
+<h2>Hindari ProgressDialog</h2>
+<p>Android menyertakan kelas dialog lain yang disebut
+{@link android.app.ProgressDialog} yang menampilkan dialog berisi progress-bar. Akan tetapi, jika Anda
+perlu menunjukkan kemajuan pemuatan ataupun kemajuan yang tidak pasti, maka Anda harus mengikuti
+panduan desain untuk <a href="{@docRoot}design/building-blocks/progress.html">Kemajuan &amp;
+Aktivitas</a> dan menggunakan {@link android.widget.ProgressBar} dalam layout Anda.</p>
+</div>
+
+<p>Kelas-kelas ini mendefinisikan gaya dan struktur dialog Anda, namun Anda harus
+menggunakan {@link android.support.v4.app.DialogFragment} sebagai kontainer dialog Anda.
+Kelas {@link android.support.v4.app.DialogFragment} menyediakan semua kontrol yang Anda
+perlukan untuk membuat dialog dan mengelola penampilannya, sebagai ganti memanggil metode
+pada objek {@link android.app.Dialog}.</p>
+
+<p>Menggunakan {@link android.support.v4.app.DialogFragment} untuk mengelola dialog
+akan memastikan bahwa kelas itu menangani kejadian daur hidup
+dengan benar seperti ketika pengguna menekan tombol <em>Back</em> atau memutar layar. Kelas {@link
+android.support.v4.app.DialogFragment} juga memungkinkan Anda menggunakan ulang dialog UI sebagai
+komponen yang bisa ditanamkan dalam UI yang lebih besar, persis seperti {@link
+android.support.v4.app.Fragment} tradisional (seperti saat Anda ingin dialog UI muncul berbeda
+pada layar besar dan kecil).</p>
+
+<p>Bagian-bagian berikutnya dalam panduan ini akan menjelaskan cara menggunakan {@link
+android.support.v4.app.DialogFragment} yang dikombinasikan dengan objek {@link android.app.AlertDialog}
+. Jika Anda ingin membuat picker tanggal atau waktu, Anda harus membaca panduan
+<a href="{@docRoot}guide/topics/ui/controls/pickers.html">Picker</a>.</p>
+
+<p class="note"><strong>Catatan:</strong>
+Karena kelas {@link android.app.DialogFragment} mulanya ditambahkan pada
+Android 3.0 (API level 11), dokumen ini menjelaskan cara menggunakan kelas {@link
+android.support.v4.app.DialogFragment} yang disediakan bersama <a href="{@docRoot}tools/support-library/index.html">Pustaka Dukungan</a>. Dengan menambahkan pustaka ini
+ke aplikasi, Anda bisa menggunakan {@link android.support.v4.app.DialogFragment} dan berbagai
+API lain pada perangkat yang menjalankan Android 1.6 atau yang lebih tinggi. Jika versi minimum yang didukung aplikasi Anda
+adalah API level 11 atau yang lebih tinggi, maka Anda bisa menggunakan versi kerangka kerja {@link
+android.app.DialogFragment}, namun ketahuilah bahwa tautan dalam dokumen ini adalah untuk API
+pustaka dukungan. Saat menggunakan pustaka dukungan,
+pastikan Anda mengimpor kelas <code>android.support.v4.app.DialogFragment</code>
+dan <em>bukan</em> <code>android.app.DialogFragment</code>.</p>
+
+
+<h2 id="DialogFragment">Membuat Fragmen Dialog</h2>
+
+<p>Anda bisa menghasilkan beragam rancangan dialog&mdash;termasuk
+layout custom dan desain yang dijelaskan dalam panduan desain <a href="{@docRoot}design/building-blocks/dialogs.html">Dialog</a>
+&mdash;dengan memperluas
+{@link android.support.v4.app.DialogFragment} dan membuat {@link android.app.AlertDialog}
+dalam metode callback {@link android.support.v4.app.DialogFragment#onCreateDialog
+onCreateDialog()}.</p>
+
+<p>Misalnya, berikut ini sebuah {@link android.app.AlertDialog} dasar yang dikelola dalam
+{@link android.support.v4.app.DialogFragment}:</p>
+
+<pre>
+public class FireMissilesDialogFragment extends DialogFragment {
+    &#64;Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        // Use the Builder class for convenient dialog construction
+        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        builder.setMessage(R.string.dialog_fire_missiles)
+               .setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
+                   public void onClick(DialogInterface dialog, int id) {
+                       // FIRE ZE MISSILES!
+                   }
+               })
+               .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+                   public void onClick(DialogInterface dialog, int id) {
+                       // User cancelled the dialog
+                   }
+               });
+        // Create the AlertDialog object and return it
+        return builder.create();
+    }
+}
+</pre>
+
+<div class="figure" style="width:290px;margin:0 0 0 20px">
+<img src="{@docRoot}images/ui/dialog_buttons.png" alt="" />
+<p class="img-caption"><strong>Gambar 1.</strong>
+Dialog dengan satu pesan dan dua tombol tindakan.</p>
+</div>
+
+<p>Sekarang, bila Anda membuat instance kelas ini dan memanggil {@link
+android.support.v4.app.DialogFragment#show show()} pada objek itu, dialog akan muncul seperti
+yang ditampilkan dalam gambar 1.</p>
+
+<p>Bagian berikutnya menjelaskan lebih jauh tentang penggunaan API {@link android.app.AlertDialog.Builder}
+untuk membuat dialog.</p>
+
+<p>Bergantung pada seberapa rumit dialog tersebut, Anda bisa menerapkan berbagai metode callback lain
+dalam {@link android.support.v4.app.DialogFragment}, termasuk semua
+<a href="{@docRoot}guide/components/fragments.html#Lifecycle">metode daur hidup fragmen</a> dasar.
+
+
+
+
+
+<h2 id="AlertDialog">Membuat Dialog Peringatan</h2>
+
+
+<p>Kelas {@link android.app.AlertDialog} memungkinkan Anda membuat berbagai desain dialog dan
+seringkali satu-satunya kelas dialog yang akan Anda perlukan.
+Seperti yang ditampilkan dalam gambar 2, ada tiga area pada dialog peringatan:</p>
+
+<div class="figure" style="width:311px;margin-top:0">
+<img src="{@docRoot}images/ui/dialogs_regions.png" alt="" style="margin-bottom:0" />
+<p class="img-caption"><strong>Gambar 2.</strong> Layout dialog.</p>
+</div>
+
+<ol>
+<li><b>Judul</b>
+  <p>Area ini opsional dan hanya boleh digunakan bila area konten
+  ditempati oleh pesan terperinci, daftar, atau layout custom. Jika Anda perlu menyatakan
+  pesan atau pertanyaan sederhana (seperti dialog dalam gambar 1), Anda tidak memerlukan judul.</li>
+<li><b>Area konten</b>
+  <p>Area ini bisa menampilkan pesan, daftar, atau layout custom lainnya.</p></li>
+<li><b>Tombol tindakan</b>
+  <p>Tidak boleh ada lebih dari tiga tombol tindakan dalam sebuah dialog.</p></li>
+</ol>
+
+<p>Kelas {@link android.app.AlertDialog.Builder}
+ menyediakan API yang memungkinkan Anda membuat {@link android.app.AlertDialog}
+dengan jenis konten ini, termasuk layout custom.</p>
+
+<p>Untuk membuat {@link android.app.AlertDialog}:</p>
+
+<pre>
+<b>// 1. Instantiate an {@link android.app.AlertDialog.Builder} with its constructor</b>
+AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+
+<b>// 2. Chain together various setter methods to set the dialog characteristics</b>
+builder.setMessage(R.string.dialog_message)
+       .setTitle(R.string.dialog_title);
+
+<b>// 3. Get the {@link android.app.AlertDialog} from {@link android.app.AlertDialog.Builder#create()}</b>
+AlertDialog dialog = builder.create();
+</pre>
+
+<p>Topik-topik selanjutnya menampilkan cara mendefinisikan berbagai atribut dialog dengan menggunakan
+kelas {@link android.app.AlertDialog.Builder}.</p>
+
+
+
+
+<h3 id="AddingButtons">Menambahkan tombol</h3>
+
+<p>Untuk menambahkan tombol tindakan seperti dalam gambar 2,
+panggil metode {@link android.app.AlertDialog.Builder#setPositiveButton setPositiveButton()} dan
+{@link android.app.AlertDialog.Builder#setNegativeButton setNegativeButton()}:</p>
+
+<pre style="clear:right">
+AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+// Add the buttons
+builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+           public void onClick(DialogInterface dialog, int id) {
+               // User clicked OK button
+           }
+       });
+builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+           public void onClick(DialogInterface dialog, int id) {
+               // User cancelled the dialog
+           }
+       });
+// Set other dialog properties
+...
+
+// Create the AlertDialog
+AlertDialog dialog = builder.create();
+</pre>
+
+<p>Metode <code>set...Button()</code> mengharuskan adanya judul bagi tombol (disediakan
+oleh suatu <a href="{@docRoot}guide/topics/resources/string-resource.html">sumber daya string</a>) dan
+{@link android.content.DialogInterface.OnClickListener} yang mendefinisikan tindakan yang diambil
+bila pengguna menekan tombol.</p>
+
+<p>Ada tiga macam tombol tindakan yang Anda bisa tambahkan:</p>
+<dl>
+  <dt>Positif</dt>
+  <dd>Anda harus menggunakan tipe ini untuk menerima dan melanjutkan tindakan (tindakan "OK").</dd>
+  <dt>Negatif</dt>
+  <dd>Anda harus menggunakan tipe ini untuk membatalkan tindakan.</dd>
+  <dt>Netral</dt>
+  <dd>Anda harus menggunakan tipe ini bila pengguna mungkin tidak ingin melanjutkan tindakan,
+  namun tidak ingin membatalkan. Tipe ini muncul antara tombol positif dan
+tombol negatif. Misalnya, tindakan bisa berupa "Ingatkan saya nanti".</dd>
+</dl>
+
+<p>Anda hanya bisa menambahkan salah satu tipe tombol ke {@link
+android.app.AlertDialog}. Artinya, Anda tidak bisa memiliki lebih dari satu tombol "positif".</p>
+
+
+
+<div class="figure" style="width:290px;margin:0 0 0 40px">
+<img src="{@docRoot}images/ui/dialog_list.png" alt="" />
+<p class="img-caption"><strong>Gambar 3.</strong>
+Dialog dengan satu judul dan daftar.</p>
+</div>
+
+<h3 id="AddingAList">Menambahkan daftar</h3>
+
+<p>Ada tiga macam daftar yang tersedia pada API {@link android.app.AlertDialog}:</p>
+<ul>
+<li>Daftar pilihan tunggal biasa</li>
+<li>Daftar pilihan tunggal persisten (tombol radio)</li>
+<li>Daftar pilihan ganda persisten (kotak cek)</li>
+</ul>
+
+<p>Untuk membuat daftar pilihan tunggal seperti dalam gambar 3,
+gunakan metode {@link android.app.AlertDialog.Builder#setItems setItems()}:</p>
+
+<pre style="clear:right">
+&#64;Override
+public Dialog onCreateDialog(Bundle savedInstanceState) {
+    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+    builder.setTitle(R.string.pick_color)
+           .setItems(R.array.colors_array, new DialogInterface.OnClickListener() {
+               public void onClick(DialogInterface dialog, int which) {
+               // The 'which' argument contains the index position
+               // of the selected item
+           }
+    });
+    return builder.create();
+}
+</pre>
+
+<p>Karena daftar muncul dalam area konten dialog,
+dialog tidak bisa menampilkan pesan dan daftar sekaligus dan Anda harus menetapkan judul untuk
+dialog dengan {@link android.app.AlertDialog.Builder#setTitle setTitle()}.
+Untuk menentukan item daftar, panggil {@link
+android.app.AlertDialog.Builder#setItems setItems()}, dengan meneruskan larik.
+Atau, Anda bisa menetapkan daftar menggunakan {@link
+android.app.AlertDialog.Builder#setAdapter setAdapter()}. Hal ini memungkinkan Anda mendukung daftar
+dengan data dinamis (seperti dari database) dengan menggunakan {@link android.widget.ListAdapter}.</p>
+
+<p>Jika Anda memilih untuk mendukung daftar dengan {@link android.widget.ListAdapter},
+selalu gunakan sebuah {@link android.support.v4.content.Loader} agar konten dimuat
+secara asinkron. Hal ini dijelaskan lebih jauh dalam panduan
+<a href="{@docRoot}guide/topics/ui/declaring-layout.html#AdapterViews">Membuat Layout
+dengan Adaptor</a> dan <a href="{@docRoot}guide/components/loaders.html">Loader</a>
+.</p>
+
+<p class="note"><strong>Catatan:</strong> Secara default, menyentuh sebuah item daftar akan menutup dialog,
+kecuali Anda menggunakan salah satu daftar pilihan persisten berikut ini.</p>
+
+<div class="figure" style="width:290px;margin:-30px 0 0 40px">
+<img src="{@docRoot}images/ui/dialog_checkboxes.png" />
+<p class="img-caption"><strong>Gambar 4.</strong>
+Daftar item pilihan ganda.</p>
+</div>
+
+
+<h4 id="Checkboxes">Menambahkan daftar pilihan ganda atau pilihan tunggal persisten</h4>
+
+<p>Untuk menambahkan daftar item pilihan ganda (kotak cek) atau
+item pilihan tunggal (tombol radio), gunakan masing-masing metode
+{@link android.app.AlertDialog.Builder#setMultiChoiceItems(Cursor,String,String,
+DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()}, atau
+{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener)
+setSingleChoiceItems()}.</p>
+
+<p>Misalnya, berikut ini cara membuat daftar pilihan ganda seperti
+yang ditampilkan dalam gambar 4 yang menyimpan item
+yang dipilih dalam {@link java.util.ArrayList}:</p>
+
+<pre style="clear:right">
+&#64;Override
+public Dialog onCreateDialog(Bundle savedInstanceState) {
+    mSelectedItems = new ArrayList();  // Where we track the selected items
+    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+    // Set the dialog title
+    builder.setTitle(R.string.pick_toppings)
+    // Specify the list array, the items to be selected by default (null for none),
+    // and the listener through which to receive callbacks when items are selected
+           .setMultiChoiceItems(R.array.toppings, null,
+                      new DialogInterface.OnMultiChoiceClickListener() {
+               &#64;Override
+               public void onClick(DialogInterface dialog, int which,
+                       boolean isChecked) {
+                   if (isChecked) {
+                       // If the user checked the item, add it to the selected items
+                       mSelectedItems.add(which);
+                   } else if (mSelectedItems.contains(which)) {
+                       // Else, if the item is already in the array, remove it
+                       mSelectedItems.remove(Integer.valueOf(which));
+                   }
+               }
+           })
+    // Set the action buttons
+           .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+               &#64;Override
+               public void onClick(DialogInterface dialog, int id) {
+                   // User clicked OK, so save the mSelectedItems results somewhere
+                   // or return them to the component that opened the dialog
+                   ...
+               }
+           })
+           .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+               &#64;Override
+               public void onClick(DialogInterface dialog, int id) {
+                   ...
+               }
+           });
+
+    return builder.create();
+}
+</pre>
+
+<p>Walaupun daftar tradisional maupun daftar dengan tombol radio
+menyediakan tindakan "pilihan tunggal", Anda harus menggunakan {@link
+android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener)
+setSingleChoiceItems()} jika ingin mempertahankan pilihan pengguna.
+Yakni, jika nanti membuka dialog lagi untuk menunjukkan pilihan pengguna,
+maka Anda perlu membuat daftar dengan tombol radio.</p>
+
+
+
+
+
+<h3 id="CustomLayout">Membuat Layout Custom</h3>
+
+<div class="figure" style="width:290px;margin:-30px 0 0 40px">
+<img src="{@docRoot}images/ui/dialog_custom.png" alt="" />
+<p class="img-caption"><strong>Gambar 5.</strong> Layout dialog custom.</p>
+</div>
+
+<p>Jika Anda menginginkan layout custom dalam dialog, buatlah layout dan tambahkan ke
+{@link android.app.AlertDialog} dengan memanggil {@link
+android.app.AlertDialog.Builder#setView setView()} pada objek {@link
+android.app.AlertDialog.Builder} Anda.</p>
+
+<p>Secara default, layout custom akan mengisi jendela dialog, namun Anda masih bisa
+menggunakan metode {@link android.app.AlertDialog.Builder} untuk menambahkan tombol dan judul.</p>
+
+<p>Misalnya, berikut ini adalah file layout untuk dialog dalam Gambar 5:</p>
+
+<p style="clear:right" class="code-caption">res/layout/dialog_signin.xml</p>
+<pre>
+&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+    &lt;ImageView
+        android:src="@drawable/header_logo"
+        android:layout_width="match_parent"
+        android:layout_height="64dp"
+        android:scaleType="center"
+        android:background="#FFFFBB33"
+        android:contentDescription="@string/app_name" />
+    &lt;EditText
+        android:id="@+id/username"
+        android:inputType="textEmailAddress"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dp"
+        android:layout_marginLeft="4dp"
+        android:layout_marginRight="4dp"
+        android:layout_marginBottom="4dp"
+        android:hint="@string/username" />
+    &lt;EditText
+        android:id="@+id/password"
+        android:inputType="textPassword"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="4dp"
+        android:layout_marginLeft="4dp"
+        android:layout_marginRight="4dp"
+        android:layout_marginBottom="16dp"
+        android:fontFamily="sans-serif"
+        android:hint="@string/password"/>
+&lt;/LinearLayout>
+</pre>
+
+<p class="note"><strong>Tip:</strong> Secara default, bila Anda telah mengatur sebuah elemen {@link android.widget.EditText}
+agar menggunakan tipe input {@code "textPassword"}, keluarga font akan diatur ke spasi tunggal, sehingga
+Anda harus mengubah keluarga font ke {@code "sans-serif"} sehingga kedua bidang teks menggunakan
+gaya font yang cocok.</p>
+
+<p>Untuk memekarkan layout dalam {@link android.support.v4.app.DialogFragment} Anda,
+ambillah {@link android.view.LayoutInflater} dengan
+{@link android.app.Activity#getLayoutInflater()} dan panggil
+{@link android.view.LayoutInflater#inflate inflate()}, dengan parameter pertama
+adalah ID sumber daya layout dan parameter kedua adalah tampilan induk untuk layout.
+Selanjutnya Anda bisa memanggil {@link android.app.AlertDialog#setView setView()}
+untuk menempatkan layout dalam dialog.</p>
+
+<pre>
+&#64;Override
+public Dialog onCreateDialog(Bundle savedInstanceState) {
+    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+    // Get the layout inflater
+    LayoutInflater inflater = getActivity().getLayoutInflater();
+
+    // Inflate and set the layout for the dialog
+    // Pass null as the parent view because its going in the dialog layout
+    builder.setView(inflater.inflate(R.layout.dialog_signin, null))
+    // Add action buttons
+           .setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
+               &#64;Override
+               public void onClick(DialogInterface dialog, int id) {
+                   // sign in the user ...
+               }
+           })
+           .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+               public void onClick(DialogInterface dialog, int id) {
+                   LoginDialogFragment.this.getDialog().cancel();
+               }
+           });
+    return builder.create();
+}
+</pre>
+
+<div class="note">
+<p><strong>Tip:</strong> Jika Anda menginginkan dialog custom,
+Anda bisa menampilkan {@link android.app.Activity} sebagai dialog
+daripada menggunakan API {@link android.app.Dialog}. Cukup buat satu aktivitas dan mengatur temanya ke
+{@link android.R.style#Theme_Holo_Dialog Theme.Holo.Dialog}
+di elemen manifes <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
+&lt;activity&gt;}</a>:</p>
+
+<pre>
+&lt;activity android:theme="&#64;android:style/Theme.Holo.Dialog" >
+</pre>
+<p>Demikian saja. Aktivitas sekarang ditampilkan dalam jendela dialog, sebagai ganti layar penuh.</p>
+</div>
+
+
+
+<h2 id="PassingEvents">Meneruskan Kejadian Kembali ke Host Dialog</h2>
+
+<p>Bila pengguna menyentuh salah satu tombol tindakan dialog atau memilih satu item dari daftarnya,
+{@link android.support.v4.app.DialogFragment} Anda bisa melakukan sendiri tindakan yang diperlukan
+, namun sering kali Anda perlu mengirim kejadian itu ke aktivitas atau fragmen yang
+membuka dialog. Caranya, definisikan antarmuka dengan sebuah metode untuk masing-masing tipe kejadian klik.
+Lalu implementasikan antarmuka itu dalam komponen host yang akan
+menerima kejadian tindakan dari dialog.</p>
+
+<p>Misalnya, berikut ini adalah {@link android.support.v4.app.DialogFragment} yang mendefinisikan
+antarmuka yang akan digunakan untuk mengirim kembali suatu kejadian ke aktivitas host:</p>
+
+<pre>
+public class NoticeDialogFragment extends DialogFragment {
+
+    /* The activity that creates an instance of this dialog fragment must
+     * implement this interface in order to receive event callbacks.
+     * Each method passes the DialogFragment in case the host needs to query it. */
+    public interface NoticeDialogListener {
+        public void onDialogPositiveClick(DialogFragment dialog);
+        public void onDialogNegativeClick(DialogFragment dialog);
+    }
+
+    // Use this instance of the interface to deliver action events
+    NoticeDialogListener mListener;
+
+    // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
+    &#64;Override
+    public void onAttach(Activity activity) {
+        super.onAttach(activity);
+        // Verify that the host activity implements the callback interface
+        try {
+            // Instantiate the NoticeDialogListener so we can send events to the host
+            mListener = (NoticeDialogListener) activity;
+        } catch (ClassCastException e) {
+            // The activity doesn't implement the interface, throw exception
+            throw new ClassCastException(activity.toString()
+                    + " must implement NoticeDialogListener");
+        }
+    }
+    ...
+}
+</pre>
+
+<p>Aktivitas yang menjadi host dialog tersebut akan membuat instance dialog
+dengan konstruktor fragmen dialog dan menerima kejadian dialog
+melalui implementasi antarmuka {@code NoticeDialogListener}:</p>
+
+<pre>
+public class MainActivity extends FragmentActivity
+                          implements NoticeDialogFragment.NoticeDialogListener{
+    ...
+
+    public void showNoticeDialog() {
+        // Create an instance of the dialog fragment and show it
+        DialogFragment dialog = new NoticeDialogFragment();
+        dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
+    }
+
+    // The dialog fragment receives a reference to this Activity through the
+    // Fragment.onAttach() callback, which it uses to call the following methods
+    // defined by the NoticeDialogFragment.NoticeDialogListener interface
+    &#64;Override
+    public void onDialogPositiveClick(DialogFragment dialog) {
+        // User touched the dialog's positive button
+        ...
+    }
+
+    &#64;Override
+    public void onDialogNegativeClick(DialogFragment dialog) {
+        // User touched the dialog's negative button
+        ...
+    }
+}
+</pre>
+
+<p>Karena aktivitas host mengimplementasikan {@code NoticeDialogListener}&mdash;yang
+diberlakukan oleh metode callback {@link android.support.v4.app.Fragment#onAttach onAttach()}
+di atas,&mdash;fragmen dialog bisa menggunakan
+metode callback antarmuka untuk mengirimkan kejadian klik ke aktivitas:</p>
+
+<pre>
+public class NoticeDialogFragment extends DialogFragment {
+    ...
+
+    &#64;Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        // Build the dialog and set up the button click handlers
+        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        builder.setMessage(R.string.dialog_fire_missiles)
+               .setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
+                   public void onClick(DialogInterface dialog, int id) {
+                       // Send the positive button event back to the host activity
+                       mListener.onDialogPositiveClick(NoticeDialogFragment.this);
+                   }
+               })
+               .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+                   public void onClick(DialogInterface dialog, int id) {
+                       // Send the negative button event back to the host activity
+                       mListener.onDialogNegativeClick(NoticeDialogFragment.this);
+                   }
+               });
+        return builder.create();
+    }
+}
+</pre>
+
+
+
+<h2 id="ShowingADialog">Menampilkan Dialog</h2>
+
+<p>Bila Anda ingin menampilkan dialog, buatlah instance {@link
+android.support.v4.app.DialogFragment} dan panggil {@link android.support.v4.app.DialogFragment#show
+show()}, dengan meneruskan {@link android.support.v4.app.FragmentManager} dan nama tag
+untuk fragmen dialognya.</p>
+
+<p>Anda bisa mendapatkan {@link android.support.v4.app.FragmentManager} dengan memanggil
+{@link android.support.v4.app.FragmentActivity#getSupportFragmentManager()} dari
+ {@link android.support.v4.app.FragmentActivity} atau {@link
+android.support.v4.app.Fragment#getFragmentManager()} dari {@link
+android.support.v4.app.Fragment}. Misalnya:</p>
+
+<pre>
+public void confirmFireMissiles() {
+    DialogFragment newFragment = new FireMissilesDialogFragment();
+    newFragment.show(getSupportFragmentManager(), "missiles");
+}
+</pre>
+
+<p>Argumen kedua, {@code "missiles"}, adalah nama tag unik yang digunakan sistem untuk menyimpan
+dan memulihkan status fragmen bila diperlukan. Tag ini juga memungkinkan Anda mendapatkan handle ke
+fragmen dengan memanggil {@link android.support.v4.app.FragmentManager#findFragmentByTag
+findFragmentByTag()}.</p>
+
+
+
+
+<h2 id="FullscreenDialog">Menampilkan Dialog sebagai Layar Penuh atau Fragmen Tertanam</h2>
+
+<p>Anda mungkin memiliki desain UI yang di dalamnya Anda ingin UI muncul sebagai dialog dalam beberapa
+situasi, namun sebagai layar penuh atau fragmen tertanam dalam situasi lain (mungkin bergantung pada apakah
+perangkat memiliki layar besar atau layar kecil). Kelas {@link android.support.v4.app.DialogFragment}
+menawarkan fleksibilitas ini karena masih bisa berperilaku sebagai {@link
+android.support.v4.app.Fragment} yang bisa ditanamkan.</p>
+
+<p>Akan tetapi, dalam hal ini Anda tidak bisa menggunakan {@link android.app.AlertDialog.Builder AlertDialog.Builder}
+atau objek {@link android.app.Dialog} lain untuk membangun dialog. Jika
+Anda ingin {@link android.support.v4.app.DialogFragment}
+bisa ditanamkan, Anda harus mendefinisikan dialog UI dalam layout, lalu memuat layout itu dalam metode callback
+{@link android.support.v4.app.DialogFragment#onCreateView
+onCreateView()}.</p>
+
+<p>Berikut ini adalah contoh {@link android.support.v4.app.DialogFragment} yang bisa muncul sebagai
+dialog maupun fragmen yang bisa ditanamkan (menggunakan layout bernama <code>purchase_items.xml</code>):</p>
+
+<pre>
+public class CustomDialogFragment extends DialogFragment {
+    /** The system calls this to get the DialogFragment's layout, regardless
+        of whether it's being displayed as a dialog or an embedded fragment. */
+    &#64;Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        // Inflate the layout to use as dialog or embedded fragment
+        return inflater.inflate(R.layout.purchase_items, container, false);
+    }
+
+    /** The system calls this only when creating the layout in a dialog. */
+    &#64;Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        // The only reason you might override this method when using onCreateView() is
+        // to modify any dialog characteristics. For example, the dialog includes a
+        // title by default, but your custom layout might not need it. So here you can
+        // remove the dialog title, but you must call the superclass to get the Dialog.
+        Dialog dialog = super.onCreateDialog(savedInstanceState);
+        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+        return dialog;
+    }
+}
+</pre>
+
+<p>Dan berikut ini adalah beberapa kode yang memutuskan apakah akan menampilkan fragmen sebagai dialog
+atau UI layar penuh, berdasarkan ukuran layar:</p>
+
+<pre>
+public void showDialog() {
+    FragmentManager fragmentManager = getSupportFragmentManager();
+    CustomDialogFragment newFragment = new CustomDialogFragment();
+
+    if (mIsLargeLayout) {
+        // The device is using a large layout, so show the fragment as a dialog
+        newFragment.show(fragmentManager, "dialog");
+    } else {
+        // The device is smaller, so show the fragment fullscreen
+        FragmentTransaction transaction = fragmentManager.beginTransaction();
+        // For a little polish, specify a transition animation
+        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
+        // To make it fullscreen, use the 'content' root view as the container
+        // for the fragment, which is always the root view for the activity
+        transaction.add(android.R.id.content, newFragment)
+                   .addToBackStack(null).commit();
+    }
+}
+</pre>
+
+<p>Untuk informasi selengkapnya tentang melakukan transaksi fragmen, lihat panduan
+<a href="{@docRoot}guide/components/fragments.html">Fragmen</a>.</p>
+
+<p>Dalam contoh ini, nilai boolean <code>mIsLargeLayout</code> menentukan apakah perangkat saat ini
+harus menggunakan desain layout besar aplikasi (dan dengan demikian menampilkan fragmen ini sebagai dialog, bukan
+layar penuh). Cara terbaik untuk mengatur jenis boolean ini adalah mendeklarasikan
+<a href="{@docRoot}guide/topics/resources/more-resources.html#Bool">nilai sumber daya boolean</a>
+dengan nilai <a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">sumber daya alternatif</a> untuk berbagai ukuran layar. Misalnya, berikut ini adalah dua
+versi sumber daya boolean untuk berbagai ukuran layar:</p>
+
+<p class="code-caption">res/values/bools.xml</p>
+<pre>
+&lt;!-- Default boolean values -->
+&lt;resources>
+    &lt;bool name="large_layout">false&lt;/bool>
+&lt;/resources>
+</pre>
+
+<p class="code-caption">res/values-large/bools.xml</p>
+<pre>
+&lt;!-- Large screen boolean values -->
+&lt;resources>
+    &lt;bool name="large_layout">true&lt;/bool>
+&lt;/resources>
+</pre>
+
+<p>Selanjutnya Anda bisa menetapkan nilai {@code mIsLargeLayout} selama
+metode {@link android.app.Activity#onCreate onCreate()} aktivitas:</p>
+
+<pre>
+boolean mIsLargeLayout;
+
+&#64;Override
+public void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    setContentView(R.layout.activity_main);
+
+    mIsLargeLayout = getResources().getBoolean(R.bool.large_layout);
+}
+</pre>
+
+
+
+<h3 id="ActivityAsDialog">Menampilkan aktivitas sebagai dialog pada layar besar</h3>
+
+<p>Sebagai ganti menampilkan dialog berupa UI layar penuh saat di layar kecil, Anda bisa memperoleh
+hasil yang sama dengan menampilkan {@link android.app.Activity} sebagai dialog saat di
+layar besar. Pendekatan yang Anda pilih bergantung pada desain aplikasi, namun
+menampilkan aktivitas sebagai dialog sering kali berguna bila aplikasi Anda sudah didesain untuk
+layar kecil dan Anda ingin meningkatkan pengalaman pada tablet dengan menampilkan aktivitas berjangka pendek
+sebagai dialog.</p>
+
+<p>Untuk menampilkan aktivitas sebagai dialog hanya saat di layar besar,
+terapkan tema {@link android.R.style#Theme_Holo_DialogWhenLarge Theme.Holo.DialogWhenLarge}
+ pada elemen manifes <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
+&lt;activity&gt;}</a>:</p>
+
+<pre>
+&lt;activity android:theme="&#64;android:style/Theme.Holo.DialogWhenLarge" >
+</pre>
+
+<p>Untuk informasi selengkapnya tentang mengatur gaya aktivitas Anda dengan tema, lihat panduan <a href="{@docRoot}guide/topics/ui/themes.html">Gaya dan Tema</a>.</p>
+
+
+
+<h2 id="DismissingADialog">Menutup Dialog</h2>
+
+<p>Bila pengguna menyentuh salah satu tombol tindakan yang dibuat dengan
+{@link android.app.AlertDialog.Builder}, sistem akan menutup dialog untuk Anda.</p>
+
+<p>Sistem juga menutup dialog bila pengguna menyentuh sebuah item dalam daftar dialog, kecuali
+bila daftar itu menggunakan tombol radio atau kotak cek. Jika tidak, Anda bisa menutup dialog secara manual
+dengan memanggil {@link android.support.v4.app.DialogFragment#dismiss()} pada {@link
+android.support.v4.app.DialogFragment} Anda.</p>
+
+<p>Jika Anda perlu melakukan
+tindakan tertentu saat dialog menghilang, Anda bisa menerapkan metode {@link
+android.support.v4.app.DialogFragment#onDismiss onDismiss()} dalam {@link
+android.support.v4.app.DialogFragment} Anda.</p>
+
+<p>Anda juga bisa <em>membatalkan</em> dialog. Ini merupakan kejadian khusus yang menunjukkan bahwa pengguna
+secara eksplisit meninggalkan dialog tanpa menyelesaikan tugas. Hal ini terjadi jika pengguna menekan tombol
+<em>Back</em>, menyentuh layar di luar area dialog,
+atau jika Anda secara eksplisit memanggil {@link android.app.Dialog#cancel()} pada {@link
+android.app.Dialog} (seperti saat merespons tombol "Cancel" dalam dialog).</p>
+
+<p>Seperti yang ditampilkan dalam contoh di atas, Anda bisa merespons kejadian batal dengan menerapkan
+{@link android.support.v4.app.DialogFragment#onCancel onCancel()} dalam kelas {@link
+android.support.v4.app.DialogFragment} Anda.</p>
+
+<p class="note"><strong>Catatan:</strong> Sistem akan memanggil
+{@link android.support.v4.app.DialogFragment#onDismiss onDismiss()} pada tiap kejadian yang
+memanggil callback {@link android.support.v4.app.DialogFragment#onCancel onCancel()}. Akan tetapi,
+jika Anda memanggil {@link android.app.Dialog#dismiss Dialog.dismiss()} atau {@link
+android.support.v4.app.DialogFragment#dismiss DialogFragment.dismiss()},
+sistem akan memanggil {@link android.support.v4.app.DialogFragment#onDismiss onDismiss()} <em>namun
+bukan</em> {@link android.support.v4.app.DialogFragment#onCancel onCancel()}. Jadi biasanya Anda harus
+memanggil {@link android.support.v4.app.DialogFragment#dismiss dismiss()} bila pengguna menekan tombol
+<em>positif</em> dalam dialog untuk menghilangkan tampilan dialog.</p>
+
+
diff --git a/docs/html-intl/intl/id/guide/topics/ui/menus.jd b/docs/html-intl/intl/id/guide/topics/ui/menus.jd
new file mode 100644
index 0000000..1ee0244
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/ui/menus.jd
@@ -0,0 +1,1031 @@
+page.title=Menu
+parent.title=Antarmuka Pengguna
+parent.link=index.html
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>Dalam dokumen ini</h2>
+<ol>
+  <li><a href="#xml">Mendefinisikan Menu dalam XML</a></li>
+  <li><a href="#options-menu">Membuat Menu Opsi</a>
+    <ol>
+      <li><a href="#RespondingOptionsMenu">Menangani kejadian klik</a></li>
+      <li><a href="#ChangingTheMenu">Mengubah item menu saat runtime</a></li>
+    </ol>
+  </li>
+  <li><a href="#context-menu">Membuat Menu Kontekstual</a>
+    <ol>
+      <li><a href="#FloatingContextMenu">Membuat menu konteks mengambang</a></li>
+      <li><a href="#CAB">Menggunakan mode tindakan kontekstual</a></li>
+    </ol>
+  </li>
+  <li><a href="#PopupMenu">Membuat Menu Popup</a>
+    <ol>
+      <li><a href="#PopupEvents">Menangani kejadian klik</a></li>
+    </ol>
+  </li>
+  <li><a href="#groups">Membuat Grup Menu</a>
+    <ol>
+      <li><a href="#checkable">Menggunakan item menu yang bisa diberi tanda cek</a></li>
+    </ol>
+  </li>
+  <li><a href="#intents">Menambahkan Item Menu Berdasarkan Intent</a>
+    <ol>
+      <li><a href="#AllowingToAdd">Memungkinkan aktivitas Anda ditambahkan ke menu lain</a></li>
+    </ol>
+  </li>
+</ol>
+
+  <h2>Kelas-kelas utama</h2>
+  <ol>
+    <li>{@link android.view.Menu}</li>
+    <li>{@link android.view.MenuItem}</li>
+    <li>{@link android.view.ContextMenu}</li>
+    <li>{@link android.view.ActionMode}</li>
+  </ol>
+
+  <h2>Lihat juga</h2>
+  <ol>
+    <li><a href="{@docRoot}guide/topics/ui/actionbar.html">Action-Bar</a></li>
+    <li><a href="{@docRoot}guide/topics/resources/menu-resource.html">Sumber Daya Menu</a></li>
+    <li><a href="http://android-developers.blogspot.com/2012/01/say-goodbye-to-menu-button.html">Ucapkan
+Selamat Tinggal pada Tombol Menu</a></li>
+  </ol>
+</div>
+</div>
+
+<p>Menu adalah komponen antarmuka pengguna yang lazim dalam banyak tipe aplikasi. Untuk menyediakan pengalaman pengguna yang sudah akrab
+dan konsisten, Anda harus menggunakan API {@link android.view.Menu} untuk menyajikan
+tindakan dan opsi lain dalam aktivitas kepada pengguna.</p>
+
+<p>Mulai dengan Android 3.0 (API level 11), perangkat berbasis Android tidak perlu lagi
+menyediakan tombol <em>Menu</em> tersendiri. Dengan perubahan ini, aplikasi Android harus bermigrasi dari
+dependensi pada panel menu 6 item biasa, dan sebagai ganti menyediakan action-bar untuk menyajikan
+berbagai tindakan pengguna yang lazim.</p>
+
+<p>Walaupun desain dan pengalaman pengguna untuk sebagian item menu telah berubah, semantik untuk mendefinisikan
+serangkaian tindakan dan opsi masih berdasarkan pada API {@link android.view.Menu}. Panduan ini
+menampilkan cara membuat tiga tipe dasar penyajian menu atau tindakan pada semua
+versi Android:</p>
+
+<dl>
+  <dt><strong>Menu opsi dan action-bar</strong></dt>
+    <dd><a href="#options-menu">Menu opsi</a> adalah kumpulan item menu utama untuk suatu
+aktivitas. Inilah tempat Anda harus menempatkan tindakan yang berdampak global pada aplikasi, seperti
+"Cari", "Tulis email", dan "Pengaturan".
+  <p>Jika Anda mengembangkan aplikasi untuk Android 2.3 atau yang lebih rendah, pengguna bisa
+menampilkan panel menu opsi dengan menekan tombol <em>Menu</em>.</p>
+  <p>Pada Android 3.0 dan yang lebih tinggi, item menu opsi disajikan melalui <a href="{@docRoot}guide/topics/ui/actionbar.html">action-bar</a> sebagai kombinasi item tindakan
+di layar dan opsi overflow. Mulai dengan Android 3.0, tombol <em>Menu</em> dihilangkan (sebagian
+perangkat
+tidak memilikinya), sehingga Anda harus bermigrasi ke penggunaan action-bar untuk menyediakan akses ke tindakan dan
+opsi lainnya.</p>
+  <p>Lihat bagian tentang <a href="#options-menu">Membuat Menu Opsi</a>.</p>
+    </dd>
+
+  <dt><strong>Menu konteks dan mode tindakan kontekstual</strong></dt>
+
+   <dd>Menu konteks adalah <a href="#FloatingContextMenu">menu mengambang</a> yang muncul saat
+pengguna mengklik lama pada suatu elemen. Menu ini menyediakan tindakan yang memengaruhi konten atau
+bingkai konteks yang dipilih.
+  <p>Saat mengembangkan aplikasi untuk Android 3.0 dan yang lebih tinggi, sebagai gantinya Anda harus menggunakan <a href="#CAB">mode tindakan kontekstual</a> untuk memungkinkan tindakan pada konten yang dipilih. Mode ini menampilkan
+item tindakan yang memengaruhi konten yang dipilih dalam baris di bagian atas layar dan memungkinkan pengguna
+memilih beberapa item sekaligus.</p>
+  <p>Lihat bagian tentang <a href="#context-menu">Membuat Menu Kontekstual</a>.</p>
+</dd>
+
+  <dt><strong>Menu popup</strong></dt>
+    <dd>Menu popup menampilkan daftar item secara vertikal yang dipasang pada tampilan yang
+memanggil menu. Ini cocok untuk menyediakan kelebihan tindakan yang terkait dengan konten tertentu atau
+untuk menyediakan opsi bagi bagian kedua dari suatu perintah. Tindakan di menu popup
+<strong>tidak</strong> boleh memengaruhi secara langsung konten yang bersangkutan&mdash;yang diperuntukkan bagi
+tindakan kontekstual. Melainkan, menu popup adalah untuk tindakan tambahan yang terkait dengan wilayah konten dalam
+aktivitas Anda.
+  <p>Lihat bagian tentang <a href="#PopupMenu">Membuat Menu Popup</a>.</p>
+</dd>
+</dl>
+
+
+
+<h2 id="xml">Mendefinisikan Menu dalam XML</h2>
+
+<p>Untuk semua tipe menu, Android menyediakan sebuah format XML standar untuk mendefinisikan item menu.
+Sebagai ganti membuat menu dalam kode aktivitas, Anda harus mendefinisikan menu dan semua itemnya dalam
+<a href="{@docRoot}guide/topics/resources/menu-resource.html">sumber daya menu</a> XML. Anda kemudian bisa
+memekarkan sumber daya menu (memuatnya sebagai objek {@link android.view.Menu}) dalam aktivitas atau
+fragmen.</p>
+
+<p>Menggunakan sumber daya menu adalah praktik yang baik karena beberapa alasan:</p>
+<ul>
+  <li>Memvisualisasikan struktur menu dalam XML menjadi lebih mudah.</li>
+  <li>Cara ini memisahkan konten untuk menu dari kode perilaku aplikasi Anda.</li>
+  <li>Cara ini memungkinkan Anda membuat konfigurasi menu alternatif untuk berbagai versi platform,
+ukuran layar, dan konfigurasi lainnya dengan memanfaatkan kerangka kerja <a href="{@docRoot}guide/topics/resources/index.html">sumber daya aplikasi</a>.</li>
+</ul>
+
+<p>Untuk mendefinisikan menu, buatlah sebuah file XML dalam direktori <code>res/menu/</code>
+proyek dan buat menu dengan elemen-elemen berikut:</p>
+<dl>
+  <dt><code>&lt;menu></code></dt>
+    <dd>Mendefinisikan {@link android.view.Menu}, yang merupakan sebuah kontainer untuk item menu. Elemen
+<code>&lt;menu></code> harus menjadi simpul akar untuk file dan bisa menampung salah satu atau beberapa dari elemen
+<code>&lt;item></code> dan <code>&lt;group></code>.</dd>
+
+  <dt><code>&lt;item></code></dt>
+    <dd>Membuat {@link android.view.MenuItem}, yang mewakili satu item menu. Elemen ini
+bisa berisi elemen <code>&lt;menu></code> tersarang guna untuk membuat submenu.</dd>
+
+  <dt><code>&lt;group></code></dt>
+    <dd>Kontainer opsional tak terlihat untuk elemen-elemen {@code &lt;item&gt;}. Kontainer ini memungkinkan Anda
+mengelompokkan item menu untuk berbagi properti seperti status aktif dan visibilitas. Untuk informasi
+selengkapnya, lihat bagian tentang <a href="#groups">Membuat Grup Menu</a>.</dd>
+</dl>
+
+
+<p>Berikut ini adalah contoh menu bernama <code>game_menu.xml</code>:</p>
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
+    &lt;item android:id="@+id/new_game"
+          android:icon="@drawable/ic_new_game"
+          android:title="@string/new_game"
+          android:showAsAction="ifRoom"/&gt;
+    &lt;item android:id="@+id/help"
+          android:icon="@drawable/ic_help"
+          android:title="@string/help" /&gt;
+&lt;/menu&gt;
+</pre>
+
+<p>Elemen <code>&lt;item></code> mendukung beberapa atribut yang bisa Anda gunakan untuk mendefinisikan penampilan dan perilaku
+item. Item menu di atas mencakup atribut berikut:</p>
+
+<dl>
+  <dt>{@code android:id}</dt>
+    <dd>ID sumber daya unik bagi item, yang memungkinkan aplikasi mengenali item
+bila pengguna memilihnya.</dd>
+  <dt>{@code android:icon}</dt>
+    <dd>Acuan ke drawable untuk digunakan sebagai ikon item.</dd>
+  <dt>{@code android:title}</dt>
+    <dd>Acuan ke string untuk digunakan sebagai judul item.</dd>
+  <dt>{@code android:showAsAction}</dt>
+    <dd>Menetapkan waktu dan cara item ini muncul sebagai item tindakan di <a href="{@docRoot}guide/topics/ui/actionbar.html">action-bar</a>.</dd>
+</dl>
+
+<p>Ini adalah atribut-atribut terpenting yang harus Anda gunakan, namun banyak lagi yang tersedia.
+Untuk informasi tentang semua atribut yang didukung, lihat dokumen <a href="{@docRoot}guide/topics/resources/menu-resource.html">Sumber Daya Menu</a>.</p>
+
+<p>Anda bisa menambahkan submenu ke sebuah item di menu (kecuali submenu) apa saja dengan menambahkan elemen {@code &lt;menu&gt;}
+sebagai anak {@code &lt;item&gt;}. Submenu berguna saat aplikasi Anda memiliki banyak
+fungsi yang bisa ditata ke dalam topik-topik, seperti item dalam sebuah baris menu aplikasi PC (File,
+Edit, Lihat, dsb.). Misalnya:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
+    &lt;item android:id="@+id/file"
+          android:title="@string/file" &gt;
+        &lt;!-- "file" submenu --&gt;
+        &lt;menu&gt;
+            &lt;item android:id="@+id/create_new"
+                  android:title="@string/create_new" /&gt;
+            &lt;item android:id="@+id/open"
+                  android:title="@string/open" /&gt;
+        &lt;/menu&gt;
+    &lt;/item&gt;
+&lt;/menu&gt;
+</pre>
+
+<p>Untuk menggunakan menu dalam aktivitas, Anda perlu memekarkan sumber daya menu (mengonversi sumber daya XML
+menjadi objek yang bisa diprogram) dengan menggunakan {@link android.view.MenuInflater#inflate(int,Menu)
+MenuInflater.inflate()}. Di bagian berikut, Anda akan melihat cara memekarkan menu untuk tiap
+tipe menu.</p>
+
+
+
+<h2 id="options-menu">Membuat Menu Opsi</h2>
+
+<div class="figure" style="width:200px;margin:0">
+  <img src="{@docRoot}images/options_menu.png" height="333" alt="" />
+  <p class="img-caption"><strong>Gambar 1.</strong> Menu opsi di
+Browser, pada Android 2.3.</p>
+</div>
+
+<p>Menu opsi adalah tempat Anda harus menyertakan tindakan dan opsi lain yang relevan dengan
+konteks aktivitas saat ini, seperti "Cari", "Tulis email", dan "Pengaturan".</p>
+
+<p>Tempat item dalam menu opsi muncul di layar bergantung pada versi aplikasi yang Anda
+kembangkan:</p>
+
+<ul>
+  <li>Jika Anda mengembangkan aplikasi untuk <strong>Android 2.3.x (API level 10) atau
+yang lebih rendah</strong>, konten menu opsi muncul pada bagian bawah layar bila pengguna
+menekan tombol <em>Menu</em>, seperti yang ditampilkan dalam gambar 1. Bila dibuka, bagian yang terlihat pertama adalah
+menu
+ikon, yang menampung hingga enam item menu. Jika menu Anda menyertakan lebih dari enam item, Android akan meletakkan
+item keenam dan sisanya ke dalam menu kelebihan, yang bisa dibuka pengguna dengan memilih
+<em>More</em>.</li>
+
+  <li>Jika Anda mengembangkan aplikasi untuk <strong>Android 3.0 (API level 11) dan
+yang lebih tinggi</strong>, item menu opsi tersedia dalam <a href="{@docRoot}guide/topics/ui/actionbar.html">action-bar</a>. Secara default, sistem
+meletakkan semua item dalam kelebihan tindakan, yang bisa ditampilkan pengguna dengan ikon kelebihan tindakan di
+sisi kanan action-bar (atau dengan menekan tombol <em>Menu</em> perangkat, jika tersedia). Untuk
+mengaktifkan
+akses cepat ke tindakan penting, Anda bisa mempromosikan beberapa item agar muncul pada action-bar dengan menambahkan
+{@code android:showAsAction="ifRoom"} ke elemen-elemen {@code &lt;item&gt;} yang bersangkutan (lihat gambar
+2). <p>Untuk informasi selengkapnya tentang item tindakan dan perilaku action-bar lainnya, lihat panduan <a href="{@docRoot}guide/topics/ui/actionbar.html">Action-Bar</a>. </p>
+<p class="note"><strong>Catatan:</strong> Sekalipun Anda <em>tidak</em> mengembangkan aplikasi untuk Android 3.0 atau
+yang lebih tinggi, Anda bisa membuat layout action-bar sendiri untuk mendapatkan efek serupa. Untuk contoh cara
+mendukung versi Android yang lebih lama dengan action-bar, lihat contoh <a href="{@docRoot}resources/samples/ActionBarCompat/index.html">Kompatibilitas Action-Bar</a>
+.</p>
+</li>
+</ul>
+
+<img src="{@docRoot}images/ui/actionbar.png" alt="" />
+<p class="img-caption"><strong>Gambar 2.</strong> Action-bar dari aplikasi <a href="{@docRoot}resources/samples/HoneycombGallery/index.html">Honeycomb Gallery</a>, yang menampilkan
+tab-tab navigasi dan item tindakan kamera (plus tombol kelebihan tindakan).</p>
+
+<p>Anda bisa mendeklarasikan item untuk menu opsi dari subkelas {@link android.app.Activity}
+atau subkelas {@link android.app.Fragment}. Jika aktivitas maupun fragmen Anda
+mendeklarasikan item menu opsi, keduanya akan dikombinasikan dalam UI. Item aktivitas akan muncul
+lebih dahulu, diikuti oleh item tiap fragmen sesuai dengan urutan penambahan fragmen ke
+aktivitas. Jika perlu, Anda bisa menyusun ulang item menu dengan atribut {@code android:orderInCategory}
+dalam setiap {@code &lt;item&gt;} yang perlu Anda pindahkan.</p>
+
+<p>Untuk menetapkan menu opsi suatu aktivitas, kesampingkan {@link
+android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} (fragmen-fragmen menyediakan
+callback {@link android.app.Fragment#onCreateOptionsMenu onCreateOptionsMenu()} sendiri). Dalam metode ini
+, Anda bisa memekarkan sumber daya menu (<a href="#xml">yang didefinisikan dalam XML</a>) menjadi {@link
+android.view.Menu} yang disediakan dalam callback. Misalnya:</p>
+
+<pre>
+&#64;Override
+public boolean onCreateOptionsMenu(Menu menu) {
+    MenuInflater inflater = {@link android.app.Activity#getMenuInflater()};
+    inflater.inflate(R.menu.game_menu, menu);
+    return true;
+}
+</pre>
+
+<p>Anda juga bisa menambahkan item menu dengan menggunakan {@link android.view.Menu#add(int,int,int,int)
+add()} dan mengambil item dengan {@link android.view.Menu#findItem findItem()} untuk merevisi propertinya
+dengan API {@link android.view.MenuItem}.</p>
+
+<p>Jika Anda mengembangkan aplikasi untuk Android 2.3.x dan yang lebih rendah, sistem akan memanggil {@link
+android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} untuk membuat menu opsi
+bila pengguna membuka menu untuk pertama kali. Jika Anda mengembangkan aplikasi untuk Android 3.0 dan yang lebih tinggi,
+sistem akan memanggil {@link android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} saat
+memulai aktivitas, untuk menampilkan item menu pada action-bar.</p>
+
+
+
+<h3 id="RespondingOptionsMenu">Menangani kejadian klik</h3>
+
+<p>Bila pengguna memilih item dari menu opsi (termasuk item tindakan dalam action-bar),
+sistem akan memanggil metode {@link android.app.Activity#onOptionsItemSelected(MenuItem)
+onOptionsItemSelected()} aktivitas Anda. Metode ini meneruskan {@link android.view.MenuItem} yang dipilih. Anda
+bisa mengidentifikasi item dengan memanggil {@link android.view.MenuItem#getItemId()}, yang menghasilkan
+ID unik untuk item menu itu (yang didefinisikan oleh atribut {@code android:id} dalam sumber daya menu atau dengan
+integer yang diberikan ke metode {@link android.view.Menu#add(int,int,int,int) add()}). Anda bisa mencocokkan
+ID ini dengan item menu yang diketahui untuk melakukan tindakan yang sesuai. Misalnya:</p>
+
+<pre>
+&#64;Override
+public boolean onOptionsItemSelected(MenuItem item) {
+    // Handle item selection
+    switch (item.getItemId()) {
+        case R.id.new_game:
+            newGame();
+            return true;
+        case R.id.help:
+            showHelp();
+            return true;
+        default:
+            return super.onOptionsItemSelected(item);
+    }
+}
+</pre>
+
+<p>Bila Anda berhasil menangani sebuah item menu, kembalikan {@code true}. Jika tidak menangani item menu
+, Anda harus memanggil implementasi superkelas {@link
+android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} (implementasi default
+menghasilkan false).</p>
+
+<p>Jika aktivitas Anda menyertakan fragmen, sistem akan memanggil lebih dahulu {@link
+android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} untuk aktivitas, kemudian
+untuk setiap fragmen (sesuai dengan urutan penambahan fragmen) hingga satu fragmen mengembalikan
+{@code true} atau semua fragmen telah dipanggil.</p>
+
+<p class="note"><strong>Tip:</strong> Android 3.0 menambahkan kemampuan mendefinisikan perilaku on-click
+untuk item menu dalam XML, dengan menggunakan atribut {@code android:onClick}. Nilai atribut
+harus berupa nama metode yang didefinisikan aktivitas dengan menggunakan menu. Metode
+harus bersifat publik dan menerima satu parameter {@link android.view.MenuItem}&mdash;bila sistem
+memanggilnya, metode ini akan meneruskan item menu yang dipilih. Untuk informasi selengkapnya dan contoh, lihat dokumen <a href="{@docRoot}guide/topics/resources/menu-resource.html">Sumber Daya Menu</a>.</p>
+
+<p class="note"><strong>Tip:</strong> Jika aplikasi Anda berisi banyak aktivitas dan
+sebagian menyediakan menu opsi yang sama, pertimbangkan untuk membuat
+aktivitas yang tidak mengimplementasikan apa-apa kecuali metode {@link android.app.Activity#onCreateOptionsMenu(Menu)
+onCreateOptionsMenu()} dan {@link android.app.Activity#onOptionsItemSelected(MenuItem)
+onOptionsItemSelected()}. Kemudian perluas kelas ini untuk setiap aktivitas yang harus menggunakan
+menu opsi yang sama. Dengan begini, Anda bisa mengelola satu set kode untuk menangani tindakan menu
+dan setiap kelas turunan mewarisi perilaku menu.
+Jika ingin menambahkan item menu ke salah satu aktivitas turunan,
+kesampingkan {@link android.app.Activity#onCreateOptionsMenu(Menu)
+onCreateOptionsMenu()} dalam aktivitas itu. Panggil {@code super.onCreateOptionsMenu(menu)} agar
+item menu asli dibuat, kemudian tambahkan item menu yang baru dengan {@link
+android.view.Menu#add(int,int,int,int) menu.add()}. Anda juga bisa mengesampingkan
+perilaku superkelas untuk setiap item menu.</p>
+
+
+<h3 id="ChangingTheMenu">Mengubah item menu saat runtime</h3>
+
+<p>Setelah sistem memanggil {@link android.app.Activity#onCreateOptionsMenu(Menu)
+onCreateOptionsMenu()}, sistem akan mempertahankan instance {@link android.view.Menu} yang Anda tempatkan dan
+tidak akan memanggil {@link android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()}
+lagi kecuali menu diinvalidkan karena suatu alasan. Akan tetapi, Anda harus menggunakan {@link
+android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} hanya untuk membuat
+status menu awal dan tidak untuk membuat perubahan selama daur hidup aktivitas.</p>
+
+<p>Jika Anda ingin mengubah menu opsi berdasarkan
+kejadian yang terjadi selama daur hidup aktivitas, Anda bisa melakukannya dalam metode
+{@link android.app.Activity#onPrepareOptionsMenu(Menu) onPrepareOptionsMenu()}. Metode ini
+meneruskan objek {@link android.view.Menu} sebagaimana adanya saat ini sehingga Anda bisa mengubahnya,
+seperti menambah, menghapus, atau menonaktifkan item. (Fragmen juga menyediakan callback {@link
+android.app.Fragment#onPrepareOptionsMenu onPrepareOptionsMenu()}.)</p>
+
+<p>Pada Android 2.3.x dan yang lebih rendah, sistem akan memanggil {@link
+android.app.Activity#onPrepareOptionsMenu(Menu)
+onPrepareOptionsMenu()} setiap kali pengguna membuka menu opsi (menekan tombol <em>Menu</em>
+).</p>
+
+<p>Pada Android 3.0 dan yang lebih tinggi, menu opsi dianggap sebagai selalu terbuka saat item menu
+ditampilkan pada action-bar. Bila ada kejadian dan Anda ingin melakukan pembaruan menu, Anda harus
+memanggil {@link android.app.Activity#invalidateOptionsMenu invalidateOptionsMenu()} untuk meminta
+sistem memanggil {@link android.app.Activity#onPrepareOptionsMenu(Menu) onPrepareOptionsMenu()}.</p>
+
+<p class="note"><strong>Catatan:</strong>
+Anda tidak boleh mengubah item dalam menu opsi berdasarkan {@link android.view.View} yang saat ini
+difokus. Saat dalam mode sentuh (bila pengguna tidak sedang menggunakan trackball atau d-pad), tampilan
+tidak bisa mengambil fokus, sehingga Anda tidak boleh menggunakan fokus sebagai dasar untuk mengubah
+item dalam menu opsi. Jika Anda ingin menyediakan item menu yang peka konteks pada {@link
+android.view.View}, gunakan <a href="#context-menu">Menu Konteks</a>.</p>
+
+
+
+
+<h2 id="context-menu">Membuat Menu Kontekstual</h2>
+
+<div class="figure" style="width:420px;margin-top:-1em">
+  <img src="{@docRoot}images/ui/menu-context.png" alt="" />
+  <p class="img-caption"><strong>Gambar 3.</strong> Cuplikan layar menu konteks mengambang (kiri)
+dan action-bar kontekstual (kanan).</p>
+</div>
+
+<p>Menu kontekstual menawarkan tindakan yang memengaruhi item atau bingkai konteks tertentu dalam UI. Anda
+bisa menyediakan menu konteks untuk setiap tampilan, tetapi menu ini paling sering digunakan untuk item pada {@link
+android.widget.ListView}, {@link android.widget.GridView}, atau kumpulan tampilan lainnya yang bisa digunakan
+pengguna untuk melakukan tindakan langsung pada setiap item.</p>
+
+<p>Ada dua cara menyediakan tindakan kontekstual:</p>
+<ul>
+  <li>Dalam <a href="#FloatingContextMenu">menu konteks mengambang</a>. Menu muncul sebagai
+daftar item menu mengambang (serupa dengan dialog) bila pengguna mengklik lama (menekan dan
+menahan) pada tampilan yang mendeklarasikan dukungan bagi menu konteks. Pengguna bisa melakukan
+tindakan kontekstual pada satu item untuk setiap kalinya.</li>
+
+  <li>Dalam <a href="#CAB">mode tindakan kontekstual</a>. Mode ini adalah implementasi sistem
+{@link android.view.ActionMode} yang menampilkan <em>action-bar kontekstual</em> di bagian atas
+layar dengan item tindakan yang memengaruhi item(-item) yang dipilih. Bila mode ini aktif, pengguna
+bisa melakukan tindakan pada beberapa item sekaligus (jika aplikasi Anda mengizinkannya).</li>
+</ul>
+
+<p class="note"><strong>Catatan:</strong> Mode tindakan kontekstual tersedia pada Android 3.0 (API
+level 11) dan yang lebih tinggi dan merupakan teknik yang lebih disukai untuk menampilkan tindakan kontekstual bila
+tersedia. Jika aplikasi Anda mendukung versi yang lebih rendah daripada 3.0, maka Anda harus mundur ke
+menu konteks mengambang pada perangkat-perangkat itu.</p>
+
+
+<h3 id="FloatingContextMenu">Membuat menu konteks mengambang</h3>
+
+<p>Untuk menyediakan menu konteks mengambang:</p>
+<ol>
+  <li>Daftarkan {@link android.view.View} ke menu konteks yang harus dikaitkan dengan
+memanggil {@link android.app.Activity#registerForContextMenu(View) registerForContextMenu()} dan teruskan
+{@link android.view.View} ke menu itu.
+  <p>Jika aktivitas Anda menggunakan {@link android.widget.ListView} atau {@link android.widget.GridView} dan
+Anda ingin setiap item untuk menyediakan menu konteks yang sama, daftarkan semua item ke menu konteks dengan
+meneruskan {@link android.widget.ListView} atau {@link android.widget.GridView} ke {@link
+android.app.Activity#registerForContextMenu(View) registerForContextMenu()}.</p>
+</li>
+
+  <li>Implementasikan metode {@link
+android.view.View.OnCreateContextMenuListener#onCreateContextMenu onCreateContextMenu()}
+dalam {@link android.app.Activity} atau {@link android.app.Fragment} Anda.
+  <p>Bila tampilan yang terdaftar menerima kejadian klik-lama, sistem akan memanggil metode {@link
+android.view.View.OnCreateContextMenuListener#onCreateContextMenu onCreateContextMenu()}
+Anda. Inilah tempat Anda mendefinisikan item menu, biasanya dengan memekarkan sumber daya menu. Misalnya:
+</p>
+<pre>
+&#64;Override
+public void onCreateContextMenu(ContextMenu menu, View v,
+                                ContextMenuInfo menuInfo) {
+    super.onCreateContextMenu(menu, v, menuInfo);
+    MenuInflater inflater = getMenuInflater();
+    inflater.inflate(R.menu.context_menu, menu);
+}
+</pre>
+
+<p>{@link android.view.MenuInflater} memungkinkan Anda untuk memekarkan menu konteks <a href="{@docRoot}guide/topics/resources/menu-resource.html">sumber daya menu</a>. Parameter metode callback
+menyertakan {@link android.view.View}
+yang dipilih pengguna dan objek {@link android.view.ContextMenu.ContextMenuInfo} yang menyediakan
+informasi tambahan tentang item yang dipilih. Jika aktivitas Anda memiliki beberapa tampilan yang masing-masingnya menyediakan
+menu konteks berbeda, Anda bisa menggunakan parameter ini untuk menentukan menu konteks yang harus
+dimekarkan.</p>
+</li>
+
+<li>Implementasikan {@link android.app.Activity#onContextItemSelected(MenuItem)
+onContextItemSelected()}.
+  <p>Bila pengguna memilih item menu, sistem akan memanggil metode ini sehingga Anda bisa melakukan
+tindakan yang sesuai. Misalnya:</p>
+
+<pre>
+&#64;Override
+public boolean onContextItemSelected(MenuItem item) {
+    AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
+    switch (item.getItemId()) {
+        case R.id.edit:
+            editNote(info.id);
+            return true;
+        case R.id.delete:
+            deleteNote(info.id);
+            return true;
+        default:
+            return super.onContextItemSelected(item);
+    }
+}
+</pre>
+
+<p>Metode {@link android.view.MenuItem#getItemId()} melakukan query ID untuk
+item menu yang dipilih, yang harus Anda tetapkan ke setiap item menu dalam XML dengan menggunakan atribut {@code
+android:id}, seperti yang ditampilkan di bagian tentang <a href="#xml">Mendefinisikan Menu dalam
+XML</a>.</p>
+
+<p>Bila Anda berhasil menangani sebuah item menu, kembalikan {@code true}. Jika tidak menangani item menu,
+Anda harus meneruskan item menu ke implementasi superkelas. Jika aktivitas Anda menyertakan fragmen,
+aktivitas akan menerima callback ini lebih dahulu. Dengan memanggil superkelas bila tidak ditangani, sistem
+meneruskan kejadian ke metode callback di setiap fragmen, satu per satu (sesuai dengan urutan
+penambahan fragmen) hingga {@code true} atau {@code false} dikembalikan. (Implementasi default
+untuk {@link android.app.Activity} dan {@code android.app.Fragment} mengembalikan {@code
+false}, sehingga Anda harus selalu memanggil superkelas bila tidak ditangani.)</p>
+</li>
+</ol>
+
+
+<h3 id="CAB">Menggunakan mode tindakan kontekstual</h3>
+
+<p>Mode tindakan kontekstual adalah implementasi sistem {@link android.view.ActionMode} yang
+memfokuskan interaksi pengguna pada upaya melakukan tindakan kontekstual. Bila seorang
+pengguna mengaktifkan mode ini dengan memilih item, <em>action-bar kontekstual</em> akan muncul di bagian atas
+layar untuk menampilkan tindakan yang bisa dilakukan pengguna pada item yang dipilih saat ini. Selagi mode ini
+diaktifkan, pengguna bisa memilih beberapa item (jika Anda mengizinkan), membatalkan pilihan item, dan melanjutkan
+penelusuran dalam aktivitas (sebanyak yang ingin Anda izinkan). Mode tindakan dinonaktifkan
+dan action-bar kontekstual menghilang bila pengguna membatalkan pilihan semua item, menekan tombol BACK,
+atau memilih tindakan <em>Done</em> di sisi kiri action-bar.</p>
+
+<p class="note"><strong>Catatan:</strong> Action-bar kontekstual tidak harus
+terkait dengan <a href="{@docRoot}guide/topics/ui/actionbar.html">action-bar</a>. Action-bar ini beroperasi
+secara independen, walaupun action-bar kontekstual secara visual mengambil alih
+posisi action-bar.</p>
+
+<p>Jika Anda mengembangkan aplikasi untuk Android 3.0 (API level 11) atau yang lebih tinggi, Anda
+biasanya harus menggunakan mode tindakan kontekstual untuk menampilkan tindakan kontekstual, sebagai ganti <a href="#FloatingContextMenu">menu konteks mengambang</a>.</p>
+
+<p>Untuk tampilan yang menyediakan tindakan kontekstual, Anda biasanya harus memanggil mode tindakan kontekstual
+pada salah satu dari dua kejadian (atau keduanya):</p>
+<ul>
+  <li>Pengguna mengklik-lama pada tampilan.</li>
+  <li>Pengguna memilih kotak cek atau komponen UI yang serupa dalam tampilan.</li>
+</ul>
+
+<p>Cara aplikasi memanggil mode tindakan kontekstual dan mendefinisikan perilaku setiap
+tindakan bergantung pada desain Anda. Pada dasarnya ada dua desain:</p>
+<ul>
+  <li>Untuk tindakan kontekstual pada tampilan individual dan tak didukung.</li>
+  <li>Untuk tindakan kontekstual batch pada grup item dalam {@link
+android.widget.ListView} atau {@link android.widget.GridView} (memungkinkan pengguna memilih beberapa
+item dan melakukan tindakan pada semua item itu).</li>
+</ul>
+
+<p>Bagian berikut ini menjelaskan penyiapan yang diperlukan untuk setiap skenario.</p>
+
+
+<h4 id="CABforViews">Mengaktifkan mode tindakan kontekstual untuk tampilan individual</h4>
+
+<p>Jika Anda ingin memanggil mode tindakan kontekstual hanya bila pengguna memilih
+tampilan tertentu, Anda harus:</p>
+<ol>
+  <li>Mengimplementasikan antarmuka {@link android.view.ActionMode.Callback}. Dalam metode callback-nya, Anda
+bisa menetapkan tindakan untuk action-bar kontekstual, merespons kejadian klik pada item tindakan, dan
+menangani kejadian daur hidup lainnya untuk mode tindakan itu.</li>
+  <li>Memanggil {@link android.app.Activity#startActionMode startActionMode()} bila Anda ingin menampilkan
+action-bar (seperti saat pengguna mengklik-lama pada tampilan).</li>
+</ol>
+
+<p>Misalnya:</p>
+
+<ol>
+  <li>Implementasikan antarmuka {@link android.view.ActionMode.Callback ActionMode.Callback}:
+<pre>
+private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
+
+    // Called when the action mode is created; startActionMode() was called
+    &#64;Override
+    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+        // Inflate a menu resource providing context menu items
+        MenuInflater inflater = mode.getMenuInflater();
+        inflater.inflate(R.menu.context_menu, menu);
+        return true;
+    }
+
+    // Called each time the action mode is shown. Always called after onCreateActionMode, but
+    // may be called multiple times if the mode is invalidated.
+    &#64;Override
+    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+        return false; // Return false if nothing is done
+    }
+
+    // Called when the user selects a contextual menu item
+    &#64;Override
+    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.menu_share:
+                shareCurrentItem();
+                mode.finish(); // Action picked, so close the CAB
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    // Called when the user exits the action mode
+    &#64;Override
+    public void onDestroyActionMode(ActionMode mode) {
+        mActionMode = null;
+    }
+};
+</pre>
+
+<p>Perhatikan bahwa kejadian callback ini hampir persis sama dengan callback untuk <a href="#options-menu">menu opsi</a>, hanya saja setiap callback ini juga meneruskan objek {@link
+android.view.ActionMode} yang terkait dengan kejadian. Anda bisa menggunakan API {@link
+android.view.ActionMode} untuk membuat berbagai perubahan pada CAB, seperti merevisi judul dan
+subjudul dengan {@link android.view.ActionMode#setTitle setTitle()} dan {@link
+android.view.ActionMode#setSubtitle setSubtitle()} (berguna untuk menunjukkan jumlah item
+yang dipilih).</p>
+
+<p>Juga perhatikan bahwa contoh di atas mengatur variabel {@code mActionMode} ke nol bila
+mode tindakan dimusnahkan. Dalam langkah berikutnya, Anda akan melihat cara variabel diinisialisasi dan kegunaan menyimpan
+variabel anggota dalam aktivitas atau fragmen.</p>
+</li>
+
+  <li>Panggil {@link android.app.Activity#startActionMode startActionMode()} untuk mengaktifkan
+mode tindakan kontekstual bila sesuai, seperti saat merespons klik-lama pada {@link
+android.view.View}:</p>
+
+<pre>
+someView.setOnLongClickListener(new View.OnLongClickListener() {
+    // Called when the user long-clicks on someView
+    public boolean onLongClick(View view) {
+        if (mActionMode != null) {
+            return false;
+        }
+
+        // Start the CAB using the ActionMode.Callback defined above
+        mActionMode = getActivity().startActionMode(mActionModeCallback);
+        view.setSelected(true);
+        return true;
+    }
+});
+</pre>
+
+<p>Bila Anda memanggil {@link android.app.Activity#startActionMode startActionMode()}, sistem akan mengembalikan
+{@link android.view.ActionMode} yang dibuat. Dengan menyimpannya dalam variabel anggota, Anda bisa
+membuat perubahan ke action-bar kontekstual sebagai respons terhadap kejadian lainnya. Dalam contoh di atas,
+{@link android.view.ActionMode} digunakan untuk memastikan bahwa instance {@link android.view.ActionMode}
+tidak dibuat kembali jika sudah aktif, dengan memeriksa apakah anggota bernilai nol sebelum memulai
+mode tindakan.</p>
+</li>
+</ol>
+
+
+
+<h4 id="CABforListView">Mengaktifkan tindakan kontekstual batch dalam ListView atau GridView</h4>
+
+<p>Jika Anda memiliki sekumpulan item dalam {@link android.widget.ListView} atau {@link
+android.widget.GridView} (atau ekstensi {@link android.widget.AbsListView} lainnya) dan ingin
+mengizinkan pengguna melakukan tindakan batch, Anda harus:</p>
+
+<ul>
+  <li>Mengimplementasikan antarmuka {@link android.widget.AbsListView.MultiChoiceModeListener} dan mengaturnya
+untuk grup tampilan dengan {@link android.widget.AbsListView#setMultiChoiceModeListener
+setMultiChoiceModeListener()}. Dalam metode callback listener, Anda bisa menetapkan tindakan
+untuk action-bar kontekstual, merespons kejadian klik pada item tindakan, dan menangani callback lainnya
+yang diwarisi dari antarmuka {@link android.view.ActionMode.Callback}.</li>
+
+  <li>Panggil {@link android.widget.AbsListView#setChoiceMode setChoiceMode()} dengan argumen {@link
+android.widget.AbsListView#CHOICE_MODE_MULTIPLE_MODAL}.</li>
+</ul>
+
+<p>Misalnya:</p>
+
+<pre>
+ListView listView = getListView();
+listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
+listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
+
+    &#64;Override
+    public void onItemCheckedStateChanged(ActionMode mode, int position,
+                                          long id, boolean checked) {
+        // Here you can do something when items are selected/de-selected,
+        // such as update the title in the CAB
+    }
+
+    &#64;Override
+    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+        // Respond to clicks on the actions in the CAB
+        switch (item.getItemId()) {
+            case R.id.menu_delete:
+                deleteSelectedItems();
+                mode.finish(); // Action picked, so close the CAB
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    &#64;Override
+    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+        // Inflate the menu for the CAB
+        MenuInflater inflater = mode.getMenuInflater();
+        inflater.inflate(R.menu.context, menu);
+        return true;
+    }
+
+    &#64;Override
+    public void onDestroyActionMode(ActionMode mode) {
+        // Here you can make any necessary updates to the activity when
+        // the CAB is removed. By default, selected items are deselected/unchecked.
+    }
+
+    &#64;Override
+    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+        // Here you can perform updates to the CAB due to
+        // an {@link android.view.ActionMode#invalidate} request
+        return false;
+    }
+});
+</pre>
+
+<p>Demikian saja. Kini bila pengguna memilih item dengan klik-lama, sistem akan memanggil metode {@link
+android.widget.AbsListView.MultiChoiceModeListener#onCreateActionMode onCreateActionMode()}
+dan menampilkan action-bar kontekstual bersama tindakan yang ditetapkan. Saat
+action-bar kontekstual terlihat, pengguna bisa memilih item tambahan.</p>
+
+<p>Dalam beberapa kasus di mana tindakan kontekstual menyediakan item tindakan umum, Anda mungkin
+ingin menambahkan kotak cek atau elemen UI serupa yang memungkinkan pengguna memilih item, karena pengguna
+mungkin tidak menemukan perilaku klik-lama. Bila pengguna memilih kotak cek itu, Anda
+bisa memanggil mode tindakan kontekstual dengan mengatur item daftar yang bersangkutan ke
+status diberi tanda cek dengan {@link android.widget.AbsListView#setItemChecked setItemChecked()}.</p>
+
+
+
+
+<h2 id="PopupMenu">Membuat Menu Popup</h2>
+
+<div class="figure" style="width:220px">
+<img src="{@docRoot}images/ui/popupmenu.png" alt="" />
+<p><strong>Gambar 4.</strong> Menu popup dalam aplikasi Gmail, dikaitkan pada
+tombol kelebihan di sudut kanan atas.</p>
+</div>
+
+<p>{@link android.widget.PopupMenu} adalah menu modal yang dikaitkan pada {@link android.view.View}.
+Menu ini muncul di bawah tampilan jangkar jika ada ruang, atau di atas tampilan jika tidak ada. Menu ini berguna untuk:</p>
+<ul>
+  <li>Menyediakan menu bergaya kelebihan (overflow) untuk tindakan yang <em>berkaitan dengan</em> konten tertentu (seperti
+header email Gmail, yang ditampilkan dalam gambar 4).
+    <p class="note"><strong>Catatan:</strong> Ini tidak sama dengan menu konteks, yang umumnya
+untuk tindakan yang <em>memengaruhi</em> konten yang dipilih. Untuk tindakan yang memengaruhi
+konten yang dipilih, gunakan <a href="#CAB">mode tindakan kontekstual</a> atau <a href="#FloatingContextMenu">menu konteks mengambang</a>.</p></li>
+  <li>Menyediakan bagian kedua dari kalimat perintah (seperti tombol bertanda "Tambah"
+yang menghasilkan menu popup dengan berbagai opsi "Tambah").</li>
+  <li>Menyediakan daftar menurun yang serupa dengan {@link android.widget.Spinner} yang tidak mempertahankan
+pilihan persisten.</li>
+</ul>
+
+
+<p class="note"><strong>Catatan:</strong> {@link android.widget.PopupMenu} tersedia dengan API
+level 11 dan yang lebih tinggi.</p>
+
+<p>Jika Anda <a href="#xml">mendefinisikan menu dalam XML</a>, berikut ini adalah cara Anda menampilkan menu popup:</p>
+<ol>
+  <li>Buat instance {@link android.widget.PopupMenu} bersama konstruktornya, yang mengambil
+aplikasi saat ini {@link android.content.Context} dan {@link android.view.View} yang akan menjadi tempat mengaitkan
+menu.</li>
+  <li>Gunakan {@link android.view.MenuInflater} untuk memekarkan sumber daya menu Anda ke dalam objek {@link
+android.view.Menu} yang dikembalikan oleh {@link
+android.widget.PopupMenu#getMenu() PopupMenu.getMenu()}. Pada API level 14 ke atas, Anda bisa menggunakan
+{@link android.widget.PopupMenu#inflate PopupMenu.inflate()} sebagai gantinya.</li>
+  <li>Panggil {@link android.widget.PopupMenu#show() PopupMenu.show()}.</li>
+</ol>
+
+<p>Misalnya, berikut ini adalah tombol dengan atribut {@link android.R.attr#onClick android:onClick}
+yang menampilkan menu popup:</p>
+
+<pre>
+&lt;ImageButton
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:src="@drawable/ic_overflow_holo_dark"
+    android:contentDescription="@string/descr_overflow_button"
+    android:onClick="showPopup" />
+</pre>
+
+<p>Aktivitas nanti bisa menampilkan menu popup seperti ini:</p>
+
+<pre>
+public void showPopup(View v) {
+    PopupMenu popup = new PopupMenu(this, v);
+    MenuInflater inflater = popup.getMenuInflater();
+    inflater.inflate(R.menu.actions, popup.getMenu());
+    popup.show();
+}
+</pre>
+
+<p>Dalam API level 14 dan yang lebih tinggi, Anda bisa menggabungkan dua baris yang memekarkan menu dengan {@link
+android.widget.PopupMenu#inflate PopupMenu.inflate()}.</p>
+
+<p>Menu akan menghilang bila pengguna memilih item atau menyentuh di luar
+area menu. Anda bisa mendengarkan kejadian menghilangkan dengan menggunakan {@link
+android.widget.PopupMenu.OnDismissListener}.</p>
+
+<h3 id="PopupEvents">Menangani kejadian klik</h3>
+
+<p>Untuk melakukan suatu
+tindakan bila pengguna memilih item menu, Anda harus mengimplementasikan antarmuka {@link
+android.widget.PopupMenu.OnMenuItemClickListener} dan mendaftarkannya pada {@link
+android.widget.PopupMenu} dengan memanggil {@link android.widget.PopupMenu#setOnMenuItemClickListener
+setOnMenuItemclickListener()}. Bila pengguna memilih item, sistem akan memanggil callback {@link
+android.widget.PopupMenu.OnMenuItemClickListener#onMenuItemClick onMenuItemClick()} dalam
+antarmuka Anda.</p>
+
+<p>Misalnya:</p>
+
+<pre>
+public void showMenu(View v) {
+    PopupMenu popup = new PopupMenu(this, v);
+
+    // This activity implements OnMenuItemClickListener
+    popup.setOnMenuItemClickListener(this);
+    popup.inflate(R.menu.actions);
+    popup.show();
+}
+
+&#64;Override
+public boolean onMenuItemClick(MenuItem item) {
+    switch (item.getItemId()) {
+        case R.id.archive:
+            archive(item);
+            return true;
+        case R.id.delete:
+            delete(item);
+            return true;
+        default:
+            return false;
+    }
+}
+</pre>
+
+
+<h2 id="groups">Membuat Grup Menu</h2>
+
+<p>Grup menu adalah sekumpulan item menu yang sama-sama memiliki ciri (trait) tertentu. Dengan grup, Anda
+bisa:</p>
+<ul>
+  <li>Menampilkan atau menyembunyikan semua item dengan {@link android.view.Menu#setGroupVisible(int,boolean)
+setGroupVisible()}</li>
+  <li>Mengaktifkan atau mennonaktifkan semua item dengan {@link android.view.Menu#setGroupEnabled(int,boolean)
+setGroupEnabled()}</li>
+  <li>Menetapkan apakah semua item bisa diberi tanda cek dengan {@link
+android.view.Menu#setGroupCheckable(int,boolean,boolean) setGroupCheckable()}</li>
+</ul>
+
+<p>Anda bisa membuat grup dengan menyarangkan elemen-elemen {@code &lt;item&gt;} dalam elemen {@code &lt;group&gt;}
+dalam sumber daya menu atau dengan menetapkan ID grup dengan metode {@link
+android.view.Menu#add(int,int,int,int) add()}.</p>
+
+<p>Berikut ini adalah contoh sumber daya menu yang berisi sebuah grup:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
+    &lt;item android:id="@+id/menu_save"
+          android:icon="@drawable/menu_save"
+          android:title="@string/menu_save" /&gt;
+    &lt;!-- menu group --&gt;
+    &lt;group android:id="@+id/group_delete"&gt;
+        &lt;item android:id="@+id/menu_archive"
+              android:title="@string/menu_archive" /&gt;
+        &lt;item android:id="@+id/menu_delete"
+              android:title="@string/menu_delete" /&gt;
+    &lt;/group&gt;
+&lt;/menu&gt;
+</pre>
+
+<p>Item yang berada dalam grup akan muncul pada level yang sama dengan item pertama&mdash;ketiga item
+dalam menu adalah bersaudara. Akan tetapi, Anda bisa memodifikasi ciri kedua
+item dalam grup dengan mengacu ID grup dan menggunakan metode yang tercantum di atas. Sistem
+juga tidak akan memisahkan item yang telah dikelompokkan. Misalnya, jika Anda mendeklarasikan {@code
+android:showAsAction="ifRoom"} untuk tiap item, item tersebut akan muncul dalam
+action-bar atau dalam kelebihan tindakan.</p>
+
+
+<h3 id="checkable">Menggunakan item menu yang bisa diberi tanda cek</h3>
+
+<div class="figure" style="width:200px">
+  <img src="{@docRoot}images/radio_buttons.png" height="333" alt="" />
+  <p class="img-caption"><strong>Gambar 5.</strong> Cuplikan layar submenu dengan
+item yang bisa diberi tanda cek.</p>
+</div>
+
+<p>Menu bisa digunakan sebagai antarmuka untuk mengaktifkan dan menonaktifkan opsi, menggunakan kotak cek untuk
+opsi mandiri, atau tombol radio untuk grup
+opsi yang saling eksklusif. Gambar 5 menampilkan submenu dengan item yang bisa diberi tanda cek dengan
+tombol radio.</p>
+
+<p class="note"><strong>Catatan:</strong> Item menu dalam Icon Menu (dari menu opsi) tidak bisa
+menampilkan kotak cek atau tombol radio. Jika Anda memilih untuk membuat item dalam Icon Menu yang bisa diberi tanda cek,
+Anda harus menandai status diberi tanda cek secara manual dengan menukar ikon dan/atau teks
+tiap kali statusnya berubah.</p>
+
+<p>Anda bisa mendefinisikan perilaku yang bisa diberi tanda cek untuk tiap item menu dengan menggunakan atribut {@code
+android:checkable} dalam elemen {@code &lt;item&gt;}, atau untuk seluruh grup dengan
+atribut {@code android:checkableBehavior} dalam elemen {@code &lt;group&gt;}. Misalnya
+, semua item dalam grup menu ini bisa diberi tanda cek dengan tombol radio:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
+    &lt;group android:checkableBehavior="single"&gt;
+        &lt;item android:id="@+id/red"
+              android:title="@string/red" /&gt;
+        &lt;item android:id="@+id/blue"
+              android:title="@string/blue" /&gt;
+    &lt;/group&gt;
+&lt;/menu&gt;
+</pre>
+
+<p>Atribut {@code android:checkableBehavior} menerima:
+<dl>
+  <dt>{@code single}</dt>
+    <dd>Hanya satu item dari grup ini yang bisa diberi tanda cek (tombol radio)</dd>
+  <dt>{@code all}</dt>
+    <dd>Semua item bisa diberi tanda cek (kotak cek)</dd>
+  <dt>{@code none}</dt>
+    <dd>Tidak ada item yang bisa diberi tanda cek</dd>
+</dl>
+
+<p>Anda bisa menerapkan status diberi tanda cek default pada suatu item dengan menggunakan atribut {@code android:checked} dalam
+elemen {@code &lt;item&gt;} dan mengubahnya dalam kode dengan metode {@link
+android.view.MenuItem#setChecked(boolean) setChecked()}.</p>
+
+<p>Bila item yang bisa diberi tanda cek dipilih, sistem akan memanggil metode callback setiap item yang dipilih
+(seperti {@link android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()}). Di sinilah
+Anda harus mengatur status kotak cek itu, karena kotak cek atau tombol radio tidak
+mengubah statusnya secara otomatis. Anda bisa melakukan query status saat ini suatu item (seperti sebelum
+pengguna memilihnya) dengan {@link android.view.MenuItem#isChecked()} kemudian mengatur status diberi tanda cek dengan
+{@link android.view.MenuItem#setChecked(boolean) setChecked()}. Misalnya:</p>
+
+<pre>
+&#64;Override
+public boolean onOptionsItemSelected(MenuItem item) {
+    switch (item.getItemId()) {
+        case R.id.vibrate:
+        case R.id.dont_vibrate:
+            if (item.isChecked()) item.setChecked(false);
+            else item.setChecked(true);
+            return true;
+        default:
+            return super.onOptionsItemSelected(item);
+    }
+}
+</pre>
+
+<p>Jika Anda tidak mengatur status diberi tanda cek dengan cara ini, maka status item (kotak cek atau
+tombol radio) yang terlihat tidak akan
+berubah bila pengguna memilihnya. Bila Anda telah mengatur status, aktivitas akan menjaga status diberi tanda cek
+suatu item sehingga bila nanti pengguna membuka menu, status diberi tanda cek yang Anda
+atur akan terlihat.</p>
+
+<p class="note"><strong>Catatan:</strong>
+Item menu yang bisa diberi tanda cek dimaksudkan untuk digunakan hanya atas dasar per sesi dan tidak disimpan setelah
+aplikasi dimusnahkan. Jika Anda memiliki pengaturan aplikasi yang ingin disimpan untuk pengguna,
+Anda harus menyimpan data dengan menggunakan <a href="{@docRoot}guide/topics/data/data-storage.html#pref">Shared Preferences</a>.</p>
+
+
+
+<h2 id="intents">Menambahkan Item Menu Berdasarkan Intent</h2>
+
+<p>Kadang-kadang Anda ingin supaya item menu menjalankan aktivitas dengan menggunakan {@link android.content.Intent}
+(baik aktivitas berada dalam aplikasi Anda maupun di aplikasi lain). Bila Anda mengetahui intent
+yang ingin digunakan dan memiliki item menu tertentu yang harus memulai intent, Anda bisa mengeksekusi
+intent dengan {@link android.app.Activity#startActivity(Intent) startActivity()} selama
+metode callback bila-item-dipilih yang sesuai (seperti callback {@link
+android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()}).</p>
+
+<p>Akan tetapi, jika Anda tidak yakin apakah perangkat pengguna
+berisi aplikasi yang menangani intent, maka menambahkan item menu yang memanggilnya bisa mengakibatkan
+item menu tidak berfungsi, karena intent tidak bisa diterjemahkan menjadi
+aktivitas. Untuk mengatasi hal ini, Android memungkinkan Anda menambahkan item menu secara dinamis ke menu
+bila Android menemukan aktivitas pada perangkat yang menangani intent Anda.</p>
+
+<p>Untuk menambahkan item menu berdasarkan aktivitas tersedia yang menerima intent:</p>
+<ol>
+  <li>Definisikan
+intent dengan kategori {@link android.content.Intent#CATEGORY_ALTERNATIVE} dan/atau
+{@link android.content.Intent#CATEGORY_SELECTED_ALTERNATIVE}, plus kebutuhan lainnya.</li>
+  <li>Panggil {@link
+android.view.Menu#addIntentOptions(int,int,int,ComponentName,Intent[],Intent,int,MenuItem[])
+Menu.addIntentOptions()}. Android kemudian akan mencari setiap aplikasi yang bisa melakukan intent
+dan menambahkannya ke menu Anda.</li>
+</ol>
+
+<p>Jika tidak ada aplikasi terinstal
+yang memenuhi intent, maka tidak ada item menu yang ditambahkan.</p>
+
+<p class="note"><strong>Catatan:</strong>
+{@link android.content.Intent#CATEGORY_SELECTED_ALTERNATIVE} digunakan untuk menangani
+elemen yang saat ini dipilih pada layar. Jadi, metode hanya digunakan saat membuat Menu dalam {@link
+android.app.Activity#onCreateContextMenu(ContextMenu,View,ContextMenuInfo)
+onCreateContextMenu()}.</p>
+
+<p>Misalnya:</p>
+
+<pre>
+&#64;Override
+public boolean onCreateOptionsMenu(Menu menu){
+    super.onCreateOptionsMenu(menu);
+
+    // Create an Intent that describes the requirements to fulfill, to be included
+    // in our menu. The offering app must include a category value of Intent.CATEGORY_ALTERNATIVE.
+    Intent intent = new Intent(null, dataUri);
+    intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
+
+    // Search and populate the menu with acceptable offering applications.
+    menu.addIntentOptions(
+         R.id.intent_group,  // Menu group to which new items will be added
+         0,      // Unique item ID (none)
+         0,      // Order for the items (none)
+         this.getComponentName(),   // The current activity name
+         null,   // Specific items to place first (none)
+         intent, // Intent created above that describes our requirements
+         0,      // Additional flags to control items (none)
+         null);  // Array of MenuItems that correlate to specific items (none)
+
+    return true;
+}</pre>
+
+<p>Untuk setiap aktivitas yang diketahui menyediakan filter intent yang cocok dengan intent yang didefinisikan, item menu
+akan ditambahkan, menggunakan nilai dalam filter intent <code>android:label</code> sebagai
+judul item menu dan ikon aplikasi sebagai ikon item menu. Metode
+{@link android.view.Menu#addIntentOptions(int,int,int,ComponentName,Intent[],Intent,int,MenuItem[])
+addIntentOptions()} mengembalikan jumlah item menu yang ditambahkan.</p>
+
+<p class="note"><strong>Catatan:</strong> Bila Anda memanggil {@link
+android.view.Menu#addIntentOptions(int,int,int,ComponentName,Intent[],Intent,int,MenuItem[])
+addIntentOptions()}, metode ini akan mengesampingkan setiap dan semua item menu menurut grup menu yang ditetapkan dalam argumen
+pertama.</p>
+
+
+<h3 id="AllowingToAdd">Memungkinkan aktivitas Anda ditambahkan ke menu lain</h3>
+
+<p>Anda juga bisa menawarkan layanan aktivitas Anda pada aplikasi lainnya, sehingga
+aplikasi Anda bisa disertakan dalam menu aplikasi lain (membalik peran yang dijelaskan di atas).</p>
+
+<p>Agar bisa dimasukkan dalam menu aplikasi lain, Anda perlu mendefinisikan
+filter intent seperti biasa, tetapi pastikan menyertakan nilai-nilai {@link android.content.Intent#CATEGORY_ALTERNATIVE}
+dan/atau {@link android.content.Intent#CATEGORY_SELECTED_ALTERNATIVE} untuk
+kategori filter intent. Misalnya:</p>
+<pre>
+&lt;intent-filter label="&#64;string/resize_image">
+    ...
+    &lt;category android:name="android.intent.category.ALTERNATIVE" />
+    &lt;category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
+    ...
+&lt;/intent-filter>
+</pre>
+
+<p>Baca selengkapnya tentang penulisan filter intent dalam dokumen
+<a href="/guide/components/intents-filters.html">Intent dan Filter Intent</a>.</p>
+
+<p>Untuk contoh aplikasi yang menggunakan teknik ini, lihat contoh kode
+<a href="{@docRoot}resources/samples/NotePad/src/com/example/android/notepad/NoteEditor.html">Note
+Pad</a>.</p>
diff --git a/docs/html-intl/intl/id/guide/topics/ui/multi-window.jd b/docs/html-intl/intl/id/guide/topics/ui/multi-window.jd
new file mode 100644
index 0000000..5e7b3d9
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/ui/multi-window.jd
@@ -0,0 +1,589 @@
+page.title=Dukungan Multi-Jendela
+page.metaDescription=Dukungan baru di Android N untuk menampilkan lebih dari satu aplikasi sekaligus.
+page.keywords="multi-window", "android N", "split screen", "free-form"
+
+@jd:body
+
+<div id="tb-wrapper">
+  <div id="tb">
+    <h2>Dalam dokumen ini</h2>
+      <ol>
+        <li><a href="#overview">Ringkasan</a></li>
+        <li><a href="#lifecycle">Daur Hidup Multi-Jendela</a></li>
+        <li><a href="#configuring">Mengonfigurasi Aplikasi Anda untuk Mode
+              Multi-Jendela</a></li>
+        <li><a href="#running">Menjalankan Aplikasi Anda dalam Mode Multi-Jendela</a></li>
+        <li><a href="#testing">Menguji Dukungan Multi-Jendela Aplikasi Anda</a></li>
+      </ol>
+    <h2>Lihat Juga</h2>
+      <ol>
+        <li><a class="external-link" href="https://github.com/googlesamples/android-MultiWindowPlayground">Aplikasi contoh Playground
+          Multi-Jendela</a></li>
+        <li><a class="external-link" href="https://medium.com/google-developers/5-tips-for-preparing-for-multi-window-in-android-n-7bed803dda64">Lima Tip untuk Mempersiapkan Multi-Jendela di Android N</a></li>
+      </ol>
+  </div>
+</div>
+
+<p>
+  Android N menambahkan dukungan untuk menampilkan lebih dari satu aplikasi
+  sekaligus. Pada perangkat genggam, dua aplikasi bisa berjalan berdampingan atau
+  atas-bawah dalam mode <em>layar terbagi</em>. Pada perangkat TV, aplikasi bisa
+  menggunakan mode <em>gambar-dalam-gambar</em> untuk melanjutkan pemutaran video selagi pengguna
+  berinteraksi dengan aplikasi lain.
+</p>
+
+<p>
+  Jika Anda membangun aplikasi Anda dengan N Preview SDK, Anda bisa mengonfigurasi cara aplikasi
+  menangani tampilan multi-jendela. Misalnya, Anda bisa menetapkan dimensi
+  minimum yang diizinkan aktivitas Anda. Anda juga bisa menonaktifkan tampilan multi-jendela untuk
+   aplikasi, sehingga memastikan sistem hanya menampilkan aplikasi Anda dalam mode
+  layar penuh.
+</p>
+
+<h2 id="overview">Ringkasan</h2>
+
+<p>
+  Android N memungkinkan beberapa aplikasi berbagi layar sekaligus. Misalnya,
+  pengguna bisa membagi layar, melihat halaman web di sisi kiri
+  sambil menulis email di sisi kanan. Pengalaman pengguna bergantung pada
+  perangkat:
+</p>
+
+<ul>
+  <li>Perangkat genggam yang menjalankan Android N menawarkan mode
+  layar terbagi. Di mode ini, sistem mengisi layar dengan dua aplikasi, menampilkannya secara
+  berdampingan atau atas-bawah. Pengguna bisa menyeret garis pembagi
+   yang memisahkan keduanya untuk membuat satu aplikasi lebih besar dan yang lainnya lebih kecil.
+  </li>
+
+  <li>Pada Nexus Player yang menjalankan Android N, aplikasi bisa menempatkan diri
+  dalam <a href="picture-in-picture.html">mode gambar-dalam-gambar</a>, yang memungkinkannya
+  untuk terus menampilkan materi selagi pengguna menjelajahi atau berinteraksi dengan
+   aplikasi lain.
+  </li>
+
+  <li>Produsen perangkat berukuran lebih besar bisa memilih untuk mengaktifkan mode
+ bentuk bebas, di mana pengguna bisa bebas mengubah ukuran setiap aktivitas. Jika
+  produsen mengaktifkan fitur ini, perangkat akan menawarkan mode bentuk bebas sebagai tambahan
+  untuk mode layar terbagi.
+  </li>
+</ul>
+
+<img src="{@docRoot}images/android-7.0/mw-splitscreen.png" alt="" width="650" srcset="{@docRoot}images/android-7.0/mw-splitscreen.png 1x,
+    {@docRoot}images/android-7.0/mw-splitscreen_2x.png 2x," id="img-split-screen" />
+<p class="img-caption">
+  <strong>Gambar 1.</strong> Dua aplikasi berjalan berdampingan dalam mode layar terbagi.
+</p>
+
+<p>
+  Pengguna bisa beralih ke mode multi-jendela dengan cara berikut:
+</p>
+
+<ul>
+  <li>Jika pengguna membuka <a href="{@docRoot}guide/components/recents.html">layar
+  Ringkasan</a> dan menekan lama pada
+  judul aktivitas, mereka bisa menyeret aktivitas itu ke bagian yang disorot pada layar
+  untuk menempatkan aktivitas dalam mode multi-jendela.
+  </li>
+
+  <li>Jika pengguna menekan lama pada tombol Ringkasan, perangkat akan menempatkan
+   aktivitas saat ini dalam mode multi-jendela, dan membuka layar Ringkasan guna
+  memungkinkan pengguna memilih aktivitas lain untuk berbagi layar.
+  </li>
+</ul>
+
+<p>
+  Pengguna bisa <a href="{@docRoot}guide/topics/ui/drag-drop.html">seret dan
+  lepas</a> data dari aktivitas satu ke aktivitas lain sewaktu aktivitas berbagi
+  layar. (Sebelumnya, pengguna hanya bisa menyeret dan melepas data dalam aktivitas
+  tunggal.)
+</p>
+
+<h2 id="lifecycle">Daur Hidup Multi-Jendela</h2>
+
+<p>
+  Mode multi-jendela tidak mengubah <a href="{@docRoot}training/basics/activity-lifecycle/index.html">daur hidup
+  aktivitas</a>.
+</p>
+
+<p>
+  Dalam mode multi-jendela, hanya aktivitas yang paling sering digunakan pengguna
+  yang akan aktif pada waktu tertentu. Aktivitas ini dianggap <em>teratas</em>.
+  Semua aktivitas lainnya dalam keadaan berhenti sementara, sekalipun terlihat.
+  Akan tetapi, sistem memberikan aktivitas, yang berhenti-sementara-namun-terlihat ini, prioritas lebih tinggi
+   daripada aktivitas yang tidak terlihat. Jika pengguna berinteraksi dengan salah satu
+  aktivitas yang berhenti sementara, aktivitas tersebut akan dilanjutkan kembali, dan aktivitas
+  teratas sebelumnya akan dihentikan sementara.
+</p>
+
+<p class="note">
+  <strong>Catatan:</strong> Dalam mode multi-jendela, aplikasi bisa berada dalam keadaan berhenti sementara
+  dan masih terlihat oleh pengguna. Sebuah aplikasi mungkin perlu melanjutkan aktivitasnya
+   bahkan saat berhenti sementara. Misalnya, aplikasi pemutar video yang ada dalam
+   mode berhenti sementara namun terlihat harus tetap menampilkan videonya. Karena alasan
+  ini, kami menyarankan aktivitas yang memutar video <em>tidak</em> menghentikan sementara video
+   dalam handler {@link android.app.Activity#onPause onPause()} mereka.
+  Sebagai gantinya, aktivitas itu harus menghentikan sementara video di {@link android.app.Activity#onStop
+  onStop()}, dan melanjutkan pemutaran di {@link android.app.Activity#onStart
+  onStart()}.
+</p>
+
+<p>
+  Bila pengguna menempatkan aplikasi dalam mode multi-jendela, sistem akan memberi tahu
+   aktivitas tersebut mengenai perubahan konfigurasi, sebagaimana ditetapkan dalam <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Menangani Perubahan
+  Waktu Proses</a>. Hal ini juga terjadi ketika pengguna mengubah skala aplikasi, atau menempatkan kembali aplikasi
+  ke mode layar penuh.
+  Pada dasarnya, perubahan ini memiliki implikasi daur hidup aktivitas yang sama
+  seperti saat sistem memberi tahu aplikasi bahwa perangkat telah beralih
+  dari mode potret ke mode lanskap, kecuali dimensi perangkat
+  telah berubah sebagai ganti bertukar posisi. Seperti yang dibahas di <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Menangani Perubahan
+  Waktu Proses</a>, aktivitas Anda bisa menangani perubahan konfigurasi itu sendiri, atau
+   mengizinkan sistem memusnahkan aktivitas dan membuatnya kembali dengan dimensi
+  baru.
+</p>
+
+<p>
+  Jika pengguna mengubah ukuran jendela dan membuat dimensinya lebih besar, sistem
+   akan mengubah ukuran aktivitas untuk menyesuaikan dengan tindakan pengguna dan mengeluarkan <a href="{@docRoot}guide/topics/resources/runtime-changes.html">perubahan waktu proses</a>
+  bila diperlukan. Jika aplikasi tertinggal dibandingkan gambar di area yang baru diekspos,
+  sistem untuk sementara mengisi area tersebut dengan warna yang ditetapkan oleh atribut {@link
+  android.R.attr#windowBackground windowBackground} atau dengan atribut gaya
+  <code>windowBackgroundFallback</code> secara default.
+</p>
+
+<h2 id="configuring">Mengonfigurasi Aplikasi Anda untuk Mode Multi-Jendela</h2>
+
+<p>
+  Jika aplikasi Anda menargetkan Android N, Anda bisa mengonfigurasi bagaimana dan
+  apakah aktivitas aplikasi Anda mendukung tampilan multi-jendela. Anda bisa menyetel
+  atribut dalam manifes untuk mengontrol ukuran dan layoutnya.
+  Setelan atribut aktivitas root berlaku pada semua aktivitas
+   dalam tumpukan tugasnya. Misalnya, jika aktivitas root memiliki
+  <code>android:resizeableActivity</code> yang disetel ke true, maka semua aktivitas
+  dalam tumpukan tugas bisa diubah ukurannya.
+</p>
+
+<p class="note">
+  <strong>Catatan:</strong> Jika Anda membangun aplikasi multi-orientasi dengan versi
+  SDK lebih rendah dari Android N, dan pengguna menggunakan aplikasi
+   dalam mode multi-jendela, sistem akan mengubah ukuran aplikasi secara paksa. Sistem akan menampilkan kotak
+  dialog yang memperingatkan pengguna bahwa aplikasi mungkin berperilaku tidak terduga. Sistem
+   <em>tidak</em> mengubah ukuran aplikasi yang berorientasi tetap; jika
+  pengguna berusaha membuka  aplikasi berorientasi tetap saat mode multi-jendela,
+  aplikasi akan menggunakan seluruh layar.
+</p>
+
+<h4 id="resizeableActivity">android:resizeableActivity</h4>
+<p>
+  Setel atribut ini dalam manifes <code>&lt;activity&gt;</code> Anda atau simpul
+  <code>&lt;application&gt;</code> untuk mengaktifkan atau menonaktifkan tampilan
+   multi-jendela:
+</p>
+
+<pre>
+android:resizeableActivity=["true" | "false"]
+</pre>
+
+<p>
+  Jika atribut ini disetel ke true, aktivitas bisa dijalankan di
+  mode layar terbagi dan mode bentuk bebas. Jika atribut ini disetel ke false, aktivitas
+  tidak akan mendukung mode multi-jendela. Jika nilai ini false, dan pengguna
+  berusaha memulai aktivitas dalam mode multi-jendela, aktivitas akan menggunakan
+   layar penuh.
+</p>
+
+<p>
+  Jika aplikasi Anda menargetkan Android N, namun Anda tidak menetapkan nilai
+  untuk atribut ini, nilai atribut default adalah true.
+</p>
+
+<h4 id="supportsPictureInPicture">android:supportsPictureInPicture</h4>
+
+<p>
+  Setel atribut ini dalam simpul <code>&lt;activity&gt;</code> manifes Anda untuk
+  menunjukkan apakah aktivitas mendukung tampilan gambar-dalam-gambar. Atribut ini
+  diabaikan jika <code>android:resizeableActivity</code> bernilai false.
+</p>
+
+<pre>
+android:supportsPictureInPicture=["true" | "false"]
+</pre>
+
+<h3 id="layout">Atribut layout</h3>
+
+<p>
+  Dengan Android N, elemen manifes <code>&lt;layout&gt;</code>
+  mendukung beberapa atribut yang memengaruhi cara aktivitas berperilaku dalam
+  mode multi-jendela:
+</p>
+
+<dl>
+  <dt>
+    <code>android:defaultWidth</code>
+  </dt>
+
+  <dd>
+    Lebar default aktivitas saat dijalankan dalam mode bentuk bebas.
+  </dd>
+
+  <dt>
+    <code>android:defaultHeight</code>
+  </dt>
+
+  <dd>
+    Tinggi default aktivitas saat dijalankan dalam mode bentuk bebas.
+  </dd>
+
+  <dt>
+    <code>android:gravity</code>
+  </dt>
+
+  <dd>
+    Penempatan awal dari aktivitas saat dibuka dalam mode bentuk bebas. Lihat referensi
+    {@link android.view.Gravity} untuk mengetahui nilai yang cocok.
+  </dd>
+
+  <dt>
+    <code>android:minimalHeight</code>, <code>android:minimalWidth</code>
+  </dt>
+
+  <dd>
+    Tinggi dan lebar minimum untuk aktivitas dalam mode layar terbagi
+    dan mode bentuk bebas. Jika pengguna memindahkan pembagi dalam mode layar terbagi
+    untuk membuat aktivitas lebih kecil dari minimum yang ditetapkan, sistem akan memangkas
+   aktivitas sesuai dengan ukuran yang diminta pengguna.
+  </dd>
+</dl>
+
+<p>
+  Misalnya, kode berikut menampilkan cara menetapkan ukuran dan lokasi default
+  aktivitas, dan ukuran minimumnya, bila aktivitas ditampilkan dalam
+   mode bentuk bebas:
+</p>
+
+<pre>
+&lt;activity android:name=".MyActivity"&gt;
+    &lt;layout android:defaultHeight="500dp"
+          android:defaultWidth="600dp"
+          android:gravity="top|end"
+          android:minimalHeight="450dp"
+          android:minimalWidth="300dp" /&gt;
+&lt;/activity&gt;
+</pre>
+
+<h2 id="running">Menjalankan Aplikasi Anda dalam Mode Multi-Jendela</h2>
+
+<p>
+  Android N menawarkan fungsionalitas baru untuk mendukung aplikasi yang bisa berjalan
+  dalam mode multi-jendela.
+</p>
+
+<h3 id="disabled-features">Fitur yang dinonaktifkan dalam mode multi-jendela</h3>
+
+<p>
+  Fitur tertentu akan dinonaktifkan atau diabaikan bila perangkat berada dalam mode
+  multi-jendela, karena dianggap tidak logis bagi suatu aktivitas yang mungkin berbagi
+  layar perangkat dengan aktivitas atau aplikasi lainnya. Fitur tersebut meliputi:
+
+<ul>
+  <li>Beberapa opsi penyesuaian di <a href="{@docRoot}training/system-ui/index.html">System UI</a>
+  dinonaktifkan; misalnya, aplikasi tidak bisa menyembunyikan bilah status
+  jika tidak berjalan dalam mode layar penuh.
+  </li>
+
+  <li>Sistem akan mengabaikan perubahan pada atribut <code><a href=
+  "{@docRoot}guide/topics/manifest/activity-element.html#screen"
+  >android:screenOrientation</a></code>.
+  </li>
+</ul>
+
+<h3 id="change-notification">Pemberitahuan perubahan multi-jendela dan melakukan kueri</h3>
+
+<p>
+  Metode baru berikut telah ditambahkan ke kelas {@link android.app.Activity}
+  untuk mendukung tampilan multi-jendela. Untuk mengetahui detail tentang setiap
+  metode, lihat <a href="{@docRoot}preview/setup-sdk.html#docs-dl">Referensi N
+ Preview SDK</a>.
+</p>
+
+<dl>
+  <dt>
+    <code>Activity.isInMultiWindowMode()</code>
+  </dt>
+
+  <dd>
+    Panggil untuk mengetahui apakah aktivitas berada dalam mode multi-jendela.
+  </dd>
+
+  <dt>
+    <code>Activity.isInPictureInPictureMode()</code>
+  </dt>
+
+  <dd>
+    Panggil untuk mengetahui apakah aktivitas berada dalam mode gambar-dalam-gambar.
+
+    <p class="note">
+      <strong>Catatan:</strong> Mode gambar-dalam-gambar adalah kasus khusus pada
+      mode multi-jendela. Jika <code>myActivity.isInPictureInPictureMode()</code>
+     mengembalikan nilai true, maka <code>myActivity.isInMultiWindowMode()</code> juga
+      mengembalikan nilai true.
+    </p>
+  </dd>
+
+  <dt>
+    <code>Activity.onMultiWindowModeChanged()</code>
+  </dt>
+
+  <dd>
+    Sistem akan memanggil metode ini bila aktivitas masuk atau keluar dari
+    mode multi-jendela. Sistem akan meneruskan ke metode sebuah nilai true jika
+   aktivitas tersebut memasuki mode multi-jendela, dan nilai false jika aktivitas
+     tersebut meninggalkan mode multi-jendela.
+  </dd>
+
+  <dt>
+    <code>Activity.onPictureInPictureModeChanged()</code>
+  </dt>
+
+  <dd>
+    Sistem akan memanggil metode ini bila aktivitas masuk atau keluar dari
+    mode gambar-dalam-gambar. Sistem akan meneruskan ke metode sebuah nilai true jika
+   aktivitas tersebut memasuki mode gambar-dalam-gambar, dan nilai false jika aktivitas
+     tersebut meninggalkan mode gambar-dalam-gambar.
+  </dd>
+</dl>
+
+<p>
+  Ada juga versi {@link android.app.Fragment} untuk setiap
+  metode ini, misalnya <code>Fragment.isInMultiWindowMode()</code>.
+</p>
+
+<h3 id="entering-pip">Memasuki mode gambar-dalam-gambar</h3>
+
+<p>
+  Untuk menempatkan aktivitas dalam mode gambar-dalam-gambar, panggil metode baru
+  <code>Activity.enterPictureInPictureMode()</code>. Metode ini tidak berpengaruh jika
+   perangkat tidak mendukung mode gambar-dalam-gambar. Untuk informasi selengkapnya,
+   lihat dokumentasi <a href="picture-in-picture.html">Gambar-dalam-Gambar</a>.
+</p>
+
+<h3 id="launch">Meluncurkan Aktivitas Baru dalam Mode Multi-Jendela</h3>
+
+<p>
+  Bila meluncurkan aktivitas baru, Anda bisa memberi petunjuk pada sistem bahwa aktivitas
+  baru harus ditampilkan bersebelahan dengan aktivitas yang sedang aktif, jika memungkinkan. Caranya,
+  gunakan flag
+  <code>Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT</code>. Meneruskan
+  flag ini akan meminta perilaku berikut:
+</p>
+
+<ul>
+  <li>Jika perangkat berada dalam mode layar terbagi, sistem akan berupaya membuat
+  aktivitas baru di sebelah aktivitas yang meluncurkannya, sehingga kedua aktivitas tersebut
+  berbagi layar. Tidak ada jaminan sistem mampu melakukannya, namun sistem akan
+  membuat aktivitas bersebelahan jika memungkinkan.
+  </li>
+
+  <li>Jika perangkat tidak berada dalam mode layar terbagi, flag ini tidak akan berpengaruh.
+  </li>
+</ul>
+
+<p>
+  Jika perangkat dalam mode bentuk bebas dan Anda menjalankan aktivitas baru, Anda bisa
+  menetapkan dimensi aktivitas baru dan lokasi layar dengan memanggil
+  <code>ActivityOptions.setLaunchBounds()</code>. Metode ini tidak berpengaruh jika
+  perangkat tidak berada dalam mode multi-jendela.
+</p>
+
+<p class="note">
+  <strong>Catatan:</strong> Jika Anda meluncurkan aktivitas dalam tumpukan tugas, aktivitas
+  tersebut akan menggantikan aktivitas pada layar, dengan mewarisi semua
+   properti multi-jendelanya. Jika Anda ingin meluncurkan aktivitas baru sebagai jendela
+  terpisah dalam mode multi-jendela, Anda harus meluncurkannya dalam tumpukan tugas baru.
+</p>
+
+<h3 id="dnd">Mendukung seret dan lepas</h3>
+
+<p>
+  Pengguna bisa <a href="{@docRoot}guide/topics/ui/drag-drop.html">menyeret dan
+  melepas</a> data dari satu aktivitas ke aktivitas yang lain selagi kedua aktivitas
+  berbagi layar. (Sebelumnya, pengguna hanya bisa menyeret dan melepas data dalam
+   aktivitas tunggal.) Karena alasan ini, Anda mungkin perlu menambahkan fungsionalitas
+  seret dan lepas ke aplikasi jika aplikasi saat ini belum mendukungnya.
+</p>
+
+<p>
+  N Preview SDK menambahkan paket <a href="{@docRoot}reference/android/view/package-summary.html"><code>android.view</code></a>
+  untuk mendukung seret dan lepas lintas-aplikasi. Untuk mengetahui detail tentang kelas dan metode
+  berikut, lihat <a href="{@docRoot}preview/setup-sdk.html#docs-dl">Referensi N
+  Preview SDK</a>.
+</p>
+
+<dl>
+  <dt>
+    <code>android.view.DropPermissions</code>
+  </dt>
+
+  <dd>
+    Objek token bertanggung jawab menetapkan izin yang diberikan kepada aplikasi
+    yang menerima pelepasan tersebut.
+  </dd>
+
+  <dt>
+    <code>View.startDragAndDrop()</code>
+  </dt>
+
+  <dd>
+    Alias baru untuk {@link android.view.View#startDrag View.startDrag()}. Untuk
+    mengaktifkan seret dan lepas lintas-aktivitas, teruskan flag baru
+    <code>View.DRAG_FLAG_GLOBAL</code>. Jika Anda perlu memberikan izin URI ke
+    aktivitas penerima, teruskan flag baru,
+    <code>View.DRAG_FLAG_GLOBAL_URI_READ</code> atau
+    <code>View.DRAG_FLAG_GLOBAL_URI_WRITE</code>, sebagaimana mestinya.
+  </dd>
+
+  <dt>
+    <code>View.cancelDragAndDrop()</code>
+  </dt>
+
+  <dd>
+    Membatalkan operasi seret yang sedang berlangsung. Hanya bisa dipanggil oleh
+    aplikasi yang menghasilkan operasi seret.
+  </dd>
+
+  <dt>
+    <code>View.updateDragShadow()</code>
+  </dt>
+
+  <dd>
+    Menggantikan bayangan penyeretan untuk operasi seret yang sedang berlangsung. Hanya
+    bisa dipanggil oleh aplikasi yang menghasilkan operasi seret.
+  </dd>
+
+  <dt>
+    <code>Activity.requestDropPermissions()</code>
+  </dt>
+
+  <dd>
+    Meminta izin untuk URI materi yang diteruskan dengan {@link
+    android.content.ClipData} yang terdapat dalam {@link android.view.DragEvent}.
+  </dd>
+</dl>
+
+<h2 id="testing">Menguji Dukungan Multi-Jendela Aplikasi Anda</h2>
+
+<p>
+  Apakah Anda memperbarui aplikasi untuk Android N atau tidak, Anda harus
+  verifikasi bagaimana perilakunya di mode multi-jendela saat pengguna mencoba untuk menjalankannya
+  dalam mode multi-jendela pada perangkat yang menjalankan Android N.
+</p>
+
+<h3 id="configuring">Mengonfigurasi Perangkat Pengujian</h3>
+
+<p>
+  Jika Anda pasang Android N pada perangkat, mode
+  layar terbagi secara otomatis didukung.
+</p>
+
+<h3 id="test-non-n">Jika aplikasi Anda tidak dibangun dengan N Preview SDK</h3>
+
+<p>
+  Jika Anda tidak membangun aplikasi dengan N Preview SDK dan pengguna berupaya menggunakan
+  aplikasi dalam mode multi-jendela, sistem secara paksa akan mengubah ukuran aplikasi kecuali jika aplikasi
+  mendeklarasikan orientasi tetap.
+</p>
+
+<p>
+  Jika aplikasi Anda tidak mendeklarasikan orientasi tetap, Anda harus meluncurkan aplikasi
+  pada perangkat yang menjalankan Android N dan berupaya menempatkan aplikasi tersebut dalam
+  mode layar terbagi. Verifikasi pengalaman pengguna
+  bisa diterima bila aplikasi secara paksa diubah ukurannya.
+</p>
+
+<p>
+  Jika aplikasi mendeklarasikan orientasi tetap, Anda harus berupaya menempatkan aplikasi dalam
+  mode multi-jendela. Verifikasi apakah saat Anda melakukannya, aplikasi tetap berada dalam
+  mode layar penuh.
+</p>
+
+<h3 id="test-mw">Jika Anda mendukung mode multi-jendela</h3>
+
+<p>
+  Jika Anda membuat aplikasi Anda dengan N Preview SDK dan belum menonaktifkan
+  dukungan multi-jendela, verifikasi perilaku berikut dalam mode layar terbagi
+   dan mode bentuk bebas.
+</p>
+
+<ul>
+  <li>Luncurkan aplikasi dalam mode layar penuh, kemudian beralih ke mode multi-jendela dengan
+   menekan lama pada tombol Ringkasan. Verifikasi apakah aplikasi beralih dengan benar.
+  </li>
+
+  <li>Jalankan aplikasi secara langsung dalam mode multi-jendela, dan verifikasi aplikasi
+  diluncurkan dengan benar. Anda bisa meluncurkan aplikasi dalam mode multi-jendela dengan menekan
+  tombol Ringkasan, kemudian menekan lama baris judul pada aplikasi Anda dan menyeretnya
+  ke salah satu area yang disorot di layar.
+  </li>
+
+  <li>Ubah ukuran aplikasi Anda dalam mode layar terbagi dengan menyeret garis pembagi.
+  Verifikasi apakah aplikasi mengubah ukuran tanpa mogok, dan apakah elemen UI yang diperlukan
+  terlihat.
+  </li>
+
+  <li>Jika Anda telah menetapkan dimensi minimum aplikasi, cobalah untuk mengubah ukuran
+  aplikasi di bawah dimensi tersebut. Verifikasi apakah Anda tidak bisa mengubah ukuran aplikasi menjadi
+  lebih kecil dari minimum yang ditetapkan.
+  </li>
+
+  <li>Melalui semua pengujian, verifikasi apakah kinerja aplikasi Anda bisa diterima. Misalnya,
+  verifikasi apakah tidak ada jeda yang terlalu lama untuk memperbarui UI setelah
+  aplikasi diubah ukurannya.
+  </li>
+</ul>
+
+<h4 id="test-checklist">Daftar periksa pengujian</h4>
+
+<p>
+  Untuk verifikasi kinerja aplikasi Anda dalam mode multi-jendela, cobalah operasi
+  berikut. Anda harus mencoba semua operasi ini dalam mode layar terbagi dan
+   dan mode multi-jendela, kecuali jika dinyatakan berbeda.
+</p>
+
+<ul>
+  <li>Masuki dan tinggalkan mode multi-jendela.
+  </li>
+
+  <li>Beralih dari aplikasi Anda ke aplikasi lain, dan verifikasi apakah aplikasi berperilaku
+   sebagaimana mestinya saat terlihat namun tidak aktif. Misalnya, jika aplikasi Anda
+   sedang memutar video, verifikasi apakah video terus diputar selagi pengguna
+  berinteraksi dengan aplikasi lain.
+  </li>
+
+  <li>Dalam mode layar terbagi, cobalah menggeser garis pembagi untuk membuat aplikasi
+  Anda menjadi lebih besar dan lebih kecil. Coba operasi ini dalam konfigurasi berdampingan dan
+  atas-bawah. Verifikasi apakah aplikasi tidak mogok,
+  fungsionalitas penting bisa terlihat, dan operasi mengubah ukuran tidak memakan waktu terlalu
+  lama.
+  </li>
+
+  <li>Lakukan beberapa operasi ubah ukuran berturut-turut dalam waktu cepat. Verifikasi apakah
+  aplikasi Anda tidak mogok atau mengalami kebocoran memori. Untuk informasi tentang memeriksa penggunaan memori
+  aplikasi Anda, lihat <a href="{@docRoot}tools/debugging/debugging-memory.html">
+  Menyelidiki Penggunaan RAM Anda</a>.
+  </li>
+
+  <li>Gunakan aplikasi secara normal di sejumlah konfigurasi jendela yang berbeda, dan
+  verifikasi apakah aplikasi berperilaku sebagaimana mestinya. Verifikasi apakah teks terbaca, dan apakah
+  elemen UI tidak terlalu kecil untuk interaksi.
+  </li>
+</ul>
+
+<h3 id="test-disabled-mw">Jika Anda telah menonaktifkan dukungan multi-jendela</h3>
+
+<p>
+  Jika Anda menonaktifkan dukungan multi-jendela dengan menyetel
+  <code>android:resizableActivity="false"</code>, Anda harus menjalankan aplikasi pada
+  perangkat yang menjalankan Android N dan berusaha menempatkan aplikasi dalam
+  mode bentuk bebas dan mode layar terbagi. Verifikasi apakah saat Anda melakukannya, aplikasi tetap berada dalam
+  mode layar penuh.
+</p>
diff --git a/docs/html-intl/intl/id/guide/topics/ui/notifiers/notifications.jd b/docs/html-intl/intl/id/guide/topics/ui/notifiers/notifications.jd
new file mode 100644
index 0000000..bb48b80
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/ui/notifiers/notifications.jd
@@ -0,0 +1,979 @@
+page.title=Pemberitahuan
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>Dalam dokumen ini</h2>
+<ol>
+  <li><a href="#Design">Pertimbangan Desain</a></li>
+  <li><a href="#CreateNotification">Membuat Pemberitahuan</a>
+    <ol>
+      <li><a href="#Required">Isi pemberitahuan yang diperlukan</a></li>
+      <li><a href="#Optional">Isi dan pengaturan pemberitahuan opsional</a></li>
+      <li><a href="#Actions">Tindakan pemberitahuan</a></li>
+      <li><a href="#Priority">Prioritas pemberitahuan</a></li>
+      <li><a href="#SimpleNotification">Membuat pemberitahuan sederhana</a></li>
+      <li><a href="#ApplyStyle">Menerapkan layout yang diperluas pada pemberitahuan</a></li>
+      <li><a href="#Compatibility">Menangani kompatibilitas</a></li>
+    </ol>
+  </li>
+  <li><a href="#Managing">Mengelola Pemberitahuan</a>
+    <ol>
+      <li><a href="#Updating">Memperbarui pemberitahuan</a></li>
+      <li><a href="#Removing">Menghapus pemberitahuan</a></li>
+    </ol>
+  </li>
+  <li><a href="#NotificationResponse">Mempertahankan Navigasi saat Memulai Aktivitas</a>
+    <ol>
+      <li><a href="#DirectEntry">Menyiapkan PendingIntent aktivitas biasa</a></li>
+      <li><a href="#ExtendedNotification">Menyiapkan PendingIntent aktivitas khusus</a></li>
+    </ol>
+  </li>
+  <li><a href="#Progress">Menampilkan Kemajuan dalam Pemberitahuan</a>
+    <ol>
+      <li><a href="#FixedProgress">Menampilkan indikator kemajuan berdurasi tetap</a></li>
+      <li><a href="#ActivityIndicator">Menampilkan indikator aktivitas berlanjut</a></li>
+    </ol>
+  </li>
+  <li><a href="#metadata">Metadata Pemberitahuan</a></li>
+  <li><a href="#Heads-up">Pemberitahuan Pendahuluan</a></li>
+  <li><a href="#lockscreenNotification">Pemberitahuan Layar Kunci</a></li>
+    <ol>
+      <li><a href="#visibility">Mengatur Visibilitas</a></li>
+      <li><a href="#controllingMedia">Mengontrol Pemutaran Media pada Layar Kunci</a></li>
+    </ol>
+  <li><a href="#CustomNotification">Layout Pemberitahuan Custom</a></li>
+</ol>
+
+    <h2>Kelas-kelas utama</h2>
+    <ol>
+        <li>{@link android.app.NotificationManager}</li>
+        <li>{@link android.support.v4.app.NotificationCompat}</li>
+    </ol>
+    <h2>Video</h2>
+    <ol>
+        <li>
+            <a href="http://www.youtube.com/watch?v=Yc8YrVc47TI&amp;feature=player_detailpage#t=1672s">
+            Pemberitahuan di 4.1</a>
+        </li>
+    </ol>
+<h2>Lihat juga</h2>
+<ol>
+    <li>
+        <a href="{@docRoot}design/patterns/notifications.html">Desain Android: Pemberitahuan</a>
+    </li>
+</ol>
+</div>
+</div>
+<p>
+    Pemberitahuan adalah pesan yang bisa Anda tampilkan kepada pengguna di luar
+    UI normal aplikasi. Bila Anda memberi tahu sistem untuk mengeluarkan pemberitahuan, pemberitahuan akan muncul lebih dahulu sebagai ikon dalam
+    <strong>area pemberitahuan</strong>. Untuk melihat detail pemberitahuan, pengguna membuka
+    <strong>laci pemberitahuan</strong>. Baik area pemberitahuan maupun laci pemberitahuan
+    adalah area-area yang dikontrol sistem yang bisa dilihat pengguna kapan saja.
+</p>
+<img id="figure1" src="{@docRoot}images/ui/notifications/notification_area.png" height="" alt="" />
+<p class="img-caption">
+    <strong>Gambar 1.</strong> Pemberitahuan di area pemberitahuan.
+</p>
+<img id="figure2" src="{@docRoot}images/ui/notifications/notification_drawer.png" width="280px" alt="" />
+<p class="img-caption">
+    <strong>Gambar 2.</strong> Pemberitahuan di laci pemberitahuan.
+</p>
+
+<p class="note"><strong>Catatan:</strong> Kecuali disebutkan, panduan ini mengacu pada
+kelas {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}
+dalam <a href="{@docRoot}tools/support-library/index.html">Support Library</a> versi 4.
+Kelas {@link android.app.Notification.Builder Notification.Builder} telah ditambahkan pada Android
+3.0 (API level 11).</p>
+
+<h2 id="Design">Pertimbangan Desain</h2>
+
+<p>Pemberitahuan, sebagai bagian penting dari antarmuka pengguna Android, memiliki panduan desainnya sendiri.
+Perubahan desain materi yang diperkenalkan dalam Android 5.0 (API level 21) adalah sangat
+penting, dan Anda harus meninjau pelatihan <a href="{@docRoot}training/material/index.html">Desain Bahan</a>
+untuk informasi selengkapnya. Untuk mengetahui cara mendesain pemberitahuan dan interaksinya, bacalah panduan desain
+<a href="{@docRoot}design/patterns/notifications.html">Pemberitahuan</a>.</p>
+
+<h2 id="CreateNotification">Membuat Pemberitahuan</h2>
+
+<p>Anda menetapkan informasi dan tindakan UI bagi pemberitahuan dalam
+objek {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}.
+Untuk membuat pemberitahuan itu sendiri, panggil
+{@link android.support.v4.app.NotificationCompat.Builder#build NotificationCompat.Builder.build()},
+yang akan mengembalikan objek {@link android.app.Notification} berisi spesifikasi Anda. Untuk mengeluarkan
+pemberitahuan, Anda meneruskan objek {@link android.app.Notification} ke sistem dengan memanggil
+{@link android.app.NotificationManager#notify NotificationManager.notify()}.</p>
+
+<h3 id="Required">Isi pemberitahuan yang diperlukan</h3>
+<p>
+    Objek {@link android.app.Notification} <em>harus</em> berisi yang berikut ini:
+</p>
+<ul>
+    <li>
+        Ikon kecil, yang diatur dengan
+        {@link android.support.v4.app.NotificationCompat.Builder#setSmallIcon setSmallIcon()}
+    </li>
+    <li>
+        Judul, yang diatur dengan
+        {@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()}
+    </li>
+    <li>
+        Teks detail, yang diatur dengan
+        {@link android.support.v4.app.NotificationCompat.Builder#setContentText setContentText()}
+    </li>
+</ul>
+<h3 id="Optional">Isi dan pengaturan pemberitahuan opsional</h3>
+<p>
+    Semua isi dan pengaturan pemberitahuan lainnya bersifat opsional. Untuk mengetahui selengkapnya tentang semua itu,
+    lihat dokumentasi acuan untuk {@link android.support.v4.app.NotificationCompat.Builder}.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="Actions">Tindakan pemberitahuan</h3>
+<p>
+    Walaupun bersifat opsional, Anda harus menambahkan setidaknya satu tindakan pada pemberitahuan.
+    Tindakan memungkinkan pengguna beralih langsung dari pemberitahuan ke
+    {@link android.app.Activity} dalam aplikasi Anda, tempat pengguna bisa melihat satu atau beberapa kejadian
+    atau melakukan pekerjaan lebih jauh.
+</p>
+<p>
+    Pemberitahuan bisa menyediakan beberapa tindakan sekaligus. Anda harus selalu mendefinisikan tindakan yang
+    akan diaktifkan bila pengguna mengklik pemberitahuan; biasanya tindakan ini akan membuka
+    {@link android.app.Activity} dalam aplikasi Anda. Anda juga bisa menambahkan tombol pada pemberitahuan
+    yang melakukan tindakan tambahan seperti mendiamkan alarm atau segera merespons
+    pesan teks; fitur ini tersedia mulai Android 4.1. Jika menggunakan tombol tindakan tambahan, Anda
+    juga harus membuat fungsionalitasnya tersedia dalam {@link android.app.Activity} di aplikasi Anda; lihat
+    bagian <a href="#Compatibility">Menangani kompatibilitas</a> untuk detail selengkapnya.
+</p>
+<p>
+    Dalam {@link android.app.Notification}, tindakan itu sendiri didefinisikan oleh
+    {@link android.app.PendingIntent} berisi
+    {@link android.content.Intent} yang memulai
+    {@link android.app.Activity} dalam aplikasi Anda. Untuk mengaitkan
+    {@link android.app.PendingIntent} dengan gestur, panggil metode
+    {@link android.support.v4.app.NotificationCompat.Builder} yang sesuai. Misalnya, jika ingin memulai
+    {@link android.app.Activity} bila pengguna mengklik teks pemberitahuan pada
+    laci pemberitahuan, tambahkan {@link android.app.PendingIntent} dengan memanggil
+    {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}.
+</p>
+<p>
+    Memulai {@link android.app.Activity} bila pengguna mengklik pemberitahuan adalah
+    skenario tindakan yang paling umum. Anda juga bisa memulai {@link android.app.Activity} bila pengguna
+    menghilangkan pemberitahuan. Dalam Android 4.1 dan yang lebih baru, Anda bisa memulai
+    {@link android.app.Activity} dari tombol tindakan. Untuk mengetahui selengkapnya, bacalah panduan acuan untuk
+    {@link android.support.v4.app.NotificationCompat.Builder}.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="Priority">Prioritas pemberitahuan</h3>
+<p>
+    Jika diinginkan, Anda bisa mengatur prioritas pemberitahuan. Prioritas berfungsi
+    sebagai petunjuk bagi UI perangkat tentang cara menampilkan pemberitahuan.
+    Untuk mengatur prioritas pemberitahuan, panggil {@link
+    android.support.v4.app.NotificationCompat.Builder#setPriority(int)
+    NotificationCompat.Builder.setPriority()} dan teruskan salah satu konstanta prioritas {@link
+    android.support.v4.app.NotificationCompat}. Ada
+    lima level prioritas, mulai dari {@link
+    android.support.v4.app.NotificationCompat#PRIORITY_MIN} (-2) hingga {@link
+    android.support.v4.app.NotificationCompat#PRIORITY_MAX} (2); jika tidak diatur,
+    prioritas default akan ditetapkan {@link
+    android.support.v4.app.NotificationCompat#PRIORITY_DEFAULT} (0).
+</p>
+<p> Untuk informasi tentang mengatur level prioritas, lihat "Mengatur
+    dan mengelola prioritas pemberitahuan dengan benar" dalam panduan
+Desain <a href="{@docRoot}design/patterns/notifications.html">Pemberitahuan</a>.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="SimpleNotification">Membuat pemberitahuan sederhana</h3>
+<p>
+    Cuplikan berikut mengilustrasikan pemberitahuan sederhana yang menetapkan aktivitas untuk dibuka bila
+    pengguna mengklik pemberitahuan. Perhatikan bahwa kode ini membuat
+    objek {@link android.support.v4.app.TaskStackBuilder} dan menggunakannya untuk membuat
+    {@link android.app.PendingIntent} untuk tindakan. Pola ini dijelaskan secara lebih detail
+    di bagian <a href="#NotificationResponse">
+    Mempertahankan Navigasi saat Memulai Aktivitas</a>:
+</p>
+<pre>
+NotificationCompat.Builder mBuilder =
+        new NotificationCompat.Builder(this)
+        .setSmallIcon(R.drawable.notification_icon)
+        .setContentTitle("My notification")
+        .setContentText("Hello World!");
+// Creates an explicit intent for an Activity in your app
+Intent resultIntent = new Intent(this, ResultActivity.class);
+
+// The stack builder object will contain an artificial back stack for the
+// started Activity.
+// This ensures that navigating backward from the Activity leads out of
+// your application to the Home screen.
+TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
+// Adds the back stack for the Intent (but not the Intent itself)
+stackBuilder.addParentStack(ResultActivity.class);
+// Adds the Intent that starts the Activity to the top of the stack
+stackBuilder.addNextIntent(resultIntent);
+PendingIntent resultPendingIntent =
+        stackBuilder.getPendingIntent(
+            0,
+            PendingIntent.FLAG_UPDATE_CURRENT
+        );
+mBuilder.setContentIntent(resultPendingIntent);
+NotificationManager mNotificationManager =
+    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+// mId allows you to update the notification later on.
+mNotificationManager.notify(mId, mBuilder.build());
+</pre>
+<p>Demikian saja. Pengguna Anda kini telah diberi tahu.</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="ApplyStyle">Menerapkan layout yang diperluas pada pemberitahuan</h3>
+<p>
+    Agar pemberitahuan muncul dalam tampilan yang diperluas, buat dahulu
+    objek {@link android.support.v4.app.NotificationCompat.Builder} dengan opsi tampilan normal
+    yang Anda inginkan. Berikutnya, panggil {@link android.support.v4.app.NotificationCompat.Builder#setStyle
+    Builder.setStyle()}  dengan objek layout yang diperluas sebagai argumennya.
+</p>
+<p>
+    Ingatlah bahwa pemberitahuan yang diperluas tidak tersedia pada platform-platform sebelum Android 4.1. Untuk
+    mengetahui cara menangani pemberitahuan untuk Android 4.1 dan untuk platform-platform sebelumnya, bacalah
+    bagian <a href="#Compatibility">Menangani kompatibilitas</a>.
+</p>
+<p>
+    Misalnya, cuplikan kode berikut memperagakan cara mengubah pemberitahuan yang dibuat
+    dalam cuplikan sebelumnya untuk menggunakan layout yang diperluas:
+</p>
+<pre>
+NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
+    .setSmallIcon(R.drawable.notification_icon)
+    .setContentTitle("Event tracker")
+    .setContentText("Events received")
+NotificationCompat.InboxStyle inboxStyle =
+        new NotificationCompat.InboxStyle();
+String[] events = new String[6];
+// Sets a title for the Inbox in expanded layout
+inboxStyle.setBigContentTitle("Event tracker details:");
+...
+// Moves events into the expanded layout
+for (int i=0; i &lt; events.length; i++) {
+
+    inboxStyle.addLine(events[i]);
+}
+// Moves the expanded layout object into the notification object.
+mBuilder.setStyle(inBoxStyle);
+...
+// Issue the notification here.
+</pre>
+
+<h3 id="Compatibility">Menangani kompatibilitas</h3>
+
+<p>
+    Tidak semua fitur pemberitahuan tersedia untuk versi tertentu, walaupun
+    metode untuk mengaturnya ada dalam kelas pustaka dukungan
+    {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}.
+    Misalnya, tombol tindakan, yang bergantung pada pemberitahuan yang diperluas, hanya muncul pada Android
+    4.1 dan lebih tinggi, karena pemberitahuan yang diperluas itu sendiri hanya tersedia pada
+    Android 4.1 dan yang lebih tinggi.
+</p>
+<p>
+    Untuk memastikan kompatibilitas terbaik, buatlah pemberitahuan dengan
+    {@link android.support.v4.app.NotificationCompat NotificationCompat} dan subkelasnya,
+    khususnya {@link android.support.v4.app.NotificationCompat.Builder
+    NotificationCompat.Builder}. Selain itu, ikutilah proses ini bila Anda mengimplementasikan pemberitahuan:
+</p>
+<ol>
+    <li>
+        Sediakan semua fungsionalitas pemberitahuan kepada semua pengguna, terlepas dari versi
+        yang mereka gunakan. Caranya, pastikan semua fungsionalitas tersedia dari
+        {@link android.app.Activity} dalam aplikasi Anda. Anda mungkin perlu menambahkan sebuah
+        {@link android.app.Activity} baru untuk melakukannya.
+        <p>
+            Misalnya, jika Anda ingin menggunakan
+            {@link android.support.v4.app.NotificationCompat.Builder#addAction addAction()} untuk
+            menyediakan kontrol yang menghentikan dan memulai pemutaran media, implementasikan dahulu
+            kontrol ini pada {@link android.app.Activity} dalam aplikasi Anda.
+        </p>
+    </li>
+    <li>
+        Pastikan semua pengguna bisa memperoleh fungsionalitas dalam {@link android.app.Activity},
+        dengan memulainya bila pengguna mengklik pemberitahuan. Caranya,
+        buatlah {@link android.app.PendingIntent}
+        untuk {@link android.app.Activity}. Panggil
+        {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
+        setContentIntent()} untuk menambahkan {@link android.app.PendingIntent} pada pemberitahuan.
+    </li>
+    <li>
+        Kini tambahkan fitur pemberitahuan diperluas yang ingin Anda gunakan pada pemberitahuan. Ingatlah
+        bahwa setiap fungsionalitas yang Anda tambahkan juga harus tersedia dalam {@link android.app.Activity}
+        yang akan dimulai bila pengguna mengklik pemberitahuan.
+    </li>
+</ol>
+
+
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="Managing">Mengelola Pemberitahuan</h2>
+<p>
+    Bila perlu mengeluarkan pemberitahuan beberapa kali untuk tipe kejadian yang sama,
+hindari membuat pemberitahuan yang sama sekali baru. Sebagai gantinya, Anda harus mempertimbangkan untuk memperbarui
+    pemberitahuan sebelumnya, baik dengan mengubah sebagian nilainya atau dengan menambahkan nilai, atau keduanya.
+</p>
+<p>
+    Misalnya, Gmail akan memberi tahu pengguna bila ada email baru dengan menambah hitungan
+    pesan tidak terbaca dan dengan menambahkan rangkuman tiap email ke pemberitahuan. Ini disebut dengan
+    "stacking" (menumpuk) pemberitahuan; hal ini dijelaskan lebih detail dalam panduan
+    Desain <a href="{@docRoot}design/patterns/notifications.html">Pemberitahuan</a>.
+</p>
+<p class="note">
+    <strong>Catatan:</strong> Fitur Gmail ini mensyaratkan layout "kotak masuk" diperluas, yang merupakan
+    bagian dari fitur pemberitahuan diperluas yang tersedia mulai Android 4.1.
+</p>
+<p>
+    Bagian berikut menjelaskan cara memperbarui pemberitahuan dan cara menghapusnya.
+</p>
+<h3 id="Updating">Memperbarui pemberitahuan</h3>
+<p>
+    Untuk menyiapkan pemberitahuan agar bisa diperbarui, keluarkan pemberitahuan bersama ID pemberitahuan dengan
+    memanggil {@link android.app.NotificationManager#notify(int, android.app.Notification) NotificationManager.notify()}.
+    Untuk memperbarui pemberitahuan ini setelah Anda
+    mengeluarkan, memperbarui, atau membuat objek {@link android.support.v4.app.NotificationCompat.Builder},
+    buat objek {@link android.app.Notification} darinya, dan keluarkan
+    {@link android.app.Notification} bersama ID yang sama dengan yang Anda gunakan sebelumnya. Jika
+    pemberitahuan sebelumnya tetap terlihat, sistem akan memperbaruinya dari konten
+    objek {@link android.app.Notification}. Jika pemberitahuan sebelumnya telah dihilangkan, sebuah
+    pemberitahuan baru akan dibuat.
+</p>
+<p>
+    Cuplikan berikut memperagakan pemberitahuan yang diperbarui untuk mencerminkan
+    jumlah kejadian yang telah terjadi. Cuplikan ini menumpuk pemberitahuan, yang menampilkan rangkuman:
+</p>
+<pre>
+mNotificationManager =
+        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+// Sets an ID for the notification, so it can be updated
+int notifyID = 1;
+mNotifyBuilder = new NotificationCompat.Builder(this)
+    .setContentTitle("New Message")
+    .setContentText("You've received new messages.")
+    .setSmallIcon(R.drawable.ic_notify_status)
+numMessages = 0;
+// Start of a loop that processes data and then notifies the user
+...
+    mNotifyBuilder.setContentText(currentText)
+        .setNumber(++numMessages);
+    // Because the ID remains unchanged, the existing notification is
+    // updated.
+    mNotificationManager.notify(
+            notifyID,
+            mNotifyBuilder.build());
+...
+</pre>
+
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="Removing">Menghapus pemberitahuan</h3>
+<p>
+    Pemberitahuan tetap terlihat hingga salah satu kejadian berikut terjadi:
+</p>
+<ul>
+    <li>
+        Pengguna menghilangkan pemberitahuan satu per satu atau dengan menggunakan "Clear All" (jika
+        pemberitahuan bisa dihapus).
+    </li>
+    <li>
+        Pengguna mengklik pemberitahuan, dan Anda memanggil
+        {@link android.support.v4.app.NotificationCompat.Builder#setAutoCancel setAutoCancel()} bila
+        Anda telah membuat pemberitahuan.
+    </li>
+    <li>
+        Anda memanggil {@link android.app.NotificationManager#cancel(int) cancel()} untuk
+        ID pemberitahuan tertentu. Metode ini juga menghapus pemberitahuan yang berjalan.
+    </li>
+    <li>
+        Anda memanggil {@link android.app.NotificationManager#cancelAll() cancelAll()}, yang menghapus
+        semua pemberitahuan yang dikeluarkan sebelumnya.
+    </li>
+</ul>
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="NotificationResponse">Mempertahankan Navigasi saat Memulai Aktivitas</h2>
+<p>
+    Bila memulai {@link android.app.Activity} dari pemberitahuan, Anda harus mempertahankan
+    pengalaman navigasi yang diharapkan pengguna. Mengklik <i>Back</i> harus membawa pengguna kembali melalui
+    aliran pekerjaan normal aplikasi ke layar Home, dan mengklik <i>Recents</i> harus menampilkan
+    {@link android.app.Activity} sebagai tugas terpisah. Untuk mempertahankan pengalaman navigasi, Anda
+    harus memulai {@link android.app.Activity} dalam tugas baru. Cara menyiapkan
+    {@link android.app.PendingIntent} untuk memberi Anda tugas baru bergantung pada sifat
+    {@link android.app.Activity} yang Anda mulai. Ada dua situasi umum:
+</p>
+<dl>
+    <dt>
+        Aktivitas rutin
+    </dt>
+    <dd>
+        Anda memulai {@link android.app.Activity} yang merupakan bagian dari aliran pekerjaan normal
+        aplikasi. Dalam situasi ini, siapkan {@link android.app.PendingIntent} untuk
+        memulai tugas baru, dan sediakan {@link android.app.PendingIntent} bersama back-stack
+        yang meniru perilaku <i>Back</i> biasa.
+        <p>
+            Pemberitahuan dari aplikasi Gmail memperagakan hal ini. Bila Anda mengklik pemberitahuan untuk
+            satu pesan email, Anda akan melihat pesan itu sendiri. Menyentuh <b>Back</b> akan membawa Anda
+            kembali melalui Gmail ke layar Home, persis seperti jika memasuki Gmail dari
+            layar Home bukannya memasukinya dari pemberitahuan.
+        </p>
+        <p>
+            Hal ini terjadi terlepas dari aplikasi tempat Anda berada saat menyentuh
+            pemberitahuan. Misalnya, jika Anda dalam Gmail sedang menulis pesan, dan Anda mengklik
+            pemberitahuan untuk satu email, Anda akan segera dibawa ke email itu. Menyentuh <i>Back</i>
+            akan membawa Anda ke kotak masuk kemudian layar Home, bukannya membawa Anda ke
+            pesan yang sedang ditulis.
+        </p>
+    </dd>
+    <dt>
+        Aktivitas khusus
+    </dt>
+    <dd>
+        Pengguna hanya melihat {@link android.app.Activity} ini jika dimulai dari pemberitahuan.
+        Dalam beberapa hal, {@link android.app.Activity} akan memperluas pemberitahuan dengan menyediakan
+        informasi yang akan sulit untuk ditampilkan dalam pemberitahuan itu sendiri. Untuk situasi ini,
+        siapkan {@link android.app.PendingIntent} untuk dimulai dalam tugas baru. Tidak perlu
+        membuat back-stack, karena {@link android.app.Activity} yang dimulai bukan bagian dari
+        aliran aktivitas aplikasi. Mengklik <i>Back</i> tetap akan membawa pengguna ke
+        layar Home.
+    </dd>
+</dl>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="DirectEntry">Menyiapkan PendingIntent aktivitas biasa</h3>
+<p>
+    Untuk menyiapkan {@link android.app.PendingIntent} yang memulai entri langsung
+    {@link android.app.Activity}, ikuti langkah-langkah ini:
+</p>
+<ol>
+    <li>
+        Definisikan hierarki {@link android.app.Activity} aplikasi Anda dalam manifes.
+        <ol style="list-style-type: lower-alpha;">
+            <li>
+                Tambahkan dukungan untuk Android 4.0.3 dan yang terdahulu. Caranya, tetapkan induk
+                {@link android.app.Activity} yang Anda mulai dengan menambahkan elemen
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
+                sebagai anak
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>.
+                <p>
+                    Untuk elemen ini, atur
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a>="android.support.PARENT_ACTIVITY"</code>.
+                    Atur
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#val">android:value</a>="&lt;parent_activity_name&gt;"</code>
+                    dengan <code>&lt;parent_activity_name&gt;</code> sebagai nilai
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a></code>
+                    untuk elemen induk
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+. Lihat XML berikut sebagai contoh.
+                </p>
+            </li>
+            <li>
+                Juga tambahkan dukungan untuk Android 4.1 dan yang lebih baru. Caranya, tambahkan atribut
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#parent">android:parentActivityName</a></code>
+                 pada elemen
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+                dari {@link android.app.Activity} yang Anda mulai.
+            </li>
+        </ol>
+        <p>
+            XML akhir akan terlihat seperti ini:
+        </p>
+<pre>
+&lt;activity
+    android:name=".MainActivity"
+    android:label="&#64;string/app_name" &gt;
+    &lt;intent-filter&gt;
+        &lt;action android:name="android.intent.action.MAIN" /&gt;
+        &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
+    &lt;/intent-filter&gt;
+&lt;/activity&gt;
+&lt;activity
+    android:name=".ResultActivity"
+    android:parentActivityName=".MainActivity"&gt;
+    &lt;meta-data
+        android:name="android.support.PARENT_ACTIVITY"
+        android:value=".MainActivity"/&gt;
+&lt;/activity&gt;
+</pre>
+    </li>
+    <li>
+        Buat back-stack berdasarkan {@link android.content.Intent} yang memulai
+        {@link android.app.Activity}:
+        <ol style="list-style-type: lower-alpha;">
+            <li>
+                Buat {@link android.content.Intent} untuk memulai {@link android.app.Activity}.
+            </li>
+            <li>
+                Buat stack-builder (pembangun tumpukan) dengan memanggil {@link android.app.TaskStackBuilder#create
+                TaskStackBuilder.create()}.
+            </li>
+            <li>
+                Tambahkan back-stack ke stack-builder dengan memanggil
+                {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}.
+                Untuk setiap {@link android.app.Activity} dalam hierarki yang telah Anda definisikan dalam
+                manifes, back-stack berisi objek {@link android.content.Intent} yang
+                memulai {@link android.app.Activity}. Metode ini juga menambahkan flag yang memulai
+                back-stack dalam tugas baru.
+                <p class="note">
+                    <strong>Catatan:</strong> Walaupun argumen untuk
+                    {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}
+                    adalah acuan ke {@link android.app.Activity} yang dimulai, panggilan metode
+                    tidak akan menambahkan {@link android.content.Intent} yang memulai
+                    {@link android.app.Activity}. Sebagai gantinya, hal itu ditangani dalam langkah berikutnya.
+                </p>
+            </li>
+            <li>
+                Tambahkan {@link android.content.Intent} yang memulai {@link android.app.Activity}
+                dari pemberitahuan, dengan memanggil
+                {@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}.
+                Teruskan {@link android.content.Intent} yang Anda buat dalam langkah pertama sebagai
+                argumen ke
+                {@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}.
+            </li>
+            <li>
+                Jika perlu, tambahkan argumen ke objek {@link android.content.Intent} pada
+                back-stack dengan memanggil {@link android.support.v4.app.TaskStackBuilder#editIntentAt
+                TaskStackBuilder.editIntentAt()}. Kadang-kadang perlu memastikan apakah
+                {@link android.app.Activity} target menampilkan data bermakna saat pengguna menelusurinya
+                dengan menggunakan <i>Back</i>.
+            </li>
+            <li>
+                Dapatkan {@link android.app.PendingIntent} untuk back-stack ini dengan memanggil
+                {@link android.support.v4.app.TaskStackBuilder#getPendingIntent getPendingIntent()}.
+                Anda nanti bisa menggunakan {@link android.app.PendingIntent} ini sebagai argumen untuk
+                {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
+                setContentIntent()}.
+            </li>
+        </ol>
+     </li>
+</ol>
+<p>
+    Cuplikan kode berikut memperagakan prosesnya:
+</p>
+<pre>
+...
+Intent resultIntent = new Intent(this, ResultActivity.class);
+TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
+// Adds the back stack
+stackBuilder.addParentStack(ResultActivity.class);
+// Adds the Intent to the top of the stack
+stackBuilder.addNextIntent(resultIntent);
+// Gets a PendingIntent containing the entire back stack
+PendingIntent resultPendingIntent =
+        stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
+...
+NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
+builder.setContentIntent(resultPendingIntent);
+NotificationManager mNotificationManager =
+    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+mNotificationManager.notify(id, builder.build());
+</pre>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="ExtendedNotification">Menyiapkan PendingIntent aktivitas khusus</h3>
+<p>
+    Bagian berikut menjelaskan cara menyiapkan aktivitas khusus
+    {@link android.app.PendingIntent}.
+</p>
+<p>
+    {@link android.app.Activity} khusus tidak memerlukan back-stack, sehingga Anda tidak perlu
+    mendefinisikan hierarki {@link android.app.Activity}-nya dalam manifes, dan Anda tidak perlu
+    memanggil
+    {@link android.support.v4.app.TaskStackBuilder#addParentStack  addParentStack()} untuk membuat
+    back-stack. Sebagai gantinya, gunakan manifes untuk menyiapkan opsi tugas {@link android.app.Activity},
+    dan buat {@link android.app.PendingIntent} dengan memanggil
+    {@link android.app.PendingIntent#getActivity getActivity()}:
+</p>
+<ol>
+    <li>
+        Dalam manifes, tambahkan atribut berikut pada elemen
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+        untuk {@link android.app.Activity}
+        <dl>
+            <dt>
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">android:name</a>="<i>activityclass</i>"</code>
+            </dt>
+            <dd>
+                Nama kelas mutlak (fully qualified) aktivitas.
+            </dd>
+            <dt>
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">android:taskAffinity</a>=""</code>
+            </dt>
+            <dd>
+                Dikombinasikan dengan flag
+                {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK}
+                yang Anda atur dalam kode, ini memastikan bahwa {@link android.app.Activity} ini tidak
+                masuk ke dalam tugas default aplikasi. Setiap tugas yang ada yang memiliki
+                afinitas default aplikasi tidak terpengaruh.
+            </dd>
+            <dt>
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#exclude">android:excludeFromRecents</a>="true"</code>
+            </dt>
+            <dd>
+                Mengecualikan tugas baru dari <i>Recents</i>, sehingga pengguna tidak bisa tanpa sengaja
+                mengarahkan kembali.
+            </dd>
+        </dl>
+        <p>
+            Cuplikan ini menampilkan elemen:
+        </p>
+<pre>
+&lt;activity
+    android:name=".ResultActivity"
+...
+    android:launchMode="singleTask"
+    android:taskAffinity=""
+    android:excludeFromRecents="true"&gt;
+&lt;/activity&gt;
+...
+</pre>
+    </li>
+    <li>
+        Buat dan keluarkan pemberitahuan:
+        <ol style="list-style-type: lower-alpha;">
+            <li>
+                Buat {@link android.content.Intent} yang memulai
+                {@link android.app.Activity}.
+            </li>
+            <li>
+                Atur {@link android.app.Activity} untuk dimulai dalam tugas kosong yang baru dengan memanggil
+                {@link android.content.Intent#setFlags setFlags()} dengan flag
+                {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK}
+                dan
+                {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK FLAG_ACTIVITY_CLEAR_TASK}.
+            </li>
+            <li>
+                Atur setiap opsi lain yang Anda perlukan untuk {@link android.content.Intent}.
+            </li>
+            <li>
+                Buat {@link android.app.PendingIntent} dari {@link android.content.Intent}
+                dengan memanggil {@link android.app.PendingIntent#getActivity getActivity()}.
+                Anda nanti bisa menggunakan {@link android.app.PendingIntent} ini sebagai argumen untuk
+                {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
+                setContentIntent()}.
+            </li>
+        </ol>
+    <p>
+        Cuplikan kode berikut memperagakan prosesnya:
+    </p>
+<pre>
+// Instantiate a Builder object.
+NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
+// Creates an Intent for the Activity
+Intent notifyIntent =
+        new Intent(this, ResultActivity.class);
+// Sets the Activity to start in a new, empty task
+notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+// Creates the PendingIntent
+PendingIntent notifyPendingIntent =
+        PendingIntent.getActivity(
+        this,
+        0,
+        notifyIntent,
+        PendingIntent.FLAG_UPDATE_CURRENT
+);
+
+// Puts the PendingIntent into the notification builder
+builder.setContentIntent(notifyPendingIntent);
+// Notifications are issued by sending them to the
+// NotificationManager system service.
+NotificationManager mNotificationManager =
+    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+// Builds an anonymous Notification object from the builder, and
+// passes it to the NotificationManager
+mNotificationManager.notify(id, builder.build());
+</pre>
+    </li>
+</ol>
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="Progress">Menampilkan Kemajuan dalam Pemberitahuan</h2>
+<p>
+    Pemberitahuan bisa menyertakan indikator kemajuan beranimasi yang menampilkan status
+operasi yang berjalan kepada pengguna. Jika Anda bisa memperkirakan lamanya operasi berlangsung dan berapa banyak
+    yang sudah selesai pada suatu waktu, gunakan bentuk indikator yang "pasti"
+    (baris kemajuan). Jika Anda tidak bisa memperkirakan lamanya operasi, gunakan
+    bentuk indikator "tidak pasti" (indikator aktivitas).
+</p>
+<p>
+    Indikator kemajuan ditampilkan bersama implementasi platform
+    kelas {@link android.widget.ProgressBar}.
+</p>
+<p>
+    Untuk menggunakan indikator kemajuan pada platform mulai dari Android 4.0, panggil
+    {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}. Untuk
+    versi sebelumnya, Anda harus membuat layout pemberitahuan custom sendiri yang
+menyertakan tampilan {@link android.widget.ProgressBar}.
+</p>
+<p>
+    Bagian berikut ini menjelaskan cara menampilkan kemajuan dalam pemberitahuan dengan menggunakan
+    {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="FixedProgress">Menampilkan indikator kemajuan berdurasi tetap</h3>
+<p>
+    Untuk menampilkan baris kemajuan pasti, tambahkan baris itu ke pemberitahuan dengan memanggil
+    {@link android.support.v4.app.NotificationCompat.Builder#setProgress
+    setProgress(max, progress, false)}, kemudian keluarkan pemberitahuan. Selagi operasi berlangsung,
+    tambah <code>progress</code>, dan perbarui pemberitahuan. Di akhir operasi,
+    <code>progress</code> harus sama dengan <code>max</code>. Satu cara umum memanggil
+    {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}
+    adalah mengatur <code>max</code> ke 100, kemudian tambah <code>progress</code> sebagai
+     nilai "persen selesai"untuk operasi itu.
+</p>
+<p>
+    Anda bisa membiarkan baris kemajuan ditampilkan saat operasi selesai, atau menghilangkannya. Dalam
+    hal apa pun, ingatlah memperbarui teks pemberitahuan untuk menampilkan bahwa operasi telah selesai.
+    Untuk menghapus baris kemajuan, panggil
+    {@link android.support.v4.app.NotificationCompat.Builder#setProgress
+    setProgress(0, 0, false)}. Misalnya:
+</p>
+<pre>
+...
+mNotifyManager =
+        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+mBuilder = new NotificationCompat.Builder(this);
+mBuilder.setContentTitle("Picture Download")
+    .setContentText("Download in progress")
+    .setSmallIcon(R.drawable.ic_notification);
+// Start a lengthy operation in a background thread
+new Thread(
+    new Runnable() {
+        &#64;Override
+        public void run() {
+            int incr;
+            // Do the "lengthy" operation 20 times
+            for (incr = 0; incr &lt;= 100; incr+=5) {
+                    // Sets the progress indicator to a max value, the
+                    // current completion percentage, and "determinate"
+                    // state
+                    mBuilder.setProgress(100, incr, false);
+                    // Displays the progress bar for the first time.
+                    mNotifyManager.notify(0, mBuilder.build());
+                        // Sleeps the thread, simulating an operation
+                        // that takes time
+                        try {
+                            // Sleep for 5 seconds
+                            Thread.sleep(5*1000);
+                        } catch (InterruptedException e) {
+                            Log.d(TAG, "sleep failure");
+                        }
+            }
+            // When the loop is finished, updates the notification
+            mBuilder.setContentText("Download complete")
+            // Removes the progress bar
+                    .setProgress(0,0,false);
+            mNotifyManager.notify(ID, mBuilder.build());
+        }
+    }
+// Starts the thread by calling the run() method in its Runnable
+).start();
+</pre>
+
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="ActivityIndicator">Menampilkan indikator aktivitas berlanjut</h3>
+<p>
+    Untuk menampilkan indikator aktivitas tidak pasti, tambahkan aktivitas ke pemberitahuan dengan
+    {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, true)}
+    (dua argumen pertama akan diabaikan), dan keluarkan pemberitahuan. Hasilnya adalah indikator
+    yang memiliki gaya yang sama dengan baris kemajuan, hanya saja animasinya terus berjalan.
+</p>
+<p>
+    Keluarkan pemberitahuan di awal operasi. Animasi akan berjalan hingga Anda
+    memodifikasi pemberitahuan. Bila operasi selesai, panggil
+    {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, false)}
+    kemudian perbarui pemberitahuan untuk menghapus indikator aktivitas.
+    Selalu lakukan ini; jika makan animasi akan terus berjalan sekalipun operasi telah selesai. Juga
+    ingatlah mengubah teks pemberitahuan untuk menunjukkan bahwa operasi telah selesai.
+</p>
+<p>
+    Untuk melihat cara kerja indikator aktivitas, lihat cuplikan terdahulu. Cari lokasi baris-baris berikut:
+</p>
+<pre>
+// Sets the progress indicator to a max value, the current completion
+// percentage, and "determinate" state
+mBuilder.setProgress(100, incr, false);
+// Issues the notification
+mNotifyManager.notify(0, mBuilder.build());
+</pre>
+<p>
+    Ganti baris yang telah Anda temukan dengan baris berikut:
+</p>
+<pre>
+ // Sets an activity indicator for an operation of indeterminate length
+mBuilder.setProgress(0, 0, true);
+// Issues the notification
+mNotifyManager.notify(0, mBuilder.build());
+</pre>
+
+<h2 id="metadata">Metadata Pemberitahuan</h2>
+
+<p>Pemberitahuan dapat disortir sesuai metadata yang Anda tetapkan dengan
+metode {@link android.support.v4.app.NotificationCompat.Builder} berikut:</p>
+
+<ul>
+    <li>{@link android.support.v4.app.NotificationCompat.Builder#setCategory(java.lang.String) setCategory()}
+    memberi tahu sistem cara menangani pemberitahuan aplikasi Anda bila perangkat berada dalam mode Priority
+    (misalnya, jika pemberitahuan menyatakan suatu panggilan masuk, pesan instan, atau alarm).</li>
+    <li>{@link android.support.v4.app.NotificationCompat.Builder#setPriority(int) setPriority()} menyebabkan
+    pemberitahuan dengan bidang prioritas diatur ke {@code PRIORITY_MAX} atau {@code PRIORITY_HIGH}
+    muncul dalam jendela kecil mengambang jika pemberitahuan juga memiliki suara atau getaran.</li>
+    <li>{@link android.support.v4.app.NotificationCompat.Builder#addPerson(java.lang.String) addPerson()}
+    memungkinkan Anda menambahkan daftar orang ke pemberitahuan. Aplikasi Anda bisa menggunakannya untuk memberi isyarat pada
+    sistem bahwa sistem harus mengelompokkan bersama pemberitahuan dari orang-orang yang ditetapkan, atau memberi peringkat lebih penting pada pemberitahuan
+    untuk orang-orang ini.</li>
+</ul>
+
+<div class="figure" style="width:230px">
+  <img src="{@docRoot}images/ui/notifications/heads-up.png" alt="" width="" height="" id="figure3" />
+  <p class="img-caption">
+    <strong>Gambar 3.</strong> Aktivitas layar penuh yang menampilkan pemberitahuan pendahuluan
+  </p>
+</div>
+
+<h2 id="Heads-up">Pemberitahuan Pendahuluan</h2>
+
+<p>Dengan Android 5.0 (API level 21), pemberitahuan bisa muncul dalam jendela kecil mengambang
+(yang disebut juga dengan <em>pemberitahuan pendahuluan</em>) saat perangkat aktif
+(yakni, perangkat dibuka kuncinya dan layarnya menyala). Pemberitahuan ini
+muncul seperti bentuk ringkas pemberitahuan Anda, hanya saja
+pemberitahuan pendahuluan juga menampilkan tombol tindakan. Pengguna bisa menindaklanjuti atau mengabaikan,
+pemberitahuan pendahuluan tanpa meninggalkan aplikasi saat ini.</p>
+
+<p>Contoh-contoh kondisi yang dapat memicu pemberitahuan pendahuluan antara lain:</p>
+
+<ul>
+  <li>Aktivitas pengguna berada dalam mode layar penuh (aplikasi menggunakan
+{@link android.app.Notification#fullScreenIntent}), atau</li>
+  <li>Pemberitahuan memiliki prioritas tinggi dan menggunakan nada dering atau
+    getaran</li>
+</ul>
+
+<h2 id="lockscreenNotification">Pemberitahuan Layar Kunci</h2>
+
+<p>Dengan rilis Android 5.0 (API level 21), pemberitahuan kini dapat muncul pada
+layar kunci. Aplikasi Anda bisa menggunakan fungsionalitas ini untuk menyediakan kontrol pemutaran media dan
+tindakan umum lainnya. Pengguna bisa memilih lewat Settings apakah akan menampilkan pemberitahuan pada layar kunci, dan
+Anda bisa mendesain apakah pemberitahuan aplikasi akan terlihat pada layar kunci.</p>
+
+<h3 id="visibility">Mengatur Visibilitas</h3>
+
+<p>Aplikasi Anda bisa mengatur level detail terlihat pada pemberitahuan yang ditampilkan di
+layar kunci aman. Anda memanggil {@link android.support.v4.app.NotificationCompat.Builder#setVisibility(int) setVisibility()}
+dan menetapkan salah satu nilai berikut:</p>
+
+<ul>
+    <li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC} menampilkan isi lengkap
+    pemberitahuan.</li>
+    <li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_SECRET} tidak menampilkan bagian apa pun dari
+    pemberitahuan ini pada layar kunci.</li>
+    <li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_PRIVATE} menampilkan informasi dasar,
+    misalnya ikon dan judul isi pemberitahuan, namun menyembunyikan isi lengkap pemberitahuan.</li>
+</ul>
+
+<p>Bila {@link android.support.v4.app.NotificationCompat#VISIBILITY_PRIVATE} telah diatur, Anda juga bisa
+menyediakan versi alternatif isi pemberitahuan yang menyembunyikan detail tertentu. Misalnya,
+aplikasi SMS dapat menampilkan pemberitahuan yang menampilkan <em>Anda memiliki 3 pesan teks baru</em>, namun menyembunyikan
+isi dan pengirim pesan. Untuk menyediakan pemberitahuan alternatif ini, buat dahulu pemberitahuan
+pengganti menggunakan {@link android.support.v4.app.NotificationCompat.Builder}. Bila Anda membuat
+objek pemberitahuan privat, lampirkan pemberitahuan pengganti melalui metode
+{@link android.support.v4.app.NotificationCompat.Builder#setPublicVersion(android.app.Notification) setPublicVersion()}
+.</p>
+
+<h3 id="controllingMedia">Mengontrol Pemutaran Media pada Layar Kunci</h3>
+
+<p>Dalam Android 5.0 (API level 21) layar kunci tidak lagi menampilkan kontrol media
+berdasarkan {@link android.media.RemoteControlClient}, yang sekarang telah dihilangkan. Sebagai gantinya, gunakan
+template {@link android.app.Notification.MediaStyle} dengan metode
+{@link android.app.Notification.Builder#addAction(android.app.Notification.Action) addAction()}
+, yang mengubah tindakan menjadi ikon yang bisa diklik.</p>
+
+<p class="note"><strong>Catatan:</strong> Template dan metode {@link android.app.Notification.Builder#addAction(android.app.Notification.Action) addAction()}
+tidak disertakan dalam pustaka dukungan, sehingga fitur-fitur ini berjalan pada Android 5.0 dan yang lebih tinggi
+saja.</p>
+
+<p>Untuk menampilkan kontrol pemutaran media di layar kunci dalam Android 5.0, atur visibilitas
+ke {@link android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC}, seperti dijelaskan di atas. Kemudian tambahkan
+tindakan dan atur template {@link android.app.Notification.MediaStyle}, seperti dijelaskan dalam contoh kode
+berikut:</p>
+
+<pre>
+Notification notification = new Notification.Builder(context)
+    // Show controls on lock screen even when user hides sensitive content.
+    .setVisibility(Notification.VISIBILITY_PUBLIC)
+    .setSmallIcon(R.drawable.ic_stat_player)
+    // Add media control buttons that invoke intents in your media service
+    .addAction(R.drawable.ic_prev, "Previous", prevPendingIntent) // #0
+    .addAction(R.drawable.ic_pause, "Pause", pausePendingIntent)  // #1
+    .addAction(R.drawable.ic_next, "Next", nextPendingIntent)     // #2
+    // Apply the media style template
+    .setStyle(new Notification.MediaStyle()
+    .setShowActionsInCompactView(1 /* #1: pause button */)
+    .setMediaSession(mMediaSession.getSessionToken())
+    .setContentTitle("Wonderful music")
+    .setContentText("My Awesome Band")
+    .setLargeIcon(albumArtBitmap)
+    .build();
+</pre>
+
+<p class="note"><strong>Catatan:</strong> Dihilangkannya {@link android.media.RemoteControlClient}
+memiliki implikasi lebih jauh untuk mengontrol media. Lihat
+<a href="{@docRoot}about/versions/android-5.0.html#MediaPlaybackControl">Kontrol Pemutaran Media</a>
+untuk informasi selengkapnya tentang API baru untuk mengelola sesi media dan mengontrol pemutaran.</p>
+
+
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="CustomNotification">Layout Pemberitahuan Custom</h2>
+<p>
+    Kerangka kerja pemberitahuan memungkinkan Anda mendefinisikan layout pemberitahuan custom, yang
+    mendefinisikan penampilan pemberitahuan dalam objek {@link android.widget.RemoteViews}.
+    Pemberitahuan dengan layout custom serupa pemberitahuan normal, namun dibuat berdasarkan
+    {@link android.widget.RemoteViews} yang didefinisikan dalam file layout XML.
+</p>
+<p>
+    Tinggi yang tersedia untuk layout pemberitahuan custom bergantung pada tampilan pemberitahuan. Layout
+    tampilan normal dibatasi hingga 64 dp, dan layout tampilan yang diperluas dibatasi hingga 256 dp.
+</p>
+<p>
+    Untuk mendefinisikan layout pemberitahuan custom, mulailah dengan membuat instance
+    objek {@link android.widget.RemoteViews} yang memekarkan file layout XML. Kemudian,
+    sebagai ganti memanggil metode seperti
+    {@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()},
+    panggil {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. Untuk mengatur
+    detail isi pemberitahuan custom, gunakan metode dalam
+    {@link android.widget.RemoteViews} untuk mengatur nilai anak tampilan:
+</p>
+<ol>
+    <li>
+        Buat layout XML untuk pemberitahuan di file terpisah. Anda bisa menggunakan nama file
+apa saja yang diinginkan, namun Anda harus menggunakan ekstensi <code>.xml</code>
+    </li>
+    <li>
+        Dalam aplikasi Anda, gunakan metode {@link android.widget.RemoteViews} untuk mendefinisikan
+        ikon dan teks pemberitahuan. Masukkan objek {@link android.widget.RemoteViews} ini ke dalam
+        {@link android.support.v4.app.NotificationCompat.Builder} Anda dengan memanggil
+        {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. Hindari
+        mengatur {@link android.graphics.drawable.Drawable} latar belakang pada
+        objek {@link android.widget.RemoteViews} Anda, karena warna teks bisa menjadi tidak terbaca.
+    </li>
+</ol>
+<p>
+    Kelas {@link android.widget.RemoteViews} juga menyertakan metode yang bisa Anda gunakan untuk
+    menambahkan {@link android.widget.Chronometer} atau {@link android.widget.ProgressBar}
+dengan mudah ke layout pemberitahuan Anda. Untuk informasi selengkapnya tentang cara membuat layout custom
+    pemberitahuan Anda, lihat dokumentasi acuan {@link android.widget.RemoteViews}.
+</p>
+<p class="caution">
+    <strong>Perhatian:</strong> Bila Anda menggunakan layout pemberitahuan custom, berhati-hatilah
+    untuk memastikan bahwa layout custom itu bekerja pada berbagai orientasi dan resolusi perangkat. Walaupun
+    berlaku bagi semua layout View, nasihat ini khususnya penting untuk pemberitahuan karena
+    ruang di laci pemberitahuan sangat terbatas. Jangan buat layout custom terlalu
+    kompleks, dan pastikan mengujinya di berbagai konfigurasi.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h4>Menggunakan sumber daya gaya untuk teks pemberitahuan custom</h4>
+<p>
+    Selalu gunakan sumber daya gaya untuk teks pemberitahuan custom. Warna latar belakang
+    pemberitahuan bisa bervariasi di berbagai perangkat dan versi, dan menggunakan sumber daya gaya
+    membantu Anda menangani hal ini. Mulai Android 2.3, sistem mendefinisikan sebuah gaya untuk
+    teks layout pemberitahuan standar. Jika Anda menggunakan gaya yang sama dalam aplikasi yang menargetkan Android
+    2.3 atau yang lebih tinggi, Anda akan memastikan bahwa teks terlihat pada latar belakang tampilan.
+</p>
diff --git a/docs/html-intl/intl/id/guide/topics/ui/overview.jd b/docs/html-intl/intl/id/guide/topics/ui/overview.jd
new file mode 100644
index 0000000..ca8b420
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/ui/overview.jd
@@ -0,0 +1,71 @@
+page.title=Ikhtisar UI
+@jd:body
+
+
+<p>Semua elemen antarmuka pengguna dalam aplikasi Android dibangun menggunakan objek {@link android.view.View} dan
+{@link android.view.ViewGroup}. {@link android.view.View} adalah objek yang menarik
+sesuatu di layar dan dapat berinteraksi dengan pengguna. {@link android.view.ViewGroup} merupakan sebuah
+objek yang menyimpan objek {@link android.view.View} lainnya (dan {@link android.view.ViewGroup}) untuk
+mendefinisikan layout antarmuka.</p>
+
+<p>Android menyediakan sekumpulan subkelas {@link android.view.View} dan {@link
+android.view.ViewGroup} yang menawarkan kontrol input umum (seperti tombol dan bidang
+teks) serta berbagai model layout (seperti layout linear atau relatif).</p>
+
+
+<h2 id="Layout">Layout Antarmuka Pengguna</h2>
+
+<p>Antarmuka pengguna untuk setiap komponen aplikasi Anda didefinisikan menggunakan hierarki objek {link
+android.view.View} dan {@link android.view.ViewGroup}, seperti yang ditampilkan dalam gambar 1. Setiap kelompok tampilan
+merupakan kontainer tak terlihat yang mengelola tampilan anak, sementara tampilan anak ini dapat menjadi kontrol
+input atau widget lain yang
+menarik sebagian dari UI. Pohon hierarki ini bisa sederhana atau bisa juga kompleks bergantung kebutuhan
+(namun yang sederhana paling baik untuk kinerja).</p>
+
+<img src="{@docRoot}images/viewgroup.png" alt="" />
+<p class="img-caption"><strong>Gambar 1.</strong> Ilustrasi dari hierarki tampilan, yang mendefinisikan layout
+UI.</p>
+
+<p>Untuk mendeklarasikan layout, Anda dapat menyediakan objek {@link android.view.View} dalam kode dan mulai
+membangun pohon, namun cara termudah dan terefektif untuk mendefinisikan layout adalah dengan file XML.
+XML menawarkan struktur layout yang dapat dibaca manusia, serupa dengan HTML.</p>
+
+<p>Nama elemen XML untuk tampilan sesuai dengan kelas Android yang diwakilinya. Dengan demikian elemen
+<code>&lt;TextView&gt;</code> membuat widget {@link android.widget.TextView} dalam UI Anda,
+dan elemen <code>&lt;LinearLayout&gt;</code> membuat kelompok tampilan {@link android.widget.LinearLayout}
+. </p>
+
+<p>Misalnya, layout vertikal sederhana dengan tampilan teks dan tombol akan tampak seperti ini:</p>
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="fill_parent"
+              android:layout_height="fill_parent"
+              android:orientation="vertical" >
+    &lt;TextView android:id="@+id/text"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:text="I am a TextView" />
+    &lt;Button android:id="@+id/button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="I am a Button" />
+&lt;/LinearLayout>
+</pre>
+
+<p>Saat Anda memuat sumber daya layout di aplikasi, Android akan menginisialisasi setiap simpul layout menjadi
+objek runtime yang bisa Anda gunakan untuk mendefinisikan perilaku tambahan, query status objek, atau memodifikasi
+layout.</p>
+
+<p>Untuk mendapatkan panduan lengkap mengenai pembuatan layout UI, lihat <a href="declaring-layout.html">Layout
+XML</a>.
+
+
+<h2 id="UIComponents">Komponen Antarmuka Pengguna</h2>
+
+<p>Anda tidak harus membuat semua UI menggunakan objek {@link android.view.View} dan {link
+android.view.ViewGroup}. Android menyediakan beberapa komponen aplikasi yang menawarkan
+layout UI standar yang tinggal Anda definisikan kontennya. Komponen UI ini masing-masing
+memiliki set API unik yang dijelaskan dalam masing-masing dokumennya, seperti <a href="{@docRoot}guide/topics/ui/actionbar.html">Action-Bar</a>, <a href="{@docRoot}guide/topics/ui/dialogs.html">Dialog</a>, dan <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Pemberitahuan Status</a>.</p>
+
+
diff --git a/docs/html-intl/intl/id/guide/topics/ui/settings.jd b/docs/html-intl/intl/id/guide/topics/ui/settings.jd
new file mode 100644
index 0000000..89be52f
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/ui/settings.jd
@@ -0,0 +1,1202 @@
+page.title=Pengaturan
+page.tags=preference,preferenceactivity,preferencefragment
+
+@jd:body
+
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>Dalam dokumen ini</h2>
+<ol>
+  <li><a href="#Overview">Ikhtisar</a>
+    <ol>
+      <li><a href="#SettingTypes">Preferensi</a></li>
+    </ol>
+  </li>
+  <li><a href="#DefiningPrefs">Mendefinisikan Preferensi dalam XML</a>
+    <ol>
+      <li><a href="#Groups">Membuat grup pengaturan</a></li>
+      <li><a href="#Intents">Menggunakan intent</a></li>
+    </ol>
+  </li>
+  <li><a href="#Activity">Membuat Aktivitas Preferensi</a></li>
+  <li><a href="#Fragment">Menggunakan Fragmen Preferensi</a></li>
+  <li><a href="#Defaults">Mengatur Nilai Default</a></li>
+  <li><a href="#PreferenceHeaders">Menggunakan Header Preferensi</a>
+    <ol>
+      <li><a href="#CreateHeaders">Membuat file header</a></li>
+      <li><a href="#DisplayHeaders">Menampilkan header</a></li>
+      <li><a href="#BackCompatHeaders">Mendukung versi yang lebih lama dengan header preferensi</a></li>
+    </ol>
+  </li>
+  <li><a href="#ReadingPrefs">Preferensi Membaca</a>
+    <ol>
+      <li><a href="#Listening">Mendengarkan perubahan preferensi</a></li>
+    </ol>
+  </li>
+  <li><a href="#NetworkUsage">Mengelola Penggunaan Jaringan</a></li>
+  <li><a href="#Custom">Membangun Preferensi Custom</a>
+    <ol>
+      <li><a href="#CustomSelected">Menetapkan antarmuka pengguna</a></li>
+      <li><a href="#CustomSave">Menyimpan nilai pengaturan</a></li>
+      <li><a href="#CustomInitialize">Menginisialisasi nilai saat ini</a></li>
+      <li><a href="#CustomDefault">Menyediakan nilai default</a></li>
+      <li><a href="#CustomSaveState">Menyimpan dan memulihkan status Preferensi</a></li>
+    </ol>
+  </li>
+</ol>
+
+<h2>Kelas-kelas utama</h2>
+<ol>
+  <li>{@link android.preference.Preference}</li>
+  <li>{@link android.preference.PreferenceActivity}</li>
+  <li>{@link android.preference.PreferenceFragment}</li>
+</ol>
+
+
+<h2>Lihat juga</h2>
+<ol>
+  <li><a href="{@docRoot}design/patterns/settings.html">Panduan desain pengaturan</a></li>
+</ol>
+</div>
+</div>
+
+
+
+
+<p>Aplikasi sering kali menyertakan pengaturan yang memungkinkan pengguna memodifikasi fitur dan perilaku aplikasi. Misalnya,
+beberapa aplikasi memungkinkan pengguna untuk menetapkan apakah pemberitahuan diaktifkan atau menetapkan seberapa sering
+aplikasi menyinkronkan data dengan cloud.</p>
+
+<p>Jika ingin menyediakan pengaturan untuk aplikasi, Anda harus menggunakan
+API Android {@link android.preference.Preference} untuk membangun antarmuka yang konsisten dengan
+pengalaman pengguna di aplikasi Android yang lain (termasuk pengaturan sistem). Dokumen ini menjelaskan
+cara membangun pengaturan aplikasi Anda menggunakan API {@link android.preference.Preference}.</p>
+
+<div class="note design">
+<p><strong>Desain Pengaturan</strong></p>
+  <p>Untuk informasi tentang cara mendesain pengaturan Anda, bacalah panduan desain <a href="{@docRoot}design/patterns/settings.html">Pengaturan</a>.</p>
+</div>
+
+
+<img src="{@docRoot}images/ui/settings/settings.png" alt="" width="435" />
+<p class="img-caption"><strong>Gambar 1.</strong> Cuplikan layar dari pengaturan
+aplikasi Messaging Android. Memilih item yang didefinisikan oleh {@link android.preference.Preference}
+akan membuka antarmuka untuk mengubah pengaturan.</p>
+
+
+
+
+<h2 id="Overview">Ikhtisar</h2>
+
+<p>Sebagai ganti menggunakan objek {@link android.view.View} untuk membangun antarmuka pengguna, pengaturan
+dibangun menggunakan berbagai subkelas dari kelas {@link android.preference.Preference} yang Anda
+deklarasikan dalam file XML.</p>
+
+<p>Objek {@link android.preference.Preference} adalah blok pembangun untuk pengaturan
+tunggal. Setiap {@link android.preference.Preference} muncul sebagai item dalam daftar dan menyediakan UI
+yang sesuai bagi pengguna untuk memodifikasi pengaturan. Misalnya, {@link
+android.preference.CheckBoxPreference} membuat item daftar yang menampilkan kotak cek, dan {@link
+android.preference.ListPreference} membuat item yang membuka dialog berisi daftar pilihan.</p>
+
+<p>Setiap {@link android.preference.Preference} yang Anda tambahkan memiliki pasangan nilai-kunci yang sesuai yang
+digunakan sistem untuk menyimpan pengaturan dalam file {@link android.content.SharedPreferences}
+default untuk pengaturan aplikasi Anda. Bila pengguna mengubah pengaturan, sistem akan memperbarui nilai
+yang bersangkutan dalam file {@link android.content.SharedPreferences} untuk Anda. Satu-satunya saat di mana Anda harus
+berinteraksi langsung dengan file {@link android.content.SharedPreferences} yang terkait adalah bila Anda
+perlu membaca nilai untuk menentukan perilaku aplikasi berdasarkan pengaturan pengguna.</p>
+
+<p>Nilai yang tersimpan di {@link android.content.SharedPreferences} untuk setiap pengaturan bisa berupa
+tipe data berikut:</p>
+
+<ul>
+  <li>Boolean</li>
+  <li>Float</li>
+  <li>Int</li>
+  <li>Long</li>
+  <li>String</li>
+  <li>String {@link java.util.Set}</li>
+</ul>
+
+<p>Oleh karena UI pengaturan aplikasi Anda dibangun menggunakan objek {@link android.preference.Preference}
+sebagai ganti
+objek {@link android.view.View}, Anda perlu menggunakan {@link android.app.Activity} khusus atau
+subkelas {@link android.app.Fragment} untuk menampilkan pengaturan daftar:</p>
+
+<ul>
+  <li>Jika aplikasi Anda mendukung versi Android yang lebih lama dari 3.0 (API level 10 dan yang lebih rendah), Anda harus
+membangun aktivitas sebagai ekstensi dari kelas {@link android.preference.PreferenceActivity}.</li>
+  <li>Pada Android 3.0 dan yang lebih baru, sebaiknya Anda menggunakan {@link android.app.Activity} biasa
+yang menjadi host {@link android.preference.PreferenceFragment} yang menampilkan pengaturan aplikasi Anda.
+Akan tetapi, Anda juga bisa menggunakan {@link android.preference.PreferenceActivity} untuk membuat layout dua panel
+bagi layar besar bila Anda memiliki beberapa grup pengaturan.</li>
+</ul>
+
+<p>Cara mengatur {@link android.preference.PreferenceActivity} Anda dan instance {@link
+android.preference.PreferenceFragment} dibahas di bagian tentang <a href="#Activity">Membuat Aktivitas Preferensi</a> dan <a href="#Fragment">Menggunakan
+Fragmen Preferensi</a>.</p>
+
+
+<h3 id="SettingTypes">Preferensi</h3>
+
+<p>Setiap pengaturan untuk aplikasi Anda diwakili oleh subkelas khusus dari kelas {@link
+android.preference.Preference}. Setiap subkelas menyertakan seperangkat properti utama yang memungkinkan Anda
+untuk menetapkan berbagai hal seperti judul pengaturan dan nilai default. Setiap subkelas juga menyediakan
+antarmuka pengguna dan properti khusus miliknya sendiri. Misalnya, gambar 1 menampilkan cuplikan layar dari
+ pengaturan aplikasi Messaging. Setiap item daftar dalam layar pengaturan didukung oleh objek {@link
+android.preference.Preference} berbeda.</p>
+
+<p>Beberapa preferensi yang paling umum adalah:</p>
+
+<dl>
+  <dt>{@link android.preference.CheckBoxPreference}</dt>
+  <dd>Menampilkan item dengan kotak cek untuk pengaturan yang diaktifkan atau dinonaktifkan. Nilai
+tersimpan adalah boolean (<code>true</code> jika diberi tanda cek).</dd>
+
+  <dt>{@link android.preference.ListPreference}</dt>
+  <dd>Membuka dialog berisi daftar tombol radio. Nilai
+tersimpan bisa berupa tipe nilai apa pun yang didukung (tercantum di atas).</dd>
+
+  <dt>{@link android.preference.EditTextPreference}</dt>
+  <dd>Membuka dialog berisi widget {@link android.widget.EditText}. Nilai tersimpan adalah {@link
+java.lang.String}.</dd>
+</dl>
+
+<p>Lihat kelas {@link android.preference.Preference} untuk mengetahui daftar subkelas lain dan
+propertinya.</p>
+
+<p>Tentu saja, kelas bawaan tidak mengakomodasi setiap kebutuhan dan aplikasi Anda mungkin memerlukan
+sesuatu yang lebih khusus. Misalnya, platform saat ini tidak menyediakan kelas {@link
+android.preference.Preference} untuk mengambil nomor atau tanggal. Anda mungkin perlu mendefinisikan
+subkelas {@link android.preference.Preference} sendiri. Untuk bantuan melakukannya, lihat bagian tentang <a href="#Custom">Membangun Preferensi Custom</a>.</p>
+
+
+
+<h2 id="DefiningPrefs">Mendefinisikan Preferensi dalam XML</h2>
+
+<p>Meskipun bisa membuat instance objek {@link android.preference.Preference} baru saat runtime, Anda
+harus mendefinisikan daftar pengaturan dalam XML dengan hierarki objek
+{@link android.preference.Preference}. Menggunakan file XML untuk mendefinisikan sekumpulan pengaturan lebih disukai karena file
+menyediakan struktur yang mudah dibaca dan diperbarui. Selain itu, pengaturan aplikasi Anda
+umumnya telah ditetapkan sebelumnya, meskipun Anda masih bisa memodifikasi kumpulan tersebut saat runtime.</p>
+
+<p>Setiap subkelas {@link android.preference.Preference} bisa dideklarasikan dengan elemen XML yang
+cocok dengan nama kelas, seperti {@code &lt;CheckBoxPreference&gt;}.</p>
+
+<p>Anda harus menyimpan file XML dalam direktori {@code res/xml/}. Meskipun bisa memberi nama file
+sesuka Anda, biasanya file diberi nama {@code preferences.xml}. Biasanya Anda hanya memerlukan satu file,
+karena cabang di hierarki (yang membuka daftar pengaturanny sendiri) dideklarasikan menggunakan instance
+tersarang {@link android.preference.PreferenceScreen}.</p>
+
+<p class="note"><strong>Catatan:</strong> Jika ingin membuat layout multipanel untuk
+pengaturan, Anda memerlukan file XML terpisah untuk setiap fragmen.</p>
+
+<p>Simpul akar untuk file XML harus merupakan elemen {@link android.preference.PreferenceScreen
+&lt;PreferenceScreen&gt;}. Dalam elemen inilah tempat Anda menambahkan setiap {@link
+android.preference.Preference}. Setiap anak yang Anda tambahkan dalam elemen
+{@link android.preference.PreferenceScreen &lt;PreferenceScreen&gt;} akan tampak sebagai item
+tunggal dalam daftar pengaturan.</p>
+
+<p>Misalnya:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+    &lt;CheckBoxPreference
+        android:key="pref_sync"
+        android:title="@string/pref_sync"
+        android:summary="@string/pref_sync_summ"
+        android:defaultValue="true" />
+    &lt;ListPreference
+        android:dependency="pref_sync"
+        android:key="pref_syncConnectionType"
+        android:title="@string/pref_syncConnectionType"
+        android:dialogTitle="@string/pref_syncConnectionType"
+        android:entries="@array/pref_syncConnectionTypes_entries"
+        android:entryValues="@array/pref_syncConnectionTypes_values"
+        android:defaultValue="@string/pref_syncConnectionTypes_default" />
+&lt;/PreferenceScreen>
+</pre>
+
+<p>Dalam contoh ini, terdapat {@link android.preference.CheckBoxPreference} dan {@link
+android.preference.ListPreference}. Kedua item tersebut menyertakan tiga atribut berikut:</p>
+
+<dl>
+  <dt>{@code android:key}</dt>
+  <dd>Atribut ini diperlukan untuk preferensi yang mempertahankan nilai data. Ini menetapkan kunci
+unik (string) yang digunakan sistem saat menyimpan nilai pengaturan ini dalam {@link
+android.content.SharedPreferences}.
+  <p>Instance satu-satunya di mana atribut ini <em>tidak diperlukan</em> adalah bila preferensi berupa
+{@link android.preference.PreferenceCategory} atau {@link android.preference.PreferenceScreen}, atau
+preferensi menetapkan {@link android.content.Intent} untuk dipanggil (dengan elemen <a href="#Intents">{@code &lt;intent&gt;}</a>) atau {@link android.app.Fragment} untuk ditampilkan (dengan atribut <a href="{@docRoot}reference/android/preference/Preference.html#attr_android:fragment">{@code
+android:fragment}</a>).</p>
+  </dd>
+  <dt>{@code android:title}</dt>
+  <dd>Ini menyediakan nama pengaturan yang bisa dilihat oleh pengguna.</dd>
+  <dt>{@code android:defaultValue}</dt>
+  <dd>Ini menetapkan nilai awal yang harus diatur sistem dalam file {@link
+android.content.SharedPreferences}. Anda harus memberikan nilai default untuk semua
+pengaturan.</dd>
+</dl>
+
+<p>Untuk informasi tentang semua atribut lain yang didukung, lihat dokumentasi {@link
+android.preference.Preference} (dan subkelas masing-masing).</p>
+
+
+<div class="figure" style="width:300px">
+  <img src="{@docRoot}images/ui/settings/settings-titles.png" alt="" />
+  <p class="img-caption"><strong>Gambar 2.</strong> Mengatur kategori
+    dengan judul. <br/><b>1.</b> Kategori ditetapkan oleh elemen {@link
+android.preference.PreferenceCategory &lt;PreferenceCategory&gt;}. <br/><b>2.</b> Judul
+ditetapkan dengan atribut {@code android:title}.</p>
+</div>
+
+
+<p>Bila daftar pengaturan Anda melebihi sekitar 10 item, Anda mungkin perlu menambahkan judul untuk
+mendefinisikan grup pengaturan atau menampilkan grup tersebut di
+layar terpisah. Opsi ini dijelaskan di bagian berikut.</p>
+
+
+<h3 id="Groups">Membuat grup pengaturan</h3>
+
+<p>Jika Anda menampilkan daftar 10 pengaturan atau lebih, pengguna
+mungkin akan kesulitan dalam memindai, memahami dan memprosesnya. Anda bisa mengatasinya dengan
+membagi sebagian atau semua pengaturan ke dalam beberapa grup, yang secara efektif akan mengubah satu daftar panjang menjadi beberapa daftar
+yang lebih pendek. Suatu grup pengaturan terkait bisa ditampilkan dalam salah satu dari dua cara:</p>
+
+<ul>
+  <li><a href="#Titles">Menggunakan judul</a></li>
+  <li><a href="#Subscreens">Menggunakan sublayar</a></li>
+</ul>
+
+<p>Anda bisa menggunakan salah satu atau keduanya untuk mengelola pengaturan aplikasi Anda. Saat
+memutuskan mana yang akan digunakan dan cara membagi pengaturan, Anda harus mengikuti pedoman dalam
+Panduan <a href="{@docRoot}design/patterns/settings.html">Pengaturan</a> Desain Android.</p>
+
+
+<h4 id="Titles">Menggunakan judul</h4>
+
+<p>Jika ingin menyediakan divider dengan heading di antara grup pengaturan (seperti yang ditampilkan dalam gambar 2),
+tempatkan setiap grup objek {@link android.preference.Preference} di dalam {@link
+android.preference.PreferenceCategory}.</p>
+
+<p>Misalnya:</p>
+
+<pre>
+&lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+    &lt;PreferenceCategory
+        android:title="&#64;string/pref_sms_storage_title"
+        android:key="pref_key_storage_settings">
+        &lt;CheckBoxPreference
+            android:key="pref_key_auto_delete"
+            android:summary="&#64;string/pref_summary_auto_delete"
+            android:title="&#64;string/pref_title_auto_delete"
+            android:defaultValue="false"... />
+        &lt;Preference
+            android:key="pref_key_sms_delete_limit"
+            android:dependency="pref_key_auto_delete"
+            android:summary="&#64;string/pref_summary_delete_limit"
+            android:title="&#64;string/pref_title_sms_delete"... />
+        &lt;Preference
+            android:key="pref_key_mms_delete_limit"
+            android:dependency="pref_key_auto_delete"
+            android:summary="&#64;string/pref_summary_delete_limit"
+            android:title="&#64;string/pref_title_mms_delete" ... />
+    &lt;/PreferenceCategory>
+    ...
+&lt;/PreferenceScreen>
+</pre>
+
+
+<h4 id="Subscreens">Menggunakan sublayar</h4>
+
+<p>Jika ingin menempatkan grup pengaturan ke dalam sublayar (seperti yang ditampilkan dalam gambar 3), tempatkan grup
+objek {@link android.preference.Preference} di dalam {@link
+android.preference.PreferenceScreen}.</p>
+
+<img src="{@docRoot}images/ui/settings/settings-subscreen.png" alt="" />
+<p class="img-caption"><strong>Gambar 3.</strong> Mengatur sublayar. Elemen {@code
+&lt;PreferenceScreen&gt;}
+membuat item yang, bila dipilih, akan membuka daftar terpisah untuk menampilkan pengaturan tersarang.</p>
+
+<p>Misalnya:</p>
+
+<pre>
+&lt;PreferenceScreen  xmlns:android="http://schemas.android.com/apk/res/android">
+    &lt;!-- opens a subscreen of settings -->
+    &lt;PreferenceScreen
+        android:key="button_voicemail_category_key"
+        android:title="&#64;string/voicemail"
+        android:persistent="false">
+        &lt;ListPreference
+            android:key="button_voicemail_provider_key"
+            android:title="&#64;string/voicemail_provider" ... />
+        &lt;!-- opens another nested subscreen -->
+        &lt;PreferenceScreen
+            android:key="button_voicemail_setting_key"
+            android:title="&#64;string/voicemail_settings"
+            android:persistent="false">
+            ...
+        &lt;/PreferenceScreen>
+        &lt;RingtonePreference
+            android:key="button_voicemail_ringtone_key"
+            android:title="&#64;string/voicemail_ringtone_title"
+            android:ringtoneType="notification" ... />
+        ...
+    &lt;/PreferenceScreen>
+    ...
+&lt;/PreferenceScreen>
+</pre>
+
+
+<h3 id="Intents">Menggunakan intent</h3>
+
+<p>Dalam beberapa kasus, Anda mungkin ingin item preferensi untuk membuka beberapa aktivitas sebagai ganti
+layar pengaturan, seperti browser web untuk melihat halaman web. Untuk memanggil {@link
+android.content.Intent} saat pengguna memilih item preferensi, tambahkan elemen {@code &lt;intent&gt;}
+sebagai anak dari elemen {@code &lt;Preference&gt;} yang bersangkutan.</p>
+
+<p>Misalnya, berikut ini cara menggunakan item preferensi untuk membuka halaman web:</p>
+
+<pre>
+&lt;Preference android:title="@string/prefs_web_page" >
+    &lt;intent android:action="android.intent.action.VIEW"
+            android:data="http://www.example.com" />
+&lt;/Preference>
+</pre>
+
+<p>Anda bisa membuat intent implisit maupun eksplisit menggunakan atribut berikut:</p>
+
+<dl>
+  <dt>{@code android:action}</dt>
+    <dd>Tindakan yang akan ditetapkan, sesuai metode
+{@link android.content.Intent#setAction setAction()}.</dd>
+  <dt>{@code android:data}</dt>
+    <dd>Data yang akan ditetapkan, sesuai metode {@link android.content.Intent#setData setData()}.</dd>
+  <dt>{@code android:mimeType}</dt>
+    <dd>Tipe MIME yang akan ditetapkan, sesuai metode
+{@link android.content.Intent#setType setType()}.</dd>
+  <dt>{@code android:targetClass}</dt>
+    <dd>Bagian kelas dari nama komponen, sesuai metode {@link android.content.Intent#setComponent
+setComponent()}.</dd>
+  <dt>{@code android:targetPackage}</dt>
+    <dd>Bagian paket dari nama komponen, sesuai metode {@link
+android.content.Intent#setComponent setComponent()}.</dd>
+</dl>
+
+
+
+<h2 id="Activity">Membuat Aktivitas Preferensi</h2>
+
+<p>Untuk menampilkan pengaturan Anda dalam suatu aktivitas, perluas kelas {@link
+android.preference.PreferenceActivity}. Ini adalah ekstensi dari kelas {@link
+android.app.Activity} biasa yang menampilkan daftar pengaturan berdasarkan hierarki objek {@link
+android.preference.Preference}. {@link android.preference.PreferenceActivity}
+secara otomatis mempertahankan pengaturan yang dikaitkan dengan setiap {@link
+android.preference.Preference} bila pengguna membuat perubahan.</p>
+
+<p class="note"><strong>Catatan:</strong> Jika Anda mengembangkan aplikasi untuk Android 3.0 dan
+yang lebih tinggi, sebaiknya gunakan {@link android.preference.PreferenceFragment}. Pindah ke bagian
+berikutnya tentang <a href="#Fragment">Menggunakan Fragmen Preferensi</a>.</p>
+
+<p>Hal paling penting untuk diingat adalah jangan memuat layout tampilan selama callback {@link
+android.preference.PreferenceActivity#onCreate onCreate()}. Sebagai gantinya, panggil {@link
+android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} untuk
+menambahkan preferensi yang telah Anda deklarasikan dalam file XML ke aktivitas. Misalnya, berikut ini adalah kode minimum
+polos yang diperlukan untuk {@link android.preference.PreferenceActivity} fungsional:</p>
+
+<pre>
+public class SettingsActivity extends PreferenceActivity {
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.xml.preferences);
+    }
+}
+</pre>
+
+<p>Ini sebenarnya kode yang cukup untuk beberapa aplikasi, karena segera setelah pengguna memodifikasi preferensi,
+sistem akan menyimpan perubahan tersebut ke file {@link android.content.SharedPreferences} default yang
+bisa dibaca oleh komponen aplikasi Anda lainnya bila Anda perlu memeriksa pengaturan pengguna. Akan tetapi,
+banyak aplikasi, yang memerlukan kode lebih sedikit untuk mendengarkan perubahan yang terjadi pada preferensi.
+Untuk informasi tentang mendengarkan perubahan di file {@link android.content.SharedPreferences},
+lihat bagian tentang <a href="#ReadingPrefs">Preferensi Membaca</a>.</p>
+
+
+
+
+<h2 id="Fragment">Menggunakan Fragmen Preferensi</h2>
+
+<p>Jika Anda mengembangkan Android 3.0 (API level 11) dan yang lebih tinggi, Anda harus menggunakan {@link
+android.preference.PreferenceFragment} untuk menampilkan daftar objek {@link android.preference.Preference}
+Anda. Anda bisa menambahkan {@link android.preference.PreferenceFragment} ke aktivitas apa pun,&mdash;Anda tidak
+perlu menggunakan {@link android.preference.PreferenceActivity}.</p>
+
+<p><a href="{@docRoot}guide/components/fragments.html">Fragmen</a> menyediakan arsitektur yang lebih
+fleksibel untuk aplikasi Anda, dibandingkan hanya menggunakan aktivitas, apa pun jenis
+aktivitas yang Anda bangun. Dengan sendirinya, kami menyarankan Anda menggunakan {@link
+android.preference.PreferenceFragment} untuk mengontrol tampilan pengaturan Anda sebagai ganti {@link
+android.preference.PreferenceActivity} bila memungkinkan.</p>
+
+<p>Implementasi {@link android.preference.PreferenceFragment} Anda bisa semudah
+mendefinisikan metode {@link android.preference.PreferenceFragment#onCreate onCreate()} untuk memuat
+file preferensi dengan {@link android.preference.PreferenceFragment#addPreferencesFromResource
+addPreferencesFromResource()}. Misalnya:</p>
+
+<pre>
+public static class SettingsFragment extends PreferenceFragment {
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Load the preferences from an XML resource
+        addPreferencesFromResource(R.xml.preferences);
+    }
+    ...
+}
+</pre>
+
+<p>Anda nanti bisa menambahkan fragmen ini ke {@link android.app.Activity} seperti yang Anda lakukan untuk
+{@link android.app.Fragment} lainnya. Misalnya:</p>
+
+<pre>
+public class SettingsActivity extends Activity {
+    &#64;Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Display the fragment as the main content.
+        getFragmentManager().beginTransaction()
+                .replace(android.R.id.content, new SettingsFragment())
+                .commit();
+    }
+}
+</pre>
+
+<p class="note"><strong>Catatan:</strong> {@link android.preference.PreferenceFragment} tidak memiliki
+objek {@link android.content.Context} sendiri. Jika memerlukan objek {@link android.content.Context}
+, Anda bisa memanggil {@link android.app.Fragment#getActivity()}. Akan tetapi, berhati-hatilah untuk memanggil
+{@link android.app.Fragment#getActivity()} hanya bila fragmen telah dikaitkan dengan aktivitas. Bila
+fragmen belum dikaitkan, atau terlepas saat akhir daur hidupnya, {@link
+android.app.Fragment#getActivity()} akan mengembalikan nol.</p>
+
+
+<h2 id="Defaults">Mengatur Nilai Default</h2>
+
+<p>Preferensi yang Anda buat mungkin mendefinisikan beberapa perilaku penting untuk aplikasi, jadi Anda
+perlu menginisialisasi file {@link android.content.SharedPreferences} yang terkait dengan
+nilai default untuk setiap {@link android.preference.Preference} bila pengguna menggunakan aplikasi
+Anda untuk pertama kali.</p>
+
+<p>Hal pertama yang harus Anda lakukan adalah menetapkan nilai default untuk setiap objek {@link
+android.preference.Preference}
+di file XML Anda menggunakan atribut {@code android:defaultValue}. Nilainya bisa berupa tipe data
+apa saja yang sesuai untuk objek {@link android.preference.Preference} bersangkutan. Misalnya:
+</p>
+
+<pre>
+&lt;!-- default value is a boolean -->
+&lt;CheckBoxPreference
+    android:defaultValue="true"
+    ... />
+
+&lt;!-- default value is a string -->
+&lt;ListPreference
+    android:defaultValue="@string/pref_syncConnectionTypes_default"
+    ... />
+</pre>
+
+<p>Kemudian, dari metode {@link android.app.Activity#onCreate onCreate()} dalam aktivitas utama aplikasi
+Anda&mdash;dan dalam aktivitas lainnya yang digunakan pengguna untuk masuk ke aplikasi Anda untuk pertama kali
+&mdash;panggil {@link android.preference.PreferenceManager#setDefaultValues
+setDefaultValues()}:</p>
+
+<pre>
+PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false);
+</pre>
+
+<p>Memanggil ini selama {@link android.app.Activity#onCreate onCreate()} akan memastikan aplikasi
+Anda diinisialisasi dengan pengaturan default, yang mungkin perlu
+dibaca oleh aplikasi Anda untuk menentukan beberapa perilaku (seperti apakah akan mengunduh data pada
+jaringan seluler).</p>
+
+<p>Metode ini membutuhkan tiga argumen:</p>
+<ul>
+  <li>{@link android.content.Context} aplikasi Anda.</li>
+  <li>ID sumber daya untuk file XML preferensi yang ingin Anda atur nilai defaultnya.</li>
+  <li>Boolean menunjukkan apakah nilai default harus diatur lebih dari satu kali.
+<p>Bila <code>false</code>, sistem akan mengatur nilai default hanya jika metode ini belum pernah
+dipanggil sebelumnya (atau {@link android.preference.PreferenceManager#KEY_HAS_SET_DEFAULT_VALUES}
+dalam file preferensi berbagi nilai default salah).</p></li>
+</ul>
+
+<p>Selama Anda mengatur argumen ketiga ke <code>false</code>, Anda bisa dengan aman memanggil metode ini
+setiap kali aktivitas Anda memulai tanpa mengesampingkan preferensi tersimpan pengguna dengan mengatur ulang preferensi tersebut ke
+default. Akan tetapi, jika mengatur ke <code>true</code>, Anda akan mengesampingkan nilai
+sebelumnya dengan default.</p>
+
+
+
+<h2 id="PreferenceHeaders">Menggunakan Header Preferensi</h2>
+
+<p>Dalam kasus yang jarang terjadi, Anda mungkin perlu mendesain pengaturan agar layar pertama
+hanya menampilkan daftar <a href="#Subscreens">sublayar</a> (seperti dalam aplikasi Setting pada sistem,
+seperti yang ditampilkan dalam gambar 4 dan 5). Bila mengembangkan desain seperti itu untuk Android 3.0 dan yang lebih tinggi, Anda
+harus menggunakan fitur "header" yang baru di Android 3.0, sebagai ganti membangun sublayar dengan elemen
+{@link android.preference.PreferenceScreen} tersarang.</p>
+
+<p>Untuk membangun pengaturan dengan header, Anda perlu:</p>
+<ol>
+  <li>Memisahkan setiap grup pengaturan ke dalam instance {@link
+android.preference.PreferenceFragment} terpisah. Ini berarti, setiap grup pengaturan memerlukan file XML
+terpisah.</li>
+  <li>Membuat file header XML yang mencantumkan daftar setiap grup pengaturan dan mendeklarasikan fragmen mana
+yang berisi daftar pengaturan yang sesuai.</li>
+  <li>Memperluas kelas {@link android.preference.PreferenceActivity} untuk menjadi host pengaturan Anda.</li>
+  <li>Mengimplementasikan callback {@link
+android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} untuk menetapkan file
+header.</li>
+</ol>
+
+<p>Manfaat besar dalam menggunakan desain ini adalah karena {@link android.preference.PreferenceActivity}
+secara otomatis akan menampilkan layout dua panel yang ditampilkan dalam gambar 4 bila dijalankan pada layar besar.</p>
+
+<p>Bahkan jika aplikasi Anda mendukung versi Android yang lebih lama dari 3.0, Anda bisa membangun
+aplikasi untuk menggunakan {@link android.preference.PreferenceFragment} bagi presentasi dua panel pada perangkat
+yang lebih baru sementara tetap mendukung hierarki multilayar biasa pada perangkat
+yang lebih lama (lihat bagian tentang <a href="#BackCompatHeaders">Mendukung versi yang lebih lama dengan
+header preferensi</a>).</p>
+
+<img src="{@docRoot}images/ui/settings/settings-headers-tablet.png" alt="" />
+<p class="img-caption"><strong>Gambar 4.</strong> Layout dua panel dengan header. <br/><b>1.</b> Header
+didefinisikan dengan file header XML. <br/><b>2.</b> Setiap grup pengaturan didefinisikan dengan
+{@link android.preference.PreferenceFragment} yang ditetapkan oleh elemen {@code &lt;header&gt;} dalam
+file header.</p>
+
+<img src="{@docRoot}images/ui/settings/settings-headers-handset.png" alt="" />
+<p class="img-caption"><strong>Gambar 5.</strong> Perangkat handset dengan header pengaturan. Bila sebuah
+item dipilih, {@link android.preference.PreferenceFragment} terkait akan menggantikan
+header.</p>
+
+
+<h3 id="CreateHeaders" style="clear:left">Membuat file header</h3>
+
+<p>Setiap grup pengaturan dalam daftar header Anda akan ditetapkan oleh elemen {@code &lt;header&gt;}
+tunggal dalam elemen {@code &lt;preference-headers&gt;} akar. Misalnya:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
+    &lt;header
+        android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"
+        android:title="@string/prefs_category_one"
+        android:summary="@string/prefs_summ_category_one" />
+    &lt;header
+        android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"
+        android:title="@string/prefs_category_two"
+        android:summary="@string/prefs_summ_category_two" >
+        &lt;!-- key/value pairs can be included as arguments for the fragment. -->
+        &lt;extra android:name="someKey" android:value="someHeaderValue" />
+    &lt;/header>
+&lt;/preference-headers>
+</pre>
+
+<p>Dengan atribut {@code android:fragment}, setiap header mendeklarasikan instance {@link
+android.preference.PreferenceFragment} yang harus terbuka saat pengguna memilih header.</p>
+
+<p>Elemen {@code &lt;extras&gt;} memungkinkan Anda meneruskan pasangan nilai-kunci ke fragmen di {@link
+android.os.Bundle}. Fragmen bisa mengambil argumen dengan memanggil {@link
+android.app.Fragment#getArguments()}. Anda bisa meneruskan argumen ke fragmen dengan berbagai
+alasan, namun satu alasan yang baik adalah untuk menggunakan kembali subkelas yang sama dari {@link
+android.preference.PreferenceFragment} untuk setiap grup dan menggunakan argumen untuk menetapkan file
+XML preferensi mana yang harus dimuat fragmen.</p>
+
+<p>Misalnya, ada fragmen yang bisa digunakan ulang untuk berbagai grup pengaturan, bila setiap
+header mendefinisikan argumen {@code &lt;extra&gt;} dengan kunci {@code "settings"}:</p>
+
+<pre>
+public static class SettingsFragment extends PreferenceFragment {
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        String settings = getArguments().getString("settings");
+        if ("notifications".equals(settings)) {
+            addPreferencesFromResource(R.xml.settings_wifi);
+        } else if ("sync".equals(settings)) {
+            addPreferencesFromResource(R.xml.settings_sync);
+        }
+    }
+}
+</pre>
+
+
+
+<h3 id="DisplayHeaders">Menampilkan header</h3>
+
+<p>Untuk menampilkan header preferensi, Anda harus mengimplementasikan metode callback {@link
+android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} dan memanggil
+{@link android.preference.PreferenceActivity#loadHeadersFromResource
+loadHeadersFromResource()}. Misalnya:</p>
+
+<pre>
+public class SettingsActivity extends PreferenceActivity {
+    &#64;Override
+    public void onBuildHeaders(List&lt;Header> target) {
+        loadHeadersFromResource(R.xml.preference_headers, target);
+    }
+}
+</pre>
+
+<p>Bila pengguna memilih item dari daftar header, sistem akan membuka {@link
+android.preference.PreferenceFragment} terkait.</p>
+
+<p class="note"><strong>Catatan:</strong> Saat menggunakan header preferensi, subkelas {@link
+android.preference.PreferenceActivity} Anda tidak perlu mengimplementasikan metode {@link
+android.preference.PreferenceActivity#onCreate onCreate()}, karena tugas
+yang diperlukan untuk aktivitas hanyalah memuat header.</p>
+
+
+<h3 id="BackCompatHeaders">Mendukung versi yang lebih lama dengan header preferensi</h3>
+
+<p>Jika aplikasi Anda mendukung versi Android yang lebih lama dari 3.0, Anda tetap bisa menggunakan header untuk
+menyediakan layout dua panel saat berjalan pada Android 3.0 dan yang lebih tinggi. Anda hanya perlu membuat
+file XML preferensi tambahan yang menggunakan elemen {@link android.preference.Preference
+&lt;Preference&gt;} dasar yang berperilaku seperti item header (untuk digunakan oleh Android
+versi yang lebih lama).</p>
+
+<p>Akan tetapi, sebagai ganti membuka {@link android.preference.PreferenceScreen} baru, setiap elemen {@link
+android.preference.Preference &lt;Preference&gt;} mengirimkan {@link android.content.Intent} ke
+{@link android.preference.PreferenceActivity} yang menetapkan file XML preferensi mana yang
+akan dimuat.</p>
+
+<p>Misalnya, ini adalah file XML untuk header preferensi yang menggunakan Android 3.0
+dan yang lebih tinggi ({@code res/xml/preference_headers.xml}):</p>
+
+<pre>
+&lt;preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
+    &lt;header
+        android:fragment="com.example.prefs.SettingsFragmentOne"
+        android:title="@string/prefs_category_one"
+        android:summary="@string/prefs_summ_category_one" />
+    &lt;header
+        android:fragment="com.example.prefs.SettingsFragmentTwo"
+        android:title="@string/prefs_category_two"
+        android:summary="@string/prefs_summ_category_two" />
+&lt;/preference-headers>
+</pre>
+
+<p>Dan ini adalah file preferensi yang menyediakan header yang sama untuk versi yang lebih lama dari
+Android 3.0 ({@code res/xml/preference_headers_legacy.xml}):</p>
+
+<pre>
+&lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+    &lt;Preference
+        android:title="@string/prefs_category_one"
+        android:summary="@string/prefs_summ_category_one"  >
+        &lt;intent
+            android:targetPackage="com.example.prefs"
+            android:targetClass="com.example.prefs.SettingsActivity"
+            android:action="com.example.prefs.PREFS_ONE" />
+    &lt;/Preference>
+    &lt;Preference
+        android:title="@string/prefs_category_two"
+        android:summary="@string/prefs_summ_category_two" >
+        &lt;intent
+            android:targetPackage="com.example.prefs"
+            android:targetClass="com.example.prefs.SettingsActivity"
+            android:action="com.example.prefs.PREFS_TWO" />
+    &lt;/Preference>
+&lt;/PreferenceScreen>
+</pre>
+
+<p>Karena dukungan untuk {@code &lt;preference-headers&gt;} telah ditambahkan di Android 3.0, sistem akan memanggil
+{@link android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} di {@link
+android.preference.PreferenceActivity} hanya saat berjalan pada Android 3.0 atau yang lebih tinggi. Untuk memuat
+file header "lama" ({@code preference_headers_legacy.xml}), Anda harus memeriksa versi Android
+dan, jika versi tersebut lebih lama dari Android 3.0 ({@link
+android.os.Build.VERSION_CODES#HONEYCOMB}), panggil {@link
+android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} untuk
+memuat file header lama. Misalnya:</p>
+
+<pre>
+&#64;Override
+public void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    ...
+
+    if (Build.VERSION.SDK_INT &lt; Build.VERSION_CODES.HONEYCOMB) {
+        // Load the legacy preferences headers
+        addPreferencesFromResource(R.xml.preference_headers_legacy);
+    }
+}
+
+// Called only on Honeycomb and later
+&#64;Override
+public void onBuildHeaders(List&lt;Header> target) {
+   loadHeadersFromResource(R.xml.preference_headers, target);
+}
+</pre>
+
+<p>Satu-satunya hal yang perlu dilakukan adalah menangani {@link android.content.Intent} yang diteruskan ke
+aktivitas untuk mengidentifikasi file preferensi yang akan dimuat. Jadi ambillah tindakan intent dan bandingkan dengan
+string tindakan yang diketahui yang telah Anda gunakan dalam tag {@code &lt;intent&gt;} XML preferensi:</p>
+
+<pre>
+final static String ACTION_PREFS_ONE = "com.example.prefs.PREFS_ONE";
+...
+
+&#64;Override
+public void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+
+    String action = getIntent().getAction();
+    if (action != null &amp;&amp; action.equals(ACTION_PREFS_ONE)) {
+        addPreferencesFromResource(R.xml.preferences);
+    }
+    ...
+
+    else if (Build.VERSION.SDK_INT &lt; Build.VERSION_CODES.HONEYCOMB) {
+        // Load the legacy preferences headers
+        addPreferencesFromResource(R.xml.preference_headers_legacy);
+    }
+}
+</pre>
+
+<p>Ketahuilah bahwa panggilan berturut-turut ke {@link
+android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} akan
+menumpuk semua preferensi ke dalam satu daftar, jadi pastikan bahwa ini hanya dipanggil sekali dengan mengikatkan syarat
+ke pernyataan else-if.</p>
+
+
+
+
+
+<h2 id="ReadingPrefs">Preferensi Membaca</h2>
+
+<p>Secara default, semua preferensi aplikasi Anda disimpan ke file yang bisa diakses dari mana saja
+di dalam aplikasi dengan memanggil metode statis {@link
+android.preference.PreferenceManager#getDefaultSharedPreferences
+PreferenceManager.getDefaultSharedPreferences()}. Ini akan mengembalikan objek {@link
+android.content.SharedPreferences} berisi semua pasangan nilai-kunci yang terkait
+dengan objek {@link android.preference.Preference} yang digunakan di {@link
+android.preference.PreferenceActivity} Anda.</p>
+
+<p>Misalnya, inilah cara membaca salah satu nilai preferensi dari aktivitas lain dalam aplikasi
+Anda:</p>
+
+<pre>
+SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
+String syncConnPref = sharedPref.getString(SettingsActivity.KEY_PREF_SYNC_CONN, "");
+</pre>
+
+
+
+<h3 id="Listening">Mendengarkan perubahan preferensi</h3>
+
+<p>Ada beberapa alasan yang membuat Anda perlu mendapatkan pemberitahuan segera setelah pengguna mengubah salah satu
+preferensi. Untuk menerima callback saat perubahan terjadi pada salah satu preferensi,
+implementasikan antarmuka {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener
+SharedPreference.OnSharedPreferenceChangeListener} dan daftarkan listener untuk objek
+{@link android.content.SharedPreferences} dengan memanggil {@link
+android.content.SharedPreferences#registerOnSharedPreferenceChangeListener
+registerOnSharedPreferenceChangeListener()}.</p>
+
+<p>Antarmuka hanya memiliki satu metode callback, {@link
+android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged
+onSharedPreferenceChanged()}, dan mungkin lebih mudah mengimplementasikan antarmuka sebagai bagian dari
+aktivitas Anda. Misalnya:</p>
+
+<pre>
+public class SettingsActivity extends PreferenceActivity
+                              implements OnSharedPreferenceChangeListener {
+    public static final String KEY_PREF_SYNC_CONN = "pref_syncConnectionType";
+    ...
+
+    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+        String key) {
+        if (key.equals(KEY_PREF_SYNC_CONN)) {
+            Preference connectionPref = findPreference(key);
+            // Set summary to be the user-description for the selected value
+            connectionPref.setSummary(sharedPreferences.getString(key, ""));
+        }
+    }
+}
+</pre>
+
+<p>Dalam contoh ini, metode akan memeriksa apakah pengaturan yang diubah adalah untuk kunci preferensi yang diketahui. Ini akan
+memanggil {@link android.preference.PreferenceActivity#findPreference findPreference()} untuk mendapatkan objek
+{@link android.preference.Preference} yang diubah agar bisa memodifikasi rangkuman item
+menjadi keterangan pada pilihan pengguna. Ini berarti, bila pengaturan adalah {@link
+android.preference.ListPreference} atau pengaturan multipilihan, Anda harus memanggil {@link
+android.preference.Preference#setSummary setSummary()} bila pengaturan berubah ke tampilkan
+status saat ini (seperti pengaturan Sleep yang ditampilkan dalam gambar 5).</p>
+
+<p class="note"><strong>Catatan:</strong> Seperti dijelaskan dalam dokumen Desain Android tentang <a href="{@docRoot}design/patterns/settings.html">Pengaturan</a>, kami merekomendasikan Anda untuk memperbarui
+rangkuman {@link android.preference.ListPreference} setiap kali pengguna mengubah preferensi untuk
+menjelaskan pengaturan saat ini.</p>
+
+<p>Untuk manajemen daur hidup yang baik di aktivitas, kami merekomendasikan Anda untuk mendaftarkan dan mencabut pendaftaran
+{@link android.content.SharedPreferences.OnSharedPreferenceChangeListener} selama callback {@link
+android.app.Activity#onResume} dan {@link android.app.Activity#onPause}:</p>
+
+<pre>
+&#64;Override
+protected void onResume() {
+    super.onResume();
+    getPreferenceScreen().getSharedPreferences()
+            .registerOnSharedPreferenceChangeListener(this);
+}
+
+&#64;Override
+protected void onPause() {
+    super.onPause();
+    getPreferenceScreen().getSharedPreferences()
+            .unregisterOnSharedPreferenceChangeListener(this);
+}
+</pre>
+
+<p class="caution"><strong>Perhatian:</strong> Bila Anda memanggil {@link
+android.content.SharedPreferences#registerOnSharedPreferenceChangeListener
+registerOnSharedPreferenceChangeListener()}, pengelola preferensi saat ini tidak akan
+menyimpan referensi kuat ke listener. Anda harus menyimpan referensi
+kuat bagi listener, atau referensi akan rentan terhadap pengumpulan sampah. Kami
+merekomendasikan Anda untuk mempertahankan referensi bagi listener dalam data instance objek
+yang akan ada selama Anda memerlukan listener tersebut.</p>
+
+<p>Misalnya, dalam kode berikut, caller tidak menyimpan referensi ke
+listener. Akibatnya, listener akan dikenakan pengumpulan sampah,
+dan suatu saat nanti akan gagal:</p>
+
+<pre>
+prefs.registerOnSharedPreferenceChangeListener(
+  // Bad! The listener is subject to garbage collection!
+  new SharedPreferences.OnSharedPreferenceChangeListener() {
+  public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
+    // listener implementation
+  }
+});
+</pre>
+
+<p>Sebagai gantinya, simpan referensi ke listener dalam bidang data instance
+objek yang akan ada selama listener dibutuhkan:</p>
+
+<pre>
+SharedPreferences.OnSharedPreferenceChangeListener listener =
+    new SharedPreferences.OnSharedPreferenceChangeListener() {
+  public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
+    // listener implementation
+  }
+};
+prefs.registerOnSharedPreferenceChangeListener(listener);
+</pre>
+
+<h2 id="NetworkUsage">Mengelola Penggunaan Jaringan</h2>
+
+
+<p>Mulai Android 4.0, aplikasi Settings untuk sistem memungkinkan pengguna melihat seberapa besar
+data jaringan yang digunakan aplikasi mereka saat berada di latar depan dan latar belakang. Kemudian pengguna bisa
+menonaktifkan penggunaan data latar belakang untuk aplikasi individual. Agar pengguna tidak menonaktifkan akses
+aplikasi ke data dari latar belakang, Anda harus menggunakan koneksi data secara efisien dan mengizinkan
+pengguna untuk menyaring penggunaan data aplikasi melalui pengaturan aplikasi Anda.<p>
+
+<p>Misalnya, Anda bisa mengizinkan pengguna untuk mengontrol seberapa sering aplikasi menyinkronkan data, apakah aplikasi
+hanya melakukan pengunggahan/pengunduhan bila ada Wi-Fi, apakah aplikasi menggunakan data saat roaming, dll. Dengan
+tersedianya kontrol ini bagi pengguna, mereka kemungkinan besar tidak akan menonaktifkan akses aplikasi ke data
+saat mendekati batas yang mereka tetapkan dalam Settings pada sistem, karena mereka bisa mengontrol secara tepat
+seberapa besar data yang digunakan aplikasi Anda.</p>
+
+<p>Setelah menambahkan preferensi yang diperlukan dalam {@link android.preference.PreferenceActivity} Anda
+untuk mengontrol kebiasaan data aplikasi, Anda harus menambahkan filter intent untuk {@link
+android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} dalam file manifes Anda. Misalnya:</p>
+
+<pre>
+&lt;activity android:name="SettingsActivity" ... >
+    &lt;intent-filter>
+       &lt;action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
+       &lt;category android:name="android.intent.category.DEFAULT" />
+    &lt;/intent-filter>
+&lt;/activity>
+</pre>
+
+<p>Filter intent ini menunjukkan pada sistem bahwa ini adalah aktivitas yang mengontrol penggunaan
+data aplikasi Anda. Jadi, saat pengguna memeriksa seberapa banyak data yang digunakan oleh aplikasi dari
+aplikasi Settings pada sistem, tombol <em>View application settings</em> akan tersedia dan menjalankan
+{@link android.preference.PreferenceActivity} sehingga pengguna bisa menyaring seberapa besar data yang digunakan
+aplikasi Anda.</p>
+
+
+
+
+
+
+
+<h2 id="Custom">Membangun Preferensi Custom</h2>
+
+<p>Kerangka kerja Android menyertakan berbagai subkelas {@link android.preference.Preference} yang
+memungkinkan Anda membangun UI untuk beberapa macam tipe pengaturan.
+Akan tetapi, Anda mungkin menemukan pengaturan yang diperlukan bila tidak ada solusi bawaan, seperti
+picker nomor atau picker tanggal. Dalam hal demikian, Anda akan perlu membuat preferensi custom dengan memperluas
+kelas {@link android.preference.Preference} atau salah satu subkelas lainnya.</p>
+
+<p>Bila memperluas kelas {@link android.preference.Preference}, ada beberapa hal
+penting yang perlu Anda lakukan:</p>
+
+<ul>
+  <li>Menetapkan antarmuka pengguna yang akan muncul saat pengguna memilih pengaturan.</li>
+  <li>Menyimpan nilai pengaturan bila perlu.</li>
+  <li>Menginisialisasi {@link android.preference.Preference} dengan nilai saat ini (atau default)
+bila muncul di tampilan.</li>
+  <li>Menyediakan nilai default bila diminta oleh sistem.</li>
+  <li>Jika {@link android.preference.Preference} menyediakan UI sendiri (seperti dialog), simpan
+dan pulihkan status untuk menangani perubahan daur hidup (seperti saat pengguna memutar layar).</li>
+</ul>
+
+<p>Bagian berikut menjelaskan cara melakukan setiap tugas ini.</p>
+
+
+
+<h3 id="CustomSelected">Menetapkan antarmuka pengguna</h3>
+
+  <p>Jika secara langsung memperluas kelas {@link android.preference.Preference}, Anda perlu mengimplementasikan
+{@link android.preference.Preference#onClick()} untuk mendefinisikan tindakan yang terjadi bila pengguna
+memilih item tersebut. Akan tetapi, sebagian besar pengaturan custom memperluas {@link android.preference.DialogPreference} untuk
+menampilkan dialog, sehingga menyederhanakan prosedur. Bila memperluas {@link
+android.preference.DialogPreference}, Anda harus memanggil {@link
+android.preference.DialogPreference#setDialogLayoutResource setDialogLayoutResourcs()} selama di
+konstruktor kelas untuk menetapkan layout dialog.</p>
+
+  <p>Misalnya, beri ini konstruktor untuk {@link
+android.preference.DialogPreference} custom yang mendeklarasikan layout dan menetapkan teks untuk tombol dialog
+negatif dan positif default:</p>
+
+<pre>
+public class NumberPickerPreference extends DialogPreference {
+    public NumberPickerPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        setDialogLayoutResource(R.layout.numberpicker_dialog);
+        setPositiveButtonText(android.R.string.ok);
+        setNegativeButtonText(android.R.string.cancel);
+
+        setDialogIcon(null);
+    }
+    ...
+}
+</pre>
+
+
+
+<h3 id="CustomSave">Menyimpan nilai pengaturan</h3>
+
+<p>Anda bisa menyimpan nilai pengaturan kapan saja dengan memanggil salah satu metode {@code persist*()} kelas {@link
+android.preference.Preference}, seperti {@link
+android.preference.Preference#persistInt persistInt()} jika nilai pengaturan adalah integer atau
+{@link android.preference.Preference#persistBoolean persistBoolean()} untuk menyimpan boolean.</p>
+
+<p class="note"><strong>Catatan:</strong> Setiap {@link android.preference.Preference} hanya bisa menyimpan satu
+tipe data, jadi Anda harus menggunakan metode {@code persist*()} yang tepat untuk tipe data yang digunakan
+oleh {@link android.preference.Preference} custom Anda.</p>
+
+<p>Bila Anda memilih untuk mempertahankannya, pengaturan bisa bergantung pada kelas {@link
+android.preference.Preference} yang Anda perluas. Jika Anda memperluas {@link
+android.preference.DialogPreference}, maka Anda harus mempertahankan nilai hanya jika dialog
+tertutup karena hasil positif (pengguna memilih tombol "OK").</p>
+
+<p>Bila {@link android.preference.DialogPreference} tertutup, sistem akan memanggil metode {@link
+android.preference.DialogPreference#onDialogClosed onDialogClosed()}. Metode mencakup argumen
+boolean yang menetapkan apakah hasil pengguna "positif"&mdash;jika nilainya
+<code>true</code>, maka pengguna memilih tombol positif dan Anda harus menyimpan nilai baru. Misalnya:
+</p>
+
+<pre>
+&#64;Override
+protected void onDialogClosed(boolean positiveResult) {
+    // When the user selects "OK", persist the new value
+    if (positiveResult) {
+        persistInt(mNewValue);
+    }
+}
+</pre>
+
+<p>Dalam contoh ini, <code>mNewValue</code> adalah anggota kelas yang menampung nilai
+pengaturan saat ini. Memanggil {@link android.preference.Preference#persistInt persistInt()} akan menyimpan nilai
+ke file {@link android.content.SharedPreferences} (secara otomatis menggunakan kunci yang
+ditetapkan dalam file XML untuk {@link android.preference.Preference} ini).</p>
+
+
+<h3 id="CustomInitialize">Menginisialisasi nilai saat ini</h3>
+
+<p>Bila sistem menambahkan {@link android.preference.Preference} Anda ke layar, ia
+akan memanggil {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} untuk memberi tahu
+Anda apakah pengaturan memiliki nilai yang dipertahankan. Jika tidak ada nilai yang dipertahankan, panggilan ini
+akan menyediakan nilai default bagi Anda.</p>
+
+<p>Metode {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} akan meneruskan
+boolean, <code>restorePersistedValue</code>, untuk menunjukkan apakah nilai dipertahankan
+untuk pengaturan. Jika <code>true</code>, maka Anda harus mengambil nilai yang dipertahankan dengan memanggil
+salah satu metode {@code getPersisted*()} kelas {@link
+android.preference.Preference}, seperti {@link
+android.preference.Preference#getPersistedInt getPersistedInt()} untuk nilai integer. Anda biasanya
+perlu mengambil nilai yang dipertahankan agar bisa memperbarui UI dengan benar untuk merefleksikan
+nilai yang tersimpan sebelumnya.</p>
+
+<p>Jika <code>restorePersistedValue</code> adalah <code>false</code>, maka Anda
+harus menggunakan nilai default yang diteruskan dalam argumen kedua.</p>
+
+<pre>
+&#64;Override
+protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
+    if (restorePersistedValue) {
+        // Restore existing state
+        mCurrentValue = this.getPersistedInt(DEFAULT_VALUE);
+    } else {
+        // Set default state from the XML attribute
+        mCurrentValue = (Integer) defaultValue;
+        persistInt(mCurrentValue);
+    }
+}
+</pre>
+
+<p>Setiap metode {@code getPersisted*()} memerlukan argumen yang menetapkan
+nilai default untuk digunakan jika tidak ada nilai yang dipertahankan atau kunci tidak ada. Dalam contoh
+di atas, konstanta lokal yang digunakan untuk menetapkan nilai default dalam kasus {@link
+android.preference.Preference#getPersistedInt getPersistedInt()} tidak bisa mengembalikan nilai yang dipertahankan.</p>
+
+<p class="caution"><strong>Perhatian:</strong> Anda <strong>tidak bisa</strong> menggunakan
+<code>defaultValue</code> sebagai nilai default dalam metode {@code getPersisted*()}, karena
+nilainya selalu nol bila <code>restorePersistedValue</code> adalah <code>true</code>.</p>
+
+
+<h3 id="CustomDefault">Menyediakan nilai default</h3>
+
+<p>Jika instance kelas {@link android.preference.Preference} Anda menetapkan nilai default
+(dengan atribut {@code android:defaultValue}), maka
+sistem akan memanggil {@link android.preference.Preference#onGetDefaultValue
+onGetDefaultValue()} bila membuat instance objek untuk mengambil nilai. Anda harus mengimplementasikan
+metode ini agar sistem bisa menyimpan nilai default dalam {@link
+android.content.SharedPreferences}. Misalnya:</p>
+
+<pre>
+&#64;Override
+protected Object onGetDefaultValue(TypedArray a, int index) {
+    return a.getInteger(index, DEFAULT_VALUE);
+}
+</pre>
+
+<p>Argumen metode menyediakan semua hal yang Anda perlukan: larik atribut dan posisi
+indeks dari {@code android:defaultValue}, yang harus Anda ambil. Alasan Anda harus
+mengimplementasikan metode ini untuk mengekstrak nilai default dari atribut adalah karena Anda harus menetapkan
+nilai default lokal untuk atribut jika nilai tidak didefinisikan.</p>
+
+
+
+<h3 id="CustomSaveState">Menyimpan dan memulihkan status Preferensi</h3>
+
+<p>Seperti halnya {@link android.view.View} di layout, subkelas {@link android.preference.Preference}
+Anda bertanggung jawab menyimpan dan memulihkan statusnya jika aktivitas atau fragmen
+di-restart (seperti saat pengguna memutar layar). Untuk menyimpan
+dan memulihkan status kelas {@link android.preference.Preference} dengan benar, Anda harus mengimplementasikan
+metode callback daur hidup {@link android.preference.Preference#onSaveInstanceState
+onSaveInstanceState()} dan {@link
+android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()}.</p>
+
+<p>Status {@link android.preference.Preference} Anda didefinisikan oleh objek yang mengimplementasikan
+antarmuka {@link android.os.Parcelable}. Kerangka kerja Android menyediakan objek seperti itu untuk Anda gunakan
+sebagai titik mulai untuk mendefinisikan objek status Anda: kelas {@link
+android.preference.Preference.BaseSavedState}.</p>
+
+<p>Untuk mendefinisikan cara kelas {@link android.preference.Preference} menyimpan statusnya, Anda harus
+memperluas kelas {@link android.preference.Preference.BaseSavedState}. Anda hanya perlu mengesampingkan
+ beberapa metode dan mendefinisikan objek {@link android.preference.Preference.BaseSavedState#CREATOR}
+.</p>
+
+<p>Untuk sebagian besar aplikasi, Anda bisa menyalin implementasi berikut dan cukup mengubah baris yang
+menangani {@code value} jika subkelas {@link android.preference.Preference} Anda menyimpan tipe
+data selain integer.</p>
+
+<pre>
+private static class SavedState extends BaseSavedState {
+    // Member that holds the setting's value
+    // Change this data type to match the type saved by your Preference
+    int value;
+
+    public SavedState(Parcelable superState) {
+        super(superState);
+    }
+
+    public SavedState(Parcel source) {
+        super(source);
+        // Get the current preference's value
+        value = source.readInt();  // Change this to read the appropriate data type
+    }
+
+    &#64;Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
+        // Write the preference's value
+        dest.writeInt(value);  // Change this to write the appropriate data type
+    }
+
+    // Standard creator object using an instance of this class
+    public static final Parcelable.Creator&lt;SavedState> CREATOR =
+            new Parcelable.Creator&lt;SavedState>() {
+
+        public SavedState createFromParcel(Parcel in) {
+            return new SavedState(in);
+        }
+
+        public SavedState[] newArray(int size) {
+            return new SavedState[size];
+        }
+    };
+}
+</pre>
+
+<p>Dengan implementasi {@link android.preference.Preference.BaseSavedState} di atas yang ditambahkan
+ke aplikasi Anda (biasanya sebagai subkelas dari subkelas {@link android.preference.Preference}), Anda
+nanti perlu mengimplementasikan metode {@link android.preference.Preference#onSaveInstanceState
+onSaveInstanceState()} dan {@link
+android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()} untuk subkelas
+{@link android.preference.Preference} Anda.</p>
+
+<p>Misalnya:</p>
+
+<pre>
+&#64;Override
+protected Parcelable onSaveInstanceState() {
+    final Parcelable superState = super.onSaveInstanceState();
+    // Check whether this Preference is persistent (continually saved)
+    if (isPersistent()) {
+        // No need to save instance state since it's persistent,
+        // use superclass state
+        return superState;
+    }
+
+    // Create instance of custom BaseSavedState
+    final SavedState myState = new SavedState(superState);
+    // Set the state's value with the class member that holds current
+    // setting value
+    myState.value = mNewValue;
+    return myState;
+}
+
+&#64;Override
+protected void onRestoreInstanceState(Parcelable state) {
+    // Check whether we saved the state in onSaveInstanceState
+    if (state == null || !state.getClass().equals(SavedState.class)) {
+        // Didn't save the state, so call superclass
+        super.onRestoreInstanceState(state);
+        return;
+    }
+
+    // Cast state to custom BaseSavedState and pass to superclass
+    SavedState myState = (SavedState) state;
+    super.onRestoreInstanceState(myState.getSuperState());
+
+    // Set this Preference's widget to reflect the restored state
+    mNumberPicker.setValue(myState.value);
+}
+</pre>
+
diff --git a/docs/html-intl/intl/id/guide/topics/ui/ui-events.jd b/docs/html-intl/intl/id/guide/topics/ui/ui-events.jd
new file mode 100644
index 0000000..0307b34
--- /dev/null
+++ b/docs/html-intl/intl/id/guide/topics/ui/ui-events.jd
@@ -0,0 +1,291 @@
+page.title=Kejadian Input
+parent.title=Antarmuka Pengguna
+parent.link=index.html
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>Dalam dokumen ini</h2>
+  <ol>
+    <li><a href="#EventListeners">Event Listener</a></li>
+    <li><a href="#EventHandlers">Event Handler</a></li>
+    <li><a href="#TouchMode">Mode Sentuh</a></li>
+    <li><a href="#HandlingFocus">Menangani Fokus</a></li>
+  </ol>
+
+</div>
+</div>
+
+<p>Di Android, ada lebih dari satu cara untuk mencegat kejadian dari interaksi pengguna dengan aplikasi Anda.
+Saat mempertimbangkan kejadian dalam antarmuka pengguna Anda, pendekatannya adalah menangkap kejadian
+dari objek View tertentu yang digunakan pengguna untuk berinteraksi. Kelas View menyediakan sarana untuk melakukannya.</p>
+
+<p>Dalam berbagai kelas View yang akan digunakan untuk menyusun layout, Anda mungkin melihat beberapa metode callback
+publik yang tampak berguna untuk kejadian UI. Metode ini dipanggil oleh kerangka kerja Android ketika masing-masing
+tindakan terjadi pada objek itu. Misalnya, bila View (seperti Button/Tombol) disentuh,
+metode <code>onTouchEvent()</code> akan dipanggil pada objek itu. Akan tetapi, untuk mencegatnya, Anda harus memperluas
+kelas dan mengesampingkan metode itu. Akan tetapi, memperluas setiap objek View
+untuk menangani kejadian seperti itu tidaklah praktis. Karena itulah kelas View juga berisi
+sekumpulan antarmuka tersarang dengan callback yang jauh lebih mudah didefinisikan. Antarmuka ini,
+yang disebut <a href="#EventListeners">event listener</a>, merupakan tiket Anda untuk menangkap interaksi pengguna dengan UI.</p>
+
+<p>Walaupun Anda akan lebih sering menggunakan event listener ini untuk interaksi pengguna,
+mungkin ada saatnya Anda ingin memperluas kelas View, untuk membuat komponen custom.
+Mungkin Anda ingin memperluas kelas {@link android.widget.Button}
+untuk membuat sesuatu yang lebih menarik. Dalam hal ini, Anda akan dapat mendefinisikan perilaku kejadian default untuk kelas Anda dengan menggunakan
+kelas <a href="#EventHandlers">event handler</a>.</p>
+
+
+<h2 id="EventListeners">Event Listener</h2>
+
+<p>Event listener merupakan antarmuka di kelas {@link android.view.View} yang berisi metode
+callback tunggal. Metode ini akan dipanggil oleh kerangka kerja Android bila View yang
+telah didaftarkan dengan listener dipicu oleh interaksi pengguna dengan item dalam UI.</p>
+
+<p>Yang juga disertakan dalam antarmuka event listener adalah metode callback berikut ini:</p>
+
+<dl>
+  <dt><code>onClick()</code></dt>
+    <dd>Dari {@link android.view.View.OnClickListener}.
+    Ini dipanggil baik saat pengguna menyentuh item
+ (bila dalam mode sentuh), maupun memfokuskan pada item dengan tombol navigasi atau trackball dan
+menekan tombol "enter" yang sesuai atau menekan trackball.</dd>
+  <dt><code>onLongClick()</code></dt>
+    <dd>Dari {@link android.view.View.OnLongClickListener}.
+    Ini dipanggil baik saat pengguna menyentuh dan menahan item (bila dalam mode sentuh),
+maupun memfokuskan pada item dengan tombol navigasi atau trackball dan
+menekan serta menahan tombol "enter" yang sesuai atau menekan dan menahan trackball (selama satu detik).</dd>
+  <dt><code>onFocusChange()</code></dt>
+    <dd>Dari {@link android.view.View.OnFocusChangeListener}.
+    Ini dipanggil saat pengguna menyusuri ke atau dari item, dengan menggunakan tombol navigasi atau trackball.</dd>
+  <dt><code>onKey()</code></dt>
+    <dd>Dari {@link android.view.View.OnKeyListener}.
+    Ini dipanggil saat pengguna memfokuskan pada item dan menekan atau melepas tombol fisik pada perangkat.</dd>
+  <dt><code>onTouch()</code></dt>
+    <dd>Dari {@link android.view.View.OnTouchListener}.
+    Ini dipanggil saat pengguna melakukan tindakan yang digolongkan sebagai kejadian sentuh, termasuk penekanan, pelepasan,
+atau gerak perpindahan pada layar (dalam batasan item itu).</dd>
+  <dt><code>onCreateContextMenu()</code></dt>
+    <dd>Dari {@link android.view.View.OnCreateContextMenuListener}.
+    Ini dipanggil saat Menu Konteks sedang dibuat (akibat "klik lama" terus-menerus). Lihat diskusi
+tentang menu konteks di panduan pengembang <a href="{@docRoot}guide/topics/ui/menus.html#context-menu">Menu</a>.
+</dd>
+</dl>
+
+<p>Metode ini satu-satunya yang menempati antarmukanya masing-masing. Untuk mendefinisikan salah satu metode ini
+dan menangani kejadian Anda, implementasikan antarmuka tersarang dalam Aktivitas Anda atau definisikan sebagai kelas anonim.
+Kemudian, teruskan satu
+instance implementasi Anda pada masing-masing metode <code>View.set...Listener()</code>. (Misalnya, panggil
+<code>{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()}</code>
+dan teruskan implementasi {@link android.view.View.OnClickListener OnClickListener} Anda.)</p>
+
+<p>Contoh di bawah menunjukkan cara mendaftarkan on-click listener untuk Button. </p>
+
+<pre>
+// Create an anonymous implementation of OnClickListener
+private OnClickListener mCorkyListener = new OnClickListener() {
+    public void onClick(View v) {
+      // do something when the button is clicked
+    }
+};
+
+protected void onCreate(Bundle savedValues) {
+    ...
+    // Capture our button from layout
+    Button button = (Button)findViewById(R.id.corky);
+    // Register the onClick listener with the implementation above
+    button.setOnClickListener(mCorkyListener);
+    ...
+}
+</pre>
+
+<p>Anda juga akan merasa lebih praktis mengimplementasikan OnClickListener sebagai bagian dari Aktivitas.
+Ini akan menghindari beban kelas ekstra dan alokasi objek. Misalnya:</p>
+<pre>
+public class ExampleActivity extends Activity implements OnClickListener {
+    protected void onCreate(Bundle savedValues) {
+        ...
+        Button button = (Button)findViewById(R.id.corky);
+        button.setOnClickListener(this);
+    }
+
+    // Implement the OnClickListener callback
+    public void onClick(View v) {
+      // do something when the button is clicked
+    }
+    ...
+}
+</pre>
+
+<p>Perhatikan bahwa callback <code>onClick()</code> dalam contoh di atas tidak memiliki
+nilai hasil, namun beberapa metode event listener lainnya harus mengembalikan boolean. Sebabnya
+bergantung pada kejadian. Untuk sebagian yang mengembalikan boolean, ini sebabnya:</p>
+<ul>
+  <li><code>{@link android.view.View.OnLongClickListener#onLongClick(View) onLongClick()}</code> -
+    Ini mengembalikan boolean untuk menunjukkan apakah Anda telah menggunakan kejadian dan tidak boleh dibawa lebih jauh.
+    Yaitu, mengembalikan <em>benar</em> untuk menunjukkan apakah Anda telah menangani kejadian dan semestinya berhenti di sini;
+    mengembalikan <em>salah</em> jika Anda tidak menanganinya dan/atau kejadian semestinya berlanjut ke
+    on-click listener lainnya.</li>
+  <li><code>{@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent) onKey()}</code> -
+    Ini mengembalikan boolean untuk menunjukkan apakah Anda telah menggunakan kejadian dan tidak boleh dibawa lebih jauh.
+    Yaitu, mengembalikan <em>benar</em> untuk menunjukkan apakah Anda telah menangani kejadian dan semestinya berhenti di sini;
+    mengembalikan <em>salah</em> jika Anda tidak menanganinya dan/atau kejadian semestinya berlanjut ke
+    on-key listener lainnya.</li>
+  <li><code>{@link android.view.View.OnTouchListener#onTouch(View,MotionEvent) onTouch()}</code> -
+    Ini mengembalikan boolean untuk menunjukkan apakah listener Anda telah menggunakan kejadian ini. Yang penting adalah
+kejadian ini bisa memiliki beberapa tindakan yang saling mengikuti. Jadi, jika Anda mengembalikan <em>salah</em>saat
+kejadian tindakan turun diterima, itu menunjukkan bahwa Anda belum menggunakan kejadian itu dan juga
+tidak tertarik dengan tindakan berikutnya dari kejadian ini. Karena itu, Anda tidak akan diminta untuk melakukan tindakan
+ lainnya dalam kejadian, seperti gerakan jari, atau kejadian tindakan naik yang akan terjadi.</li>
+</ul>
+
+<p>Ingatlah bahwa kejadian tombol fisik selalu disampaikan ke View yang sedang difokus. Kejadian ini dikirim mulai dari atas
+hierarki View, kemudian turun hingga tujuan yang sesuai. Jika View Anda (atau anak View Anda)
+saat ini sedang fokus, maka Anda dapat melihat kejadian berpindah melalui metode.<code>{@link android.view.View#dispatchKeyEvent(KeyEvent)
+dispatchKeyEvent()}</code> Sebagai pengganti untuk menangkap kejadian penting melalui View, Anda juga dapat menerima
+semua kejadian dalam Aktivitas Anda dengan <code>{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}</code>
+dan <code>{@link android.app.Activity#onKeyUp(int,KeyEvent) onKeyUp()}</code>.</p>
+
+<p>Selain itu, saat memikirkan tentang input teks aplikasi Anda, ingatlah bahwa banyak perangkat yang hanya memiliki
+metode input perangkat lunak. Metode seperti itu tidak harus berbasis tombol; sebagian mungkin menggunakan input suara, tulisan tangan, dan seterusnya. Meskipun
+metode input menyajikan antarmuka seperti keyboard, itu umumnya <strong>tidak</strong> memicu keluarga kejadian
+<code>{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}</code>. Anda sama sekali tidak boleh
+membangun UI yang mengharuskan penekanan tombol tertentu dikontrol kecuali jika Anda ingin membatasi aplikasi Anda pada perangkat yang memiliki
+keyboard fisik. Khususnya, jangan mengandalkan metode ini untuk memvalidasi input saat pengguna menekan tombol
+enter; melainkan, gunakan tindakan seperti {@link android.view.inputmethod.EditorInfo#IME_ACTION_DONE} untuk menandai
+metode input mengenai reaksi yang diharapkan aplikasi Anda, sehingga bisa mengubah UI-nya secara signifikan. Hindari anggapan
+tentang bagaimana metode input perangkat lunak seharusnya bekerja dan percayalah bahwa metode akan menyediakan teks yang sudah diformat bagi aplikasi Anda.</p>
+
+<p class="note"><strong>Catatan:</strong> Android akan memanggil event handler terlebih dahulu kemudian handler
+default yang sesuai dari definisi kelas. Karena itu, mengembalikan <em>benar</em> dari event listener ini akan menghentikan
+penyebaran kejadian ke event listener lain dan juga akan memblokir callback ke
+event handler default di View. Pastikan bahwa Anda ingin mengakhiri kejadian saat mengembalikan <em>true</em>.</p>
+
+
+<h2 id="EventHandlers">Event Handler</h2>
+
+<p>Jika Anda membuat komponen custom dari View, maka Anda dapat mendefinisikan penggunaan beberapa
+metode callback sebagai event handler default.
+Dalam dokumen tentang <a href="{@docRoot}guide/topics/ui/custom-components.html">Komponen
+Custom</a>, Anda akan melihat penggunaan beberapa callback umum untuk penanganan kejadian,
+termasuk:</p>
+<ul>
+  <li><code>{@link  android.view.View#onKeyDown}</code> - Dipanggil bila terjadi kejadian tombol baru.</li>
+  <li><code>{@link  android.view.View#onKeyUp}</code> - Dipanggil bila terjadi kejadian tombol naik.</li>
+  <li><code>{@link  android.view.View#onTrackballEvent}</code> - Dipanggil bila terjadi kejadian gerakan trackball.</li>
+  <li><code>{@link  android.view.View#onTouchEvent}</code> - Dipanggil bila terjadi kejadian gerakan layar sentuh.</li>
+  <li><code>{@link  android.view.View#onFocusChanged}</code> - Dipanggil bila View memperoleh atau kehilangan fokus.</li>
+</ul>
+<p>Ada beberapa metode lain yang harus Anda ketahui, yang bukan bagian dari kelas View,
+namun bisa berdampak langsung pada kemampuan Anda menangani kejadian. Jadi, saat mengelola kejadian yang lebih kompleks dalam
+layout, pertimbangkanlah metode-metode lain ini:</p>
+<ul>
+  <li><code>{@link  android.app.Activity#dispatchTouchEvent(MotionEvent)
+    Activity.dispatchTouchEvent(MotionEvent)}</code> - Ini memungkinkan {@link
+    android.app.Activity} Anda mencegat semua kejadian sentuh sebelum dikirim ke jendela.</li>
+  <li><code>{@link  android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)
+    ViewGroup.onInterceptTouchEvent(MotionEvent)}</code> - Ini memungkinkan {@link
+    android.view.ViewGroup} memantau kejadian saat dikirim ke View anak.</li>
+  <li><code>{@link  android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean)
+    ViewParent.requestDisallowInterceptTouchEvent(boolean)}</code> - Panggil ini
+    pada View induk untuk menunjukan larangan mencegat kejadian sentuh dengan <code>{@link
+    android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)}</code>.</li>
+</ul>
+
+<h2 id="TouchMode">Mode Sentuh</h2>
+<p>
+Saat pengguna menyusuri antarmuka pengguna dengan tombol pengarah atau trackball, Anda
+perlu memberikan fokus pada item tindakan (seperti tombol) agar pengguna bisa mengetahui apa
+yang akan menerima input.  Akan tetapi jika perangkat memiliki kemampuan sentuh, dan pengguna
+mulai berinteraksi dengan antarmuka dengan menyentuhnya, maka Anda tidak perlu lagi
+menyorot item, atau memfokuskan pada View tertentu.  Karena itu, ada mode
+untuk interaksi yang bernama "mode sentuh".
+</p>
+<p>
+Untuk perangkat berkemampuan sentuh, setelah pengguna menyentuh layar, perangkat
+akan masuk ke mode sentuh.  Dari sini dan selanjutnya, hanya View dengan
+{@link android.view.View#isFocusableInTouchMode} benar yang akan dapat difokus, seperti widget pengedit teks.
+View lain yang dapat disentuh, seperti tombol, tidak akan difokus bila disentuh; View ini akan
+langsung memicu on-click listener bila ditekan.
+</p>
+<p>
+Kapan saja pengguna menekan tombol pengarah atau menggulir dengan trackball, perangkat akan
+keluar dari mode sentuh, dan mencari tampilan untuk difokuskan. Kini pengguna bisa melanjutkan interaksi
+dengan antarmuka pengguna tanpa menyentuh layar.
+</p>
+<p>
+Status mode sentuh dipertahankan di seluruh sistem (semua jendela dan aktivitas).
+Untuk query status saat ini, Anda bisa memanggil
+{@link android.view.View#isInTouchMode} untuk mengetahui apakah perangkat saat ini sedang dalam mode sentuh.
+</p>
+
+
+<h2 id="HandlingFocus">Menangani Fokus</h2>
+
+<p>Kerangka kerja ini akan menangani gerakan fokus rutin sebagai respons input pengguna.
+Ini termasuk mengubah fokus saat View dihapus atau disembunyikan, atau saat tersedia View
+baru. View menunjukkan kesediaannya untuk mengambil fokus
+melalui metode <code>{@link android.view.View#isFocusable()}</code>. Untuk mengubah apakah View bisa mengambil
+fokus, panggil <code>{@link android.view.View#setFocusable(boolean) setFocusable()}</code>.  Saat dalam mode sentuh,
+Anda dapat me-query apakah View memungkinkan fokus dengan <code>{@link android.view.View#isFocusableInTouchMode()}</code>.
+Anda bisa mengubahnya dengan <code>{@link android.view.View#setFocusableInTouchMode(boolean) setFocusableInTouchMode()}</code>.
+</p>
+
+<p>Gerakan fokus berdasarkan pada algoritma yang mencari tetangga terdekat dalam
+arah yang diberikan. Dalam kasus yang jarang terjadi, algoritma default mungkin
+tidak cocok dengan perilaku yang diinginkan pengembang. Dalam situasi ini, Anda bisa memberikan
+pengesampingan eksplisit dengan mengikuti atribut XML berikut dalam file layout:
+<var>nextFocusDown</var>, <var>nextFocusLeft</var>, <var>nextFocusRight</var>, dan
+<var>nextFocusUp</var>. Tambahkan salah satu atribut ini ke View <em>dari</em> mana fokus
+meninggalkan. Definisikan nilai atribut untuk menjadi ID View
+<em>ke</em> mana fokus harus diberikan. Misalnya:</p>
+<pre>
+&lt;LinearLayout
+    android:orientation="vertical"
+    ... >
+  &lt;Button android:id="@+id/top"
+          android:nextFocusUp="@+id/bottom"
+          ... />
+  &lt;Button android:id="@+id/bottom"
+          android:nextFocusDown="@+id/top"
+          ... />
+&lt;/LinearLayout>
+</pre>
+
+<p>Biasanya, dalam layout vertikal ini, navigasi ke atas dari Button pertama tidak akan membawa ke
+mana pun, tidak pula akan menyusuri ke bawah dari Button kedua. Karena sekarang Button atas telah
+mendefinisikan Button bawah sebagai <var>nextFocusUp</var> (dan sebaliknya), fokus navigasi akan
+silih berganti dari atas ke bawah dan bawah ke atas.</p>
+
+<p>Jika Anda ingin mendeklarasikan View sebagai dapat difokus dalam UI (bila biasanya tidak dapat difokus),
+tambahkan atribut XML <code>android:focusable</code> ke View, dalam deklarasi layout Anda.
+Atur nilai <var>true</var>. Anda juga bisa mendeklarasikan View
+sebagai dapat difokus saat dalam Mode Sentuh dengan <code>android:focusableInTouchMode</code>.</p>
+<p>Untuk meminta View tertentu difokus, panggil <code>{@link android.view.View#requestFocus()}</code>.</p>
+<p>Untuk mendengarkan kejadian fokus (diberi tahu bila View menerima atau kehilangan fokus), gunakan
+<code>{@link android.view.View.OnFocusChangeListener#onFocusChange(View,boolean) onFocusChange()}</code>
+, seperti yang dibahas di bagian <a href="#EventListeners">Event Listener</a>, di atas.</p>
+
+
+
+<!--
+<h2 is="EventCycle">Event Cycle</h2>
+   <p>The basic cycle of a View is as follows:</p>
+   <ol>
+    <li>An event comes in and is dispatched to the appropriate View. The View
+    handles the event and notifies any listeners.</li>
+    <li>If, in the course of processing the event, the View's bounds may need
+    to be changed, the View will call {@link android.view.View#requestLayout()}.</li>
+    <li>Similarly, if in the course of processing the event the View's appearance
+    may need to be changed, the View will call {@link android.view.View#invalidate()}.</li>
+    <li>If either {@link android.view.View#requestLayout()} or {@link android.view.View#invalidate()} were called,
+    the framework will take care of measuring, laying out, and drawing the tree
+    as appropriate.</li>
+   </ol>
+
+   <p class="note"><strong>Note:</strong> The entire View tree is single threaded. You must always be on
+   the UI thread when calling any method on any View.
+   If you are doing work on other threads and want to update the state of a View
+   from that thread, you should use a {@link android.os.Handler}.
+   </p>
+-->
diff --git a/docs/html-intl/intl/id/training/articles/direct-boot.jd b/docs/html-intl/intl/id/training/articles/direct-boot.jd
new file mode 100644
index 0000000..a7e3cf3
--- /dev/null
+++ b/docs/html-intl/intl/id/training/articles/direct-boot.jd
@@ -0,0 +1,181 @@
+page.title=Direct Boot
+page.keywords=pratinjau,sdk,direct boot
+page.tags=androidn
+page.image=images/cards/card-nyc_2x.jpg
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+  <h2>Dalam dokumen ini</h2>
+  <ol>
+    <li><a href="#run">Meminta Akses untuk Berjalan Selama Direct Boot</a></li>
+    <li><a href="#access">Mengakses Penyimpanan yang Dienkripsi dengan Perangkat</a></li>
+    <li><a href="#notification">Mendapatkan Pemberitahuan saat Pengguna Membuka Kunci</a></li>
+    <li><a href="#migrating">Migrasi Data yang Ada</a></li>
+    <li><a href="#testing">Menguji Aplikasi Peka Enkripsi Anda</a></li>
+  </ol>
+</div>
+</div>
+
+<p>Android N berjalan dalam mode <i>Direct Boot</i> yang aman
+bila perangkat telah dihidupkan namun pengguna tidak membuka
+kunci perangkat. Untuk mendukung hal ini, sistem menyediakan dua lokasi penyimpanan untuk data:</p>
+
+<ul>
+<li><i>Penyimpanan yang dienkripsi dengan kredensial</i>, yang merupakan lokasi penyimpanan default
+dan hanya tersedia setelah pengguna membuka kunci perangkat.</li>
+<li><i>Penyimpanan yang dienkripsi dengan perangkat</i>, yang merupakan lokasi penyimpanan yang tersedia
+selama mode Direct Boot dan setelah pengguna membuka kunci perangkat.</li>
+</ul>
+
+<p>Secara default, aplikasi tidak berjalan selama mode Direct Boot.
+Jika aplikasi Anda perlu melakukan tindakan selama mode Direct Boot, Anda bisa mendaftarkan
+komponen aplikasi yang harus dijalankan selama mode ini. Beberapa kasus penggunaan umum
+untuk aplikasi yang perlu dijalankan selama mode Direct Boot antara lain:</p>
+
+<ul>
+<li>Aplikasi yang telah menjadwalkan pemberitahuan, seperti aplikasi
+beker.</li>
+<li>Aplikasi yang menyediakan pemberitahuan pengguna yang penting, seperti aplikasi SMS.</li>
+<li>Aplikasi yang menyediakan layanan aksesibilitas, seperti TalkBack.</li>
+</ul>
+
+<p>Jika aplikasi Anda perlu mengakses data saat dijalankan dalam mode Direct Boot, gunakan
+penyimpanan yang dienkripsi dengan perangkat. Penyimpanan yang dienkripsi dengan perangkat berisi data
+yang dienkripsi dengan kunci yang hanya tersedia setelah perangkat melakukan
+booting yang berhasil diverifikasi.</p>
+
+<p>Untuk data yang harus dienkripsi dengan kunci yang dikaitkan dengan kredensial
+pengguna, seperti PIN atau kata sandi, gunakan penyimpanan yang dienkripsi dengan kredensial.
+Penyimpanan yang dienkripsi dengan kredensial hanya tersedia setelah pengguna berhasil
+membuka kunci perangkat, hingga saat pengguna menghidupkan ulang perangkat lagi. Jika
+pengguna mengaktifkan layar kunci setelah membuka kunci perangkat, hal ini tidak akan mengunci
+penyimpanan yang dienkripsi dengan kredensial.</p>
+
+<h2 id="run">Meminta Akses untuk Berjalan Selama Direct Boot</h2>
+
+<p>Aplikasi harus mendaftarkan komponennya pada sistem agar
+bisa berjalan selama mode Direct Boot atau mengakses
+penyimpanan yang dienkripsi dengan perangkat. Aplikasi mendaftar pada sistem dengan menandai komponen sebagai
+<i>peka enkripsi</i>. Untuk menandai komponen Anda sebagai peka enkripsi, setel atribut
+<code>android:directBootAware</code> ke true dalam manifes Anda.<p>
+
+<p>Komponen yang peka enkripsi bisa mendaftar untuk menerima pesan siaran
+<code>LOCKED_BOOT_COMPLETED</code> dari
+sistem bila perangkat telah dihidupkan ulang. Pada tahap ini
+penyimpanan yang dienkripsi dengan perangkat akan tersedia, dan komponen Anda bisa mengeksekusi tugas-tugas yang perlu
+dijalankan selama mode Direct Boot, seperti memicu alarm yang terjadwal.</p>
+
+<p>Cuplikan kode berikut adalah contoh cara mendaftarkan
+{@link android.content.BroadcastReceiver} sebagai peka enkripsi, dan menambahkan sebuah
+filter intent untuk <code>LOCKED_BOOT_COMPLETED</code>, dalam manifes aplikasi:</p>
+
+<pre>
+&lt;receiver
+  android:directBootAware="true" &gt;
+  ...
+  &lt;intent-filter&gt;
+    &lt;action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" /&gt;
+  &lt;/intent-filter&gt;
+&lt;/receiver&gt;
+</pre>
+
+<p>Setelah pengguna membuka kunci perangkat, semua komponen bisa mengakses
+penyimpanan yang dienkripsi dengan perangkat serta penyimpanan yang dienkripsi dengan kredensial.</p>
+
+<h2 id="access">Mengakses Penyimpanan yang Dienkripsi dengan Perangkat</h2>
+
+<p>Untuk mengakses penyimpanan yang dienkripsi dengan perangkat, buat instance
+{@link android.content.Context} kedua dengan memanggil
+<code>Context.createDeviceProtectedStorageContext()</code>. Semua panggilan
+API penyimpanan yang dibuat menggunakan konteks ini mengakses penyimpanan yang dienkripsi dengan perangkat. Contoh
+berikut mengakses penyimpanan yang dienkripsi dengan perangkat dan membuka file data aplikasi
+yang ada:</p>
+
+<pre>
+Context directBootContext = appContext.createDeviceProtectedStorageContext();
+// Access appDataFilename that lives in device encrypted storage
+FileInputStream inStream = directBootContext.openFileInput(appDataFilename);
+// Use inStream to read content...
+</pre>
+
+<p>Gunakan penyimpanan yang dienkripsi dengan perangkat hanya untuk
+informasi yang harus bisa diakses selama mode Direct Boot.
+Jangan gunakan penyimpanan yang dienkripsi dengan perangkat sebagai penyimpanan terenkripsi serba guna.
+Untuk informasi pengguna yang bersifat pribadi, atau data terenkripsi yang tidak diperlukan selama
+mode Direct Boot, gunakan penyimpanan yang dienkripsi dengan kredensial.</p>
+
+<h2 id="notification">Mendapatkan Pemberitahuan saat Pengguna Membuka Kunci</h2>
+
+<p>Setelah pengguna membuka kunci perangkat setelah restart, aplikasi Anda bisa beralih untuk
+mengakses penyimpanan yang dienkripsi dengan kredensial dan menggunakan layanan sistem biasa yang
+bergantung pada kredensial pengguna.</p>
+
+<p>Agar diberi tahu bila pengguna membuka kunci perangkat setelah boot ulang,
+daftarkan {@link android.content.BroadcastReceiver} dari komponen yang berjalan
+untuk mendengarkan pesan <code>ACTION_USER_UNLOCKED</code>. Atau, Anda bisa
+menerima pesan {@link android.content.Intent#ACTION_BOOT_COMPLETED
+ACTION_BOOT_COMPLETED} yang ada, yang sekarang menunjukkan bahwa perangkat telah dihidupkan dan
+pengguna telah membuka kunci perangkat.</p>
+
+<p>Anda bisa langsung kueri apakah pengguna telah membuka kunci perangkat dengan memanggil
+<code>UserManager.isUserUnlocked()</code>.</p>
+
+<h2 id="migrating">Migrasi Data yang Ada</h2>
+
+<p>Jika pengguna memperbarui perangkat mereka untuk menggunakan mode Direct Boot,
+data Anda yang ada mungkin perlu dipindahkan ke penyimpanan yang dienkripsi dengan perangkat. Gunakan
+<code>Context.moveSharedPreferencesFrom()</code> dan
+<code>Context.moveDatabaseFrom()</code> untuk memindahkan data preferensi dan
+basis data antara penyimpanan yang dienkripsi dengan kredensial dan penyimpanan yang dienkripsi dengan perangkat.</p>
+
+<p>Pertimbangkan dengan baik saat memutuskan data apa yang akan dipindahkan dari
+penyimpanan yang dienkripsi dengan kredensial ke penyimpanan yang dienkripsi dengan perangkat. Anda sebaiknya tidak memindahkan
+informasi pengguna yang bersifat rahasia, seperti kata sandi atau token otorisasi, ke
+penyimpanan yang dienkripsi dengan perangkat. Dalam beberapa skenario, Anda mungkin perlu mengelola
+set data terpisah pada dua tempat penyimpanan yang dienkripsi.</p>
+
+<h2 id="testing">Menguji Aplikasi Peka Enkripsi Anda</h2>
+
+<p>Uji aplikasi peka enkripsi Anda menggunakan mode Direct Boot baru. Ada
+dua cara untuk mengaktifkan Direct Boot.</p>
+
+<p class="caution"><strong>Perhatian:</strong> Mengaktifkan Direct Boot
+akan menghapus semua data pengguna pada perangkat.</p>
+
+<p>Pada perangkat yang didukung dengan Android N terpasang, aktifkan
+Direct Boot dengan melakukan salah satu hal berikut:</p>
+
+<ul>
+<li>Pada perangkat, aktifkan <b>Developer options</b> jika Anda belum melakukannya dengan
+masuk ke <b>Settings &gt; About phone</b>, dan menyentuh <b>Build number</b>
+tujuh kali. Setelah layar Developer options terbuka, masuk ke
+<b>Settings &gt; Developer options</b> dan pilih
+<b>Convert to file encryption</b>.</li>
+<li>Gunakan perintah shell adb berikut untuk mengaktifkan mode Direct Boot:
+<pre class="no-pretty-print">
+$ adb reboot-bootloader
+$ fastboot --wipe-and-use-fbe
+</pre>
+</li>
+</ul>
+
+<p>Mode emulasi Direct Boot juga tersedia, jika Anda perlu mengganti
+mode pada perangkat pengujian. Mode emulasi sebaiknya hanya digunakan selama
+pengembangan dan bisa menyebabkan kehilangan data. Untuk mengaktifkan mode emulasi Direct Boot,
+setel pola kunci pada perangkat, pilih "No thanks" jika ditanya mengenai
+layar start-up aman saat menetapkan pola kunci, kemudian gunakan
+perintah shell adb berikut:</p>
+
+<pre class="no-pretty-print">
+$ adb shell sm set-emulate-fbe true
+</pre>
+
+<p>Untuk menonaktifkan mode emulasi Direct Boot, gunakan perintah berikut:</p>
+
+<pre class="no-pretty-print">
+$ adb shell sm set-emulate-fbe false
+</pre>
+
+<p>Menggunakan perintah ini akan menyebabkan perangkat melakukan boot ulang.</p>
diff --git a/docs/html-intl/intl/id/training/articles/scoped-directory-access.jd b/docs/html-intl/intl/id/training/articles/scoped-directory-access.jd
new file mode 100644
index 0000000..30aed6f
--- /dev/null
+++ b/docs/html-intl/intl/id/training/articles/scoped-directory-access.jd
@@ -0,0 +1,148 @@
+page.title=Scoped Directory Access
+page.keywords=pratinjau,sdk,scoped directory access
+page.tags=androidn
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+  <h2>Dalam dokumen ini</h2>
+  <ol>
+    <li><a href="#accessing">Mengakses Direktori Penyimpanan Eksternal</a></li>
+    <li><a href="#removable">Mengakses Direktori pada Media Lepas-Pasang</a></li>
+    <li><a href="#best">Praktik Terbaik</a></li>
+  </ol>
+</div>
+</div>
+
+<p>Aplikasi seperti aplikasi foto biasanya hanya memerlukan akses ke direktori tertentu dalam
+penyimpanan eksternal, seperti direktori <code>Pictures</code>. Pendekatan
+yang ada dalam mengakses penyimpanan eksternal tidak didesain untuk memberi kemudahan
+akses direktori tertarget untuk tipe aplikasi ini. Misalnya:</p>
+
+<ul>
+<li>Meminta {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}
+atau {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} dalam manifes Anda
+akan memungkinkan akses ke semua direktori publik pada penyimpanan eksternal, yang mungkin
+lebih banyak akses dari yang dibutuhkan aplikasi Anda.</li>
+<li>Menggunakan
+<a href="{@docRoot}guide/topics/providers/document-provider.html">Storage
+Access Framework</a> biasanya membuat pengguna Anda memilih direktori
+melalui UI sistem, yang tidak diperlukan jika aplikasi Anda selalu mengakses
+direktori eksternal yang sama.</li>
+</ul>
+
+<p>Android N menyediakan API baru yang disederhanakan untuk mengakses
+direktori penyimpanan eksternal umum. </p>
+
+<h2 id="accessing">Mengakses Direktori Penyimpanan Eksternal</h2>
+
+<p>Gunakan kelas <code>StorageManager</code> untuk mendapatkan instance
+<code>StorageVolume</code> yang tepat. Kemudian, buat intent dengan memanggil metode
+<code>StorageVolume.createAccessIntent()</code> dari instance itu.
+Gunakan intent ini untuk mengakses direktori penyimpanan eksternal. Untuk mendapatkan daftar
+semua volume yang tersedia, termasuk volume media lepas-pasang, gunakan
+<code>StorageManager.getVolumesList()</code>.</p>
+
+<p>Jika Anda memiliki informasi tentang file spesifik, gunakan
+<code>StorageManager.getStorageVolume(File)</code> untuk mendapatkan
+<code>StorageVolume</code> yang berisi file tersebut. Panggil
+<code>createAccessIntent()</code> pada <code>StorageVolume</code> ini untuk mengakses
+direktori penyimpanan eksternal untuk file tersebut.</p>
+
+<p>
+Di volume kedua, seperti kartu SD eksternal, teruskan null saat memanggil
+<code>StorageVolume.createAccessIntent()</code> untuk meminta akses ke seluruh
+volume, sebagai ganti direktori spesifik.
+<code>StorageVolume.createAccessIntent()</code> akan mengembalikan null jika Anda meneruskan
+null ke volume utama, atau jika Anda meneruskan nama direktori yang tidak valid.
+</p>
+
+<p>Cuplikan kode berikut adalah contoh cara membuka direktori
+<code>Pictures</code> dalam penyimpanan bersama utama:</p>
+
+<pre>
+StorageManager sm = (StorageManager)getSystemService(Context.STORAGE_SERVICE);
+StorageVolume volume = sm.getPrimaryVolume();
+Intent intent = volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
+startActivityForResult(intent, request_code);
+</pre>
+
+<p>Sistem ini mencoba untuk memberikan akses ke direktori eksternal, dan jika
+diperlukan mengonfirmasi akses dengan pengguna menggunakan UI yang disederhanakan:</p>
+
+<img src="{@docRoot}images/android-7.0/scoped-directory-access-framed.png" srcset="{@docRoot}images/android-7.0/scoped-directory-access-framed.png 1x,
+{@docRoot}images/android-7.0/scoped-directory-access-framed_2x.png 2x" />
+<p class="img-caption"><strong>Gambar 1.</strong> Sebuah aplikasi yang meminta
+akses ke direktori Pictures.</p>
+
+<p>Jika pengguna memberi akses, sistem akan memanggil penggantian
+<code>onActivityResult()</code> Anda dengan kode hasil
+<code>Activity.RESULT_OK</code>, dan data intent yang berisi URI. Gunakan
+URI yang disediakan untuk mengakses informasi direktori, serupa dengan menggunakan URI
+yang dikembalikan oleh
+<a href="{@docRoot}guide/topics/providers/document-provider.html">Storage
+Access Framework</a>.</p>
+
+<p>Jika pengguna tidak memberi akses, sistem akan memanggil penggantian
+<code>onActivityResult()</code> Anda dengan kode hasil
+<code>Activity.RESULT_CANCELED</code>, dan data intent nol.</p>
+
+<p class="note"><b>Catatan</b>: Mendapatkan akses ke direktori eksternal tertentu
+juga akan memperoleh akses ke subdirektori dalam direktori tersebut.</p>
+
+<h2 id="removable">Mengakses Direktori pada Media Lepas-Pasang</h2>
+
+<p>Untuk menggunakan Scoped Directory Access guna mengakses direktori pada media lepas-pasang,
+pertama tambahkan {@link android.content.BroadcastReceiver} yang akan mendengarkan pemberitahuan
+{@link android.os.Environment#MEDIA_MOUNTED}, misalnya:</p>
+
+<pre>
+&lt;receiver
+    android:name=".MediaMountedReceiver"
+    android:enabled="true"
+    android:exported="true" &gt;
+    &lt;intent-filter&gt;
+        &lt;action android:name="android.intent.action.MEDIA_MOUNTED" /&gt;
+        &lt;data android:scheme="file" /&gt;
+    &lt;/intent-filter&gt;
+&lt;/receiver&gt;
+</pre>
+
+<p>Bila pengguna memasang media lepas-pasang, seperti kartu SD, sistem akan mengirimkan pemberitahuan
+{@link android.os.Environment#MEDIA_MOUNTED}. Pemberitahuan ini
+memberikan sebuah objek <code>StorageVolume</code> dalam data intent yang bisa
+Anda gunakan untuk mengakses direktori pada media lepas-pasang. Contoh berikut
+mengakses direktori <code>Pictures</code> pada media lepas-pasang:</p>
+
+<pre>
+// BroadcastReceiver has already cached the MEDIA_MOUNTED
+// notification Intent in mediaMountedIntent
+StorageVolume volume = (StorageVolume)
+    mediaMountedIntent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME);
+volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
+startActivityForResult(intent, request_code);
+</pre>
+
+<h2 id="best">Praktik Terbaik</h2>
+
+<p>Bila memungkinkan, pertahankan URI akses direktori eksternal sehingga Anda tidak perlu
+berulang kali meminta akses ke pengguna. Setelah pengguna memberikan akses, panggil
+<code>getContentResolver().takePersistableUriPermssion()</code> bersama
+URI akses direktori. Sistem akan mempertahankan URI dan permintaan
+akses berikutnya akan mengembalikan <code>RESULT_OK</code> dan tidak menampilkan UI konfirmasi kepada
+pengguna.</p>
+
+<p>Jika pengguna menolak akses ke direktori eksternal, jangan langsung
+meminta akses lagi. Berulang kali meminta akses akan menghasilkan pengalaman
+pengguna yang buruk. Jika permintaan ditolak oleh pengguna, dan aplikasi meminta akses
+lagi, UI akan menampilkan kotak centang <b>Don't ask again</b>:</p>
+
+<img src="{@docRoot}images/android-7.0/scoped-directory-access-dont-ask.png" srcset="{@docRoot}images/android-7.0/scoped-directory-access-dont-ask.png 1x,
+{@docRoot}images/android-7.0/scoped-directory-access-dont-ask_2x.png 2x" />
+<p class="img-caption"><strong>Gambar 1.</strong> Sebuah aplikasi membuat
+permintaan kedua untuk mengakses media lepas-pasang.</p>
+
+<p>Jika pengguna memilih <b>Don't ask again</b> dan menolak permintaan,
+semua permintaan berikutnya untuk direktori yang diberikan dari aplikasi
+Anda secara otomatis akan ditolak, dan tidak ada UI permintaan yang akan ditampilkan ke pengguna.</p>
\ No newline at end of file
diff --git a/docs/html-intl/intl/id/training/articles/security-config.jd b/docs/html-intl/intl/id/training/articles/security-config.jd
new file mode 100644
index 0000000..e13429d
--- /dev/null
+++ b/docs/html-intl/intl/id/training/articles/security-config.jd
@@ -0,0 +1,747 @@
+page.title=Konfigurasi Keamanan Jaringan
+page.keywords=androidn,keamanan,jaringan
+page.image=images/cards/card-nyc_2x.jpg
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>Dalam dokumen ini</h2>
+<ol>
+  <li><a href="#manifest">Menambahkan File Konfigurasi Keamanan</a></li>
+  <li><a href="#CustomTrust">Menyesuaikan CA Tepercaya</a>
+      <ol>
+      <li><a href="#ConfigCustom">Mengonfigurasi CA Tepercaya Khusus</a></li>
+      <li><a href="#LimitingCas">Membatasi Set CA Tepercaya</a></li>
+      <li><a href="#TrustingAdditionalCas">Mempercayai CA Tambahan</a></li>
+      </ol>
+  </li>
+  <li><a href="#TrustingDebugCa">CA Debug Saja</a></li>
+  <li><a href="#UsesCleartextTraffic">Berhenti dari Lalu Lintas Cleartext</a></li>
+  <li><a href="#CertificatePinning">Menyematkan Sertifikat</a></li>
+  <li><a href="#ConfigInheritance">Perilaku Pewarisan Konfigurasi</a></li>
+  <li><a href="#FileFormat">Format File Konfigurasi</a></li>
+</ol>
+</div>
+</div>
+
+
+<p>
+  Android N menyertakan fitur
+  Network Security Configuration yang memungkinkan aplikasi menyesuaikan setelan keamanan jaringan mereka dalam
+  file konfigurasi deklaratif yang aman tanpa memodifikasi kode aplikasi. Setelan ini bisa
+  dikonfigurasi untuk domain dan aplikasi tertentu. Kemampuan
+  utama fitur ini adalah sebagai berikut:
+</p>
+
+<ul>
+  <li>
+    <b>Trust-anchor khusus:</b> Menyesuaikan Certificate Authorities (CA) mana
+    yang dipercaya untuk koneksi aman aplikasi. Misalnya,
+    mempercayai sertifikat tertentu yang ditandatangani sendiri atau membatasi
+    set CA umum yang dipercaya aplikasi.
+  </li>
+
+  <li>
+    <b>Penggantian hanya-debug:</b> Men-debug secara aman koneksi aman dalam aplikasi
+    tanpa menambahkan risiko pada basis yang telah dipasang.
+  </li>
+
+  <li>
+    <b>Berhenti dari lalu lintas cleartext:</b> Melindungi aplikasi dari
+    penggunaan lalu lintas cleartext secara tidak sengaja.
+  </li>
+
+  <li>
+    <b>Penyematan sertifikat:</b> Membatasi koneksi aman aplikasi ke
+    sertifikat tertentu.
+  </li>
+</ul>
+
+
+<h2 id="manifest">Menambahkan File Konfigurasi Keamanan</h2>
+
+<p>
+  Fitur Network Security Configuration menggunakan file XML tempat Anda menetapkan
+  setelan untuk aplikasi. Anda harus menyertakan sebuah entri dalam manifes aplikasi
+  untuk menunjuk ke file ini. Kutipan kode berikut dari sebuah manifes
+  yang memperagakan cara membuat entri ini:
+</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;manifest ... &gt;
+  &lt;application ... &gt;
+    &lt;meta-data android:name="android.security.net.config"
+               android:resource="@xml/network_security_config" /&gt;
+    ...
+  &lt;/application&gt;
+&lt;/manifest&gt;
+</pre>
+
+<h2 id="CustomTrust">Menyesuaikan CA Tepercaya</h2>
+
+<p>
+  Aplikasi mungkin perlu mempercayai set CA khusus sebagai ganti default
+  platform. Alasannya yang paling umum adalah:
+</p>
+
+<ul>
+  <li>Menghubungkan ke host dengan otoritas sertifikat khusus (ditandatangani sendiri,
+  dikeluarkan oleh CA internal, dll).
+  </li>
+
+  <li>Membatasi set CA hanya untuk CA yang Anda percaya sebagai ganti setiap CA
+  yang sudah terpasang.
+  </li>
+
+  <li>Mempercayai CA tambahan yang tidak disertakan dalam sistem.
+  </li>
+</ul>
+
+<p>
+  Secara default koneksi (mis. TLS, HTTPS) aman dari semua aplikasi mempercayai
+  CA yang telah dipasang oleh sistem, dan aplikasi yang menargetkan API level 23
+  (Android M) ke bawah, juga mempercayai penyimpanan CA yang ditambahkan pengguna secara default. Aplikasi
+  bisa menyesuaikan koneksinya menggunakan {@code base-config} (untuk
+  penyesuaian lebar-aplikasi) atau {@code domain-config} (untuk penyesuaian
+  per-domain).
+</p>
+
+
+<h3 id="ConfigCustom">Mengonfigurasi CA Khusus</h3>
+
+<p>
+  Anggaplah Anda ingin menghubungkan ke host Anda yang menggunakan sertifikat
+  SSL yang ditandatangani sendiri atau ke host yang sertifikat SSL-nya dikeluarkan oleh CA non-publik
+  yang Anda percaya, seperti CA internal perusahaan Anda.
+</p>
+
+<p>
+  <code>res/xml/network_security_config.xml</code>:
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;network-security-config&gt;
+    &lt;domain-config&gt;
+        &lt;domain includeSubdomains="true"&gt;example.com&lt;/domain&gt;
+        &lt;trust-anchors&gt;
+            &lt;certificates src="@raw/my_ca"/&gt;
+        &lt;/trust-anchors&gt;
+    &lt;/domain-config&gt;
+&lt;/network-security-config&gt;
+</pre>
+</p>
+
+<p>
+  Menambahkan sertifikat CA yang ditandatangani sendiri atau sertifikat CA non-publik, dalam format PEM atau DER, ke
+  {@code res/raw/my_ca}.
+</p>
+
+
+<h3 id="LimitingCas">Membatasi Set CA Tepercaya</h3>
+
+<p>
+  Aplikasi yang tidak ingin mempercayai semua CA yang dipercaya oleh sistem
+  sebagai gantinya bisa menetapkan set CA sendiri yang telah dikurangi untuk dipercaya. Ini akan melindungi
+  aplikasi dari sertifikat palsu yang dikeluarkan oleh selain CA.
+</p>
+
+<p>
+  Konfigurasi untuk membatasi set CA tepercaya mirip dengan <a href="#TrustingACustomCa">mempercayai CA khusus</a> untuk domain tertentu selain
+  beberapa CA disediakan dalam sumber daya.
+</p>
+
+<p>
+<code>res/xml/network_security_config.xml</code>:
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;network-security-config&gt;
+    &lt;domain-config&gt;
+        &lt;domain includeSubdomains="true"&gt;secure.example.com&lt;/domain&gt;
+        &lt;domain includeSubdomains="true"&gt;cdn.example.com&lt;/domain&gt;
+        &lt;trust-anchors&gt;
+            &lt;certificates src="@raw/trusted_roots"/&gt;
+        &lt;/trust-anchors&gt;
+    &lt;/domain-config&gt;
+&lt;/network-security-config&gt;
+</pre>
+</p>
+
+<p>
+  Menambahkan CA tepercaya, dalam format PEM atau DER, ke {@code res/raw/trusted_roots}.
+  Perhatikan, jika menggunakan format PEM, file <em>hanya</em> boleh berisi data PEM
+  dan tidak ada teks tambahan. Anda juga bisa menyediakan beberapa elemen
+  <a href="#certificates"><code>&lt;certificates&gt;</code></a>
+sebagai ganti satu elemen.
+</p>
+
+
+<h3 id="TrustingAdditionalCas">
+  Mempercayai CA Tambahan
+</h3>
+
+<p>
+  Sebuah aplikasi mungkin perlu mempercayai CA tambahan yang tidak dipercaya oleh sistem,
+  hal ini bisa disebabkan karena sistem belum menyertakan CA atau CA tidak
+  memenuhi persyaratan untuk memasukkan ke dalam sistem Android. Aplikasi
+  bisa melakukannya dengan menetapkan beberapa sumber sertifikat untuk
+  konfigurasi.
+</p>
+<p>
+<code>res/xml/network_security_config.xml</code>:
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;network-security-config&gt;
+    &lt;base-config&gt;
+        &lt;trust-anchors&gt;
+            &lt;certificates src="@raw/extracas"/&gt;
+            &lt;certificates src="system"/&gt;
+        &lt;/trust-anchors&gt;
+    &lt;/base-config&gt;
+&lt;/network-security-config&gt;
+</pre>
+</p>
+
+
+<h2 id="TrustingDebugCa">Mengonfigurasi CA untuk Debug</h2>
+
+<p>
+  Saat men-debug aplikasi yang terhubung melalui HTTPS, Anda mungkin perlu
+  menghubungkan ke server pengembangan lokal, yang tidak memiliki sertifikat
+  SSL untuk server produksi Anda. Untuk mendukungnya tanpa
+  memodifikasi kode aplikasi, Anda bisa menetapkan CA hanya-debug
+  yang <i>hanya</i> dipercaya bila <a href="{@docRoot}guide/topics/manifest/application-element.html#debug">
+android:debuggable</a>
+  adalah {@code true} dengan menggunakan {@code debug-overrides}. Biasanya IDE dan alat
+  build menyetel flag ini secara otomatis untuk build non-rilis.
+</p>
+
+<p>
+  Ini lebih aman daripada kode kondisional biasa karena, sebagai tindakan
+  pencegahan keamanan, toko aplikasi tidak menerima aplikasi yang ditandai
+  bisa-di-debug.
+</p>
+
+<p>
+<code>res/xml/network_security_config.xml</code>:
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;network-security-config&gt;
+    &lt;debug-overrides&gt;
+        &lt;trust-anchors&gt;
+            &lt;certificates src="@raw/debug_cas"/&gt;
+        &lt;/trust-anchors&gt;
+    &lt;/debug-overrides&gt;
+&lt;/network-security-config&gt;
+</pre>
+</p>
+
+
+<h2 id="UsesCleartextTraffic">Berhenti dari Lalu Lintas Cleartext</h2>
+
+<p>
+  Aplikasi bermaksud menyambung ke tujuan hanya menggunakan koneksi
+ aman dapat memilih keluar dari dukungan cleartext (menggunakan protokol
+ HTTP yang tidak terenkripsi sebagai ganti HTTPS) ke tujuan tersebut. Opsi ini akan membantu mencegah
+  regresi tidak disengaja dalam aplikasi karena perubahan dalam URL yang disediakan oleh sumber-sumber
+  eksternal seperti server backend.
+  Lihat {@link android.security.NetworkSecurityPolicy#isCleartextTrafficPermitted
+  NetworkSecurityPolicy.isCleartextTrafficPermitted()} untuk detail selengkapnya.
+</p>
+
+<p>
+  Misalnya, aplikasi mungkin ingin memastikan semua koneksi ke {@code
+  secure.example.com} selalu dilakukan melalui HTTPS untuk melindungi lalu lintas sensitif
+  dari jaringan yang berbahaya.
+</p>
+
+<p>
+<code>res/xml/network_security_config.xml</code>:
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;network-security-config&gt;
+    &lt;domain-config usesCleartextTraffic="false"&gt;
+        &lt;domain includeSubdomains="true"&gt;secure.example.com&lt;/domain&gt;
+    &lt;/domain-config&gt;
+&lt;/network-security-config&gt;
+</pre>
+</p>
+
+
+<h2 id="CertificatePinning">Menyematkan Sertifikat</h2>
+
+<p>
+  Biasanya aplikasi mempercayai semua CA yang telah terpasang. Jika salah satu dari CA ini
+  mengeluarkan sertifikat palsu, aplikasi akan berisiko terkena serangan
+  MiTM. Beberapa aplikasi memilih untuk membatasi set sertifikat yang mereka terima
+  baik dengan membatasi set CA yang mereka percaya atau dengan menyematkan sertifikat.
+</p>
+
+<p>
+  Penyematan sertifikat dilakukan dengan memberikan seperangkat sertifikat dengan hash
+  kunci publik (SubjectPublicKeyInfo pada sertifikat X.509). Rantai
+  sertifikat nanti hanya berlaku jika rantai sertifikat berisi setidaknya salah satu
+  dari kunci publik yang disematkan.
+</p>
+
+<p>
+  Perhatikan, saat menggunakan penyematan sertifikat, Anda harus selalu menyertakan kunci
+  cadangan sehingga jika Anda terpaksa beralih ke kunci baru, atau mengubah CA (saat
+  menyematkan ke sertifikat CA atau perantara CA tersebut), konektivitas
+  aplikasi Anda tidak terpengaruh. Jika tidak, Anda harus mendorong
+  pembaruan ke aplikasi tersebut untuk memulihkan konektivitas.
+</p>
+
+<p>
+  Selain itu dimungkinkan juga menyetel waktu habis masa berlaku untuk pin setelah
+  penyematan tidak dilakukan. Hal ini membantu mencegah masalah konektivitas dalam
+  aplikasi yang belum diperbarui. Akan tetapi, menyetel waktu kedaluwarsa
+  pada pin mungkin akan membuat penyematan bisa diabaikan.
+</p>
+
+<p>
+<code>res/xml/network_security_config.xml</code>:
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;network-security-config&gt;
+    &lt;domain-config&gt;
+        &lt;domain includeSubdomains="true"&gt;example.com&lt;/domain&gt;
+        &lt;pin-set expiration="2018-01-01"&gt;
+            &lt;pin digest="SHA-256"&gt;7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=&lt;/pin&gt;
+            &lt;!-- backup pin --&gt
+            &lt;pin digest="SHA-256"&gt;fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=&lt;/pin&gt;
+        &lt;/pin-set&gt;
+    &lt;/domain-config&gt;
+&lt;/network-security-config&gt;
+</pre>
+</p>
+
+
+<h2 id="ConfigInheritance">Perilaku Pewarisan Konfigurasi</h2>
+
+<p>
+  Nilai yang tidak disetel dalam konfigurasi tertentu akan diwariskan. Perilaku ini memungkinkan konfigurasi
+  yang lebih kompleks sambil menjaga file konfigurasi tetap terbaca.
+</p>
+
+<p>
+  Jika nilai tidak disetel dalam entri tertentu maka nilai dari entri berikutnya yang lebih
+  umum akan digunakan. Nilai yang tidak disetel dalam {@code domain-config} akan
+  diambil dari {@code domain-config} induk, jika tersarang, atau dari {@code
+  base-config} jika tidak. Nilai yang tidak disetel dalam {@code base-config} akan menggunakan
+  nilai default platform.
+</p>
+
+<p>
+  Misalnya pertimbangkan, bila semua koneksi ke subdomain {@code
+  example.com} harus menggunakan set CA khusus. Selain itu, lalu lintas cleartext ke
+  domain ini diizinkan <em>kecuali</em> saat menghubungkan ke {@code
+  secure.example.com}. Dengan menyarangkan konfigurasi untuk {@code
+  secure.example.com} dalam konfigurasi untuk {@code example.com},
+  {@code trust-anchors} tidak perlu digandakan.
+</p>
+
+<p>
+<code>res/xml/network_security_config.xml</code>:
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;network-security-config&gt;
+    &lt;domain-config&gt;
+        &lt;domain includeSubdomains="true"&gt;example.com&lt;/domain&gt;
+        &lt;trust-anchors&gt;
+            &lt;certificates src="@raw/my_ca"/&gt;
+        &lt;/trust-anchors&gt;
+        &lt;domain-config cleartextTrafficPermitted="false"&gt;
+            &lt;domain includeSubdomains="true"&gt;secure.example.com&lt;/domain&gt;
+        &lt;/domain-config&gt;
+    &lt;/domain-config&gt;
+&lt;/network-security-config&gt;
+</pre>
+</p>
+
+
+<h2 id="FileFormat">Format File Konfigurasi</h2>
+
+<p>
+  Fitur Network Security Configuration menggunakan format file XML.
+  Struktur keseluruhan file ditampilkan dalam contoh kode berikut:
+</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;network-security-config&gt;
+    &lt;base-config&gt;
+        &lt;trust-anchors&gt;
+            &lt;certificates src="..."/&gt;
+            ...
+        &lt;/trust-anchors&gt;
+    &lt;/base-config&gt;
+
+    &lt;domain-config&gt;
+        &lt;domain&gt;android.com&lt;/domain&gt;
+        ...
+        &lt;trust-anchors&gt;
+            &lt;certificates src="..."/&gt;
+            ...
+        &lt;/trust-anchors&gt;
+        &lt;pin-set&gt;
+            &lt;pin digest="..."&gt;...&lt;/pin&gt;
+            ...
+        &lt;/pin-set&gt;
+    &lt;/domain-config&gt;
+    ...
+    &lt;debug-overrides&gt;
+        &lt;trust-anchors&gt;
+            &lt;certificates src="..."/&gt;
+            ...
+        &lt;/trust-anchors&gt;
+    &lt;/debug-overrides&gt;
+&lt;/network-security-config&gt;
+</pre>
+
+<p>
+  Bagian berikut menjelaskan sintaks dan detail lainnya dari format
+  file.
+</p>
+
+<h3 id="network-security-config">
+  &lt;network-security-config&gt;
+</h3>
+
+<dl class="xml">
+  <dt>
+    bisa berisi:
+  </dt>
+
+  <dd>
+    0 atau 1 <code><a href="#base-config">&lt;base-config&gt;</a></code><br>
+    Sejumlah <code><a href=
+    "#domain-config">&lt;domain-config&gt;</a></code><br>
+    0 atau 1 <code><a href="#debug-overrides">&lt;debug-overrides&gt;</a></code>
+  </dd>
+</dl>
+
+<h3 id="base-config">
+  &lt;base-config&gt;
+</h3>
+
+<dl class="xml">
+  <dt>
+    sintaks:
+  </dt>
+</dl>
+
+<pre class="stx">
+&lt;base-config <a href=
+"#usesCleartextTraffic">usesCleartextTraffic</a>=["true" | "false"]&gt;
+    ...
+&lt;/base-config&gt;
+</pre>
+<dl class="xml">
+  <dt>
+    bisa berisi:
+  </dt>
+
+  <dd>
+    <code><a href="#trust-anchors">&lt;trust-anchors&gt;</a></code>
+  </dd>
+
+  <dt>
+    keterangan:
+  </dt>
+
+  <dd>
+    Konfigurasi default yang digunakan oleh semua koneksi yang tujuannya tidak
+    tercakup oleh <a href="#domain-config"><code>domain-config</code></a>.
+
+<p>
+  Nilai yang tidak disetel akan menggunakan nilai default platform. Konfigurasi
+  default untuk aplikasi yang menargetkan API level 24 ke atas:
+</p>
+
+<pre>
+&lt;base-config usesCleartextTraffic="true"&gt;
+    &lt;trust-anchors&gt;
+        &lt;certificates src="system" /&gt;
+    &lt;/trust-anchors&gt;
+&lt;/base-config&gt;
+</pre>
+Konfigurasi default untuk aplikasi yang menargetkan API level 23 ke bawah:
+<pre>
+&lt;base-config usesCleartextTraffic="true"&gt;
+    &lt;trust-anchors&gt;
+        &lt;certificates src="system" /&gt;
+        &lt;certificates src="user" /&gt;
+    &lt;/trust-anchors&gt;
+&lt;/base-config&gt;
+</pre>
+
+  </dd>
+</dl>
+
+<h3 id="domain-config">&lt;domain-config&gt;</h3>
+<dl class="xml">
+<dt>sintaks:</dt>
+<dd>
+<pre class="stx">&lt;domain-config <a href="#usesCleartextTraffic">usesCleartextTraffic</a>=["true" | "false"]&gt;
+    ...
+&lt;/domain-config&gt;</pre>
+</dd>
+
+<dt>Bisa Berisi:</dt>
+
+<dd>
+1 atau beberapa <code><a href="#domain">&lt;domain&gt;</a></code>
+<br/>0 atau 1 <code><a href="#trust-anchors">&lt;trust-anchors&gt;</a></code>
+<br/>0 atau 1 <code><a href="#pin-set">&lt;pin-set&gt;</code></a>
+<br/>Sejumlah <code>&lt;domain-config&gt;</code> tersarang</dd>
+
+<dt>Keterangan</dt>
+<dd>Konfigurasi yang digunakan untuk koneksi ke tujuan tertentu seperti didefinisikan oleh elemen {@code domain}.
+
+<p>Perhatikan, jika beberapa elemen {@code domain-config} mencakup suatu tujuan, konfigurasi dengan aturan domain paling spesifik (terpanjang) yang cocok
+akan digunakan.</p></dd>
+</dl>
+
+
+<h3 id="domain">&lt;domain&gt;</h3>
+
+<dl class="xml">
+  <dt>
+    sintaks:
+  </dt>
+
+  <dd>
+    <pre class="stx">
+&lt;domain includeSubdomains=["true" | "false"]&gt;example.com&lt;/domain&gt;
+</pre>
+  </dd>
+
+  <dt>
+    Atribut:
+  </dt>
+
+  <dd>
+    <dl class="attr">
+      <dt>
+        {@code includeSubdomains}
+      </dt>
+
+      <dd>
+        Jika {@code "true"} maka aturan domain ini akan dicocokkan dengan domain dan semua
+        subdomain, termasuk subdomain dari subdomain, jika tidak peraturan hanya
+        diterapkan pada kecocokan yang persis tepat.
+      </dd>
+    </dl>
+  </dd>
+
+  <dt>
+    Keterangan:
+  </dt>
+</dl>
+
+<h3 id="debug-overrides">&lt;debug-overrides&gt;</h3>
+
+<dl class="xml">
+  <dt>
+    sintaks:
+  </dt>
+
+  <dd>
+    <pre class="stx">
+&lt;debug-overrides&gt;
+    ...
+&lt;/debug-overrides&gt;
+</pre>
+  </dd>
+
+  <dt>
+    Bisa Berisi:
+  </dt>
+
+  <dd>
+    0 atau 1 <code><a href="#trust-anchors">&lt;trust-anchors&gt;</a></code>
+  </dd>
+
+  <dt>
+    Keterangan:
+  </dt>
+
+  <dd>
+    Pengesampingan yang akan diterapkan bila <a href="{@docRoot}guide/topics/manifest/application-element.html#debug">android:debuggable</a>
+    adalah {@code "true"} yang biasanya terjadi untuk build non-rilis
+    yang dihasilkan oleh alat IDE dan build. Trust-anchor yang ditetapkan dalam {@code
+    debug-overrides} akan ditambahkan ke semua konfigurasi lainnya dan penyematan
+    sertifikat tidak dilakukan bila rantai sertifikat server menggunakan satu dari
+    trust-anchor hanya-debug ini. Jika <a href="{@docRoot}guide/topics/manifest/application-element.html#debug">android:debuggable</a>
+    adalah {@code "false"} maka bagian ini akan diabaikan sepenuhnya.
+  </dd>
+</dl>
+
+<h3 id="trust-anchors">&lt;trust-anchors&gt;</h3>
+<dl class="xml">
+  <dt>
+    sintaks:
+  </dt>
+
+  <dd>
+    <pre class="stx">
+&lt;trust-anchors&gt;
+...
+&lt;/trust-anchors&gt;
+</pre>
+  </dd>
+
+  <dt>
+    Bisa Berisi:
+  </dt>
+
+  <dd>
+    Sejumlah <code><a href="#certificates">&lt;certificates&gt;</a></code>
+  </dd>
+
+  <dt>
+    Keterangan:
+  </dt>
+
+  <dd>
+    Set trust-anchor untuk koneksi aman.
+  </dd>
+</dl>
+
+
+<h3 id="certificates">&lt;certificates&gt;</h3>
+<dl class="xml">
+<dt>sintaks:</dt>
+<dd><pre class="stx">&lt;certificates src=["system" | "user" | "<i>raw resource</i>"]
+              overridePins=["true" | "false"] /&gt;
+</pre></dd>
+<dt>keterangan:</dt>
+<dd>Set sertifikat X.509 untuk elemen {@code trust-anchors}.</dd>
+
+<dt>atribut:</dt>
+<dd><dl class="attr">
+<dt>{@code src}</dt>
+<dd>
+Sumber sertifikat CA, bisa salah satu dari
+<ul>
+  <li>ID sumber daya mentah yang menunjuk ke file berisi sertifikat X.509.
+  Sertifikat harus dikodekan dalam format DER atau PEM. Dalam hal sertifikat
+  PEM, file <em>tidak boleh</em> berisi data tambahan non-PEM seperti
+  komentar.
+  </li>
+
+  <li>{@code "system"} untuk sertifikat CA sistem yang telah terpasang.
+  </li>
+
+  <li>{@code "user"} untuk sertifikat CA yang ditambahkan pengguna.
+  </li>
+</ul>
+</dd>
+
+<dt>{@code overridePins}</dt>
+<dd>
+  <p>
+    Menetapkan apakah CA dari sumber akan mengabaikan penyematan sertifikat. Jika {@code
+    "true"} kemudian rangkaian sertifikat melalui salah satu CA dari
+    sumber ini maka tidak dilakukan penyematan. Hal ini bisa berguna untuk debug CA
+    atau untuk mendukung dengan memungkinkan pengguna melakukan MiTM atas lalu lintas aman aplikasi Anda.
+  </p>
+
+  <p>
+    Default-nya adalah {@code "false"} kecuali jika ditetapkan dalam elemen {@code debug-overrides},
+    dalam hal demikian default-nya adalah {@code "true"}.
+  </p>
+</dd>
+</dl>
+</dd>
+
+
+<h3 id="pin-set">&lt;pin-set&gt;</h3>
+
+<dl class="xml">
+  <dt>
+    sintaks:
+  </dt>
+
+  <dd>
+<pre class="stx">
+&lt;pin-set expiration="date"&gt;
+...
+&lt;/pin-set&gt;
+</pre>
+  </dd>
+
+  <dt>
+    Bisa Berisi:
+  </dt>
+
+  <dd>
+    Sejumlah <code><a href="#pin">&lt;pin&gt;</a></code>
+  </dd>
+
+  <dt>
+    Keterangan:
+  </dt>
+
+  <dd>
+    Satu set pin kunci publik. Agar koneksi aman bisa dipercaya, salah satu
+    kunci publik dalam rantai kepercayaan harus berada dalam set pin. Lihat
+    <code><a href="#pin">&lt;pin&gt;</a></code> untuk mengetahui format pin.
+  </dd>
+
+  <dt>
+    Atribut:
+  </dt>
+
+  <dd>
+    <dl class="attr">
+      <dt>
+        {@code expiration}
+      </dt>
+
+      <dd>
+        Tanggal, dalam format {@code yyyy-MM-dd}, pada saat dan setelah pin
+        kedaluwarsa, sehingga menonaktifkan penyematan. Jika atribut tidak disetel maka
+        pin tidak kedaluwarsa.
+        <p>
+          Tanggal kedaluwarsa membantu mencegah masalah konektivitas di aplikasi yang
+          tidak mengambil pembaruan untuk set pin mereka, misalnya karena pengguna
+          menonaktifkan pembaruan aplikasi.
+        </p>
+      </dd>
+    </dl>
+  </dd>
+</dl>
+
+<h3 id="pin">&lt;pin&gt;</h3>
+<dl class="xml">
+  <dt>
+    sintaks:
+  </dt>
+
+  <dd>
+<pre class="stx">
+&lt;pin digest=["SHA-256"]&gt;base64 encoded digest of X.509
+    SubjectPublicKeyInfo (SPKI)&lt;/pin&gt;
+</pre>
+  </dd>
+
+  <dt>
+    Atribut:
+  </dt>
+
+  <dd>
+    <dl class="attr">
+      <dt>
+        {@code digest}
+      </dt>
+
+      <dd>
+        Algoritme intisari yang digunakan untuk menghasilkan pin. Saat ini, hanya
+        {@code "SHA-256"} yang didukung.
+      </dd>
+    </dl>
+  </dd>
+</dl>
diff --git a/docs/html-intl/intl/id/training/basics/network-ops/data-saver.jd b/docs/html-intl/intl/id/training/basics/network-ops/data-saver.jd
new file mode 100644
index 0000000..abd4e43
--- /dev/null
+++ b/docs/html-intl/intl/id/training/basics/network-ops/data-saver.jd
@@ -0,0 +1,234 @@
+page.title=Data Saver
+metaDescription=Optimalisasi penggunaan data yang diaktifkan pengguna.
+page.keywords="android N", "data usage", "metered network"
+page.image=images/cards/card-nyc_2x.jpg
+@jd:body
+
+<div id="tb-wrapper">
+  <div id="tb">
+    <h2>
+      Dalam dokumen ini
+    </h2>
+
+    <ol>
+      <li>
+        <a href="#status">Memeriksa Preferensi Data Saver</a>
+        <ol>
+          <li>
+            <a href="#request-whitelist">Meminta izin daftar putih</a>
+          </li>
+        </ol>
+      </li>
+
+      <li>
+        <a href="#monitor-changes">Memantau Perubahan pada Preferensi
+        Data Saver</a>
+      </li>
+
+      <li>
+        <a href="#testing">Menguji dengan Perintah Android Debug Bridge</a>
+      </li>
+    </ol>
+  </div>
+</div>
+
+<p>
+  Selama penggunaan ponsel cerdas, biaya paket data seluler bisa saja
+  melebihi harga perangkat itu sendiri. Di N Developer Preview, pengguna bisa
+  mengaktifkan Data Saver berdasarkan lingkup perangkat untuk menghemat data, baik saat
+  roaming, mendekati akhir siklus penagihan, atau pada paket data prabayar kecil.
+</p>
+
+<p>
+  Bila pengguna mengaktifkan Data Saver di <strong>Settings</strong> dan perangkat
+  berada dalam jaringan berkuota, sistem akan memblokir penggunaan data latar belakang dan memberi tahu
+  aplikasi untuk menghemat penggunaan data latar depan bila memungkinkan. Pengguna bisa
+  memasukkan aplikasi tertentu ke daftar putih untuk memungkinkan penggunaan data berkuota bila Data
+  Saver diaktifkan.
+</p>
+
+<p>
+  N Developer Preview memperluas {@link android.net.ConnectivityManager}
+  API untuk menyediakan cara pada aplikasi untuk <a href="#status">menerima preferensi Data Saver
+  pengguna</a> dan <a href="#monitor-changes">memantau perubahan
+  preferensi</a>. Hal ini dianggap praktik terbaik bagi aplikasi untuk memeriksa apakah
+  pengguna telah mengaktifkan DataSaver dan berusaha membatasi penggunaan data latar depan dan
+  data latar belakang.
+</p>
+
+<h2 id="status">
+  Memeriksa Preferensi Data Saver
+</h2>
+
+<p>
+  Di N Developer Preview, aplikasi bisa menggunakan {@link
+  android.net.ConnectivityManager} API untuk menentukan pembatasan penggunaan data
+  apa yang sedang diterapkan. Metode {@code getRestrictBackgroundStatus()}
+  akan mengembalikan salah satu dari nilai berikut:
+</p>
+
+<dl>
+  <dt>
+    {@code RESTRICT_BACKGROUND_STATUS_DISABLED}
+  </dt>
+
+  <dd>
+    Data Saver dinonaktifkan.
+  </dd>
+
+  <dt>
+    {@code RESTRICT_BACKGROUND_STATUS_ENABLED}
+  </dt>
+
+  <dd>
+    Pengguna telah mengaktifkan Data Saver untuk aplikasi ini. Aplikasi harus berusaha membatasi
+    penggunaan data di latar depan dan dengan halus menangani pembatasan penggunaan
+    data latar belakang.
+  </dd>
+
+  <dt>
+    {@code RESTRICT_BACKGROUND_STATUS_WHITELISTED}
+  </dt>
+
+  <dd>
+    Pengguna telah mengaktifkan Data Saver namun aplikasi telah dimasukkan dalam daftar putih. Aplikasi harus
+    tetap berusaha membatasi penggunaan data latar belakang dan latar depan.
+  </dd>
+</dl>
+
+<p>
+  Hal ini dianggap praktik terbaik untuk membatasi penggunaan data bila perangkat
+  terhubung ke jaringan berkuota, meskipun Data Saver telah dinonaktifkan atau aplikasi
+  telah dimasukkan dalam daftar putih. Kode contoh berikut menggunakan {@link
+  android.net.ConnectivityManager#isActiveNetworkMetered
+  ConnectivityManager.isActiveNetworkMetered()} dan {@code
+  ConnectivityManager.getRestrictBackgroundStatus()} untuk menentukan berapa banyak data
+  yang harus digunakan aplikasi:
+</p>
+
+<pre>
+ConnectivityManager connMgr = (ConnectivityManager)
+        getSystemService(Context.CONNECTIVITY_SERVICE);
+// Checks if the device is on a metered network
+if (connMgr.isActiveNetworkMetered()) {
+  // Checks user’s Data Saver settings.
+  switch (connMgr.getRestrictBackgroundStatus()) {
+    case RESTRICT_BACKGROUND_STATUS_ENABLED:
+    // Background data usage is blocked for this app. Wherever possible,
+    // the app should also use less data in the foreground.
+
+    case RESTRICT_BACKGROUND_STATUS_WHITELISTED:
+    // The app is whitelisted. Wherever possible,
+    // the app should use less data in the foreground and background.
+
+    case RESTRICT_BACKGROUND_STATUS_DISABLED:
+    // Data Saver is disabled. Since the device is connected to a
+    // metered network, the app should use less data wherever possible.
+  }
+} else {
+  // The device is not on a metered network.
+  // Use data as required to perform syncs, downloads, and updates.
+}
+</pre>
+
+<h3 id="request-whitelist">
+  Meminta izin daftar putih
+</h3>
+
+<p>
+  Jika aplikasi Anda perlu menggunakan data di latar belakang, aplikasi bisa meminta izin
+  daftar putih dengan mengirim
+  <code>Settings.ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS</code>
+  yang mengandung URI dari nama paket aplikasi Anda: misalnya,
+  <code>package:MY_APP_ID</code>.
+</p>
+
+<p>
+  Mengirim intent dan URI akan membuka aplikasi <strong>Settings</strong> dan
+  menampilkan setelan penggunaan data untuk aplikasi Anda. Pengguna nanti bisa memutuskan apakah akan
+  mengaktifkan data latar belakang untuk aplikasi Anda. Sebelum Anda mengirim intent ini, sebaiknya
+  tanyakan kepada pengguna terlebih dahulu apakah mereka ingin membuka aplikasi
+  <strong>Settings</strong> untuk keperluan mengaktifkan penggunaan
+  data latar belakang.
+</p>
+
+<h2 id="monitor-changes">
+  Memantau Perubahan pada Preferensi Data Saver
+</h2>
+
+<p>
+  Aplikasi bisa memantau perubahan pada preferensi Data Saver dengan membuat {@link
+  android.content.BroadcastReceiver} untuk memantau {@code
+  ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED} dan secara dinamis
+  mendaftarkan penerima pada {@link android.content.Context#registerReceiver
+  Context.registerReceiver()}. Bila menerima siaran ini, aplikasi harus
+  <a href="#status">memeriksa apakah preferensi Data Saver baru memengaruhi
+  izinnya</a> dengan memanggil {@code
+  ConnectivityManager.getRestrictBackgroundStatus()}.
+</p>
+
+<p class="note">
+  <strong>Catatan:</strong> Sistem hanya mengirim siaran ini ke aplikasi yang
+  secara dinamis mendaftar padanya dengan {@link
+  android.content.Context#registerReceiver Context.registerReceiver()}. Aplikasi
+  yang mendaftar untuk menerima siaran ini dalam manifes mereka
+  tidak akan menerimanya.
+</p>
+
+<h2 id="testing">
+  Menguji dengan Perintah Android Debug Bridge
+</h2>
+
+<a href="{@docRoot}tools/help/adb.html">Android Debug Bridge (ADB)</a>
+menyediakan beberapa perintah yang bisa Anda gunakan untuk memeriksa dan
+mengonfigurasi izin jaringan:
+
+<dl>
+  <dt>
+    <code>$ adb shell dumpsys netpolicy</code>
+  </dt>
+
+  <dd>
+    Menghasilkan laporan berisi setelan pembatasan jaringan latar belakang
+    global saat ini, UID paket saat ini di daftar putih, dan izin jaringan
+    untuk paket yang diketahui lainnya.
+  </dd>
+
+  <dt>
+    <code>$ adb shell cmd netpolicy</code>
+  </dt>
+
+  <dd>
+    Menampilkan daftar lengkap dari perintah Network Policy Manager (netpolicy).
+  </dd>
+
+  <dt>
+    <code>$ adb shell cmd netpolicy set restrict-background
+    &lt;boolean&gt;</code>
+  </dt>
+
+  <dd>
+    Mengaktifkan atau menonaktifkan mode Data Saver saat meneruskan <code>true</code> atau
+ <code>false</code>, masing-masing.
+  </dd>
+
+  <dt>
+    <code>$ adb shell cmd netpolicy add restrict-background-whitelist
+    &lt;UID&gt;</code>
+  </dt>
+
+  <dd>
+    Menambahkan UID paket tertentu ke daftar putih untuk mengizinkan penggunaan data berkuota
+  di latar belakang.
+  </dd>
+
+  <dt>
+    <code>$ adb shell cmd netpolicy remove restrict-background-whitelist
+    &lt;UID&gt;</code>
+  </dt>
+
+  <dd>
+    Membuang UID paket tertentu dari daftar putih untuk memblokir
+    penggunaan data berkuota di latar belakang saat Data Saver diaktifkan.
+  </dd>
+</dl>
diff --git a/docs/html-intl/intl/id/training/material/animations.jd b/docs/html-intl/intl/id/training/material/animations.jd
new file mode 100644
index 0000000..e57a03f
--- /dev/null
+++ b/docs/html-intl/intl/id/training/material/animations.jd
@@ -0,0 +1,550 @@
+page.title=Mendefinisikan Animasi Custom
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>Pelajaran ini mengajarkan Anda cara</h2>
+<ol>
+  <li><a href="#Touch">Menyesuaikan Umpan Balik Sentuh</a></li>
+  <li><a href="#Reveal">Menggunakan Reveal Effect</a></li>
+  <li><a href="#Transitions">Menyesuaikan Transisi Aktivitas</a></li>
+  <li><a href="#ViewState">Menganimasikan Perubahan Status Tampilan</a></li>
+  <li><a href="#AnimVector">Menganimasikan Drawable Vektor</a></li>
+</ol>
+<h2>Anda juga harus membaca</h2>
+<ul>
+  <li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
+  <li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
+</ul>
+</div>
+</div>
+
+
+<p>Animasi dalam desain bahan memberi pengguna umpan balik tentang tindakannya dan menyediakan
+kesinambungan visual saat pengguna berinteraksi dengan aplikasi Anda. Tema bahan menyediakan beberapa animasi default
+untuk tombol dan transisi aktivitas, dan Android 5.0 (API level 21) ke atas memungkinkan Anda menyesuaikan
+animasi ini dan membuat yang baru:</p>
+
+<ul>
+<li>Umpan balik sentuh</li>
+<li>Singkap Melingkar</li>
+<li>Transisi aktivitas</li>
+<li>Gerakan melengkung</li>
+<li>Perubahan status tampilan</li>
+</ul>
+
+
+<h2 id="Touch">Menyesuaikan Umpan Balik Sentuh</h2>
+
+<p>Umpan balik sentuh dalam desain bahan menyediakan konfirmasi visual seketika pada
+titik kontak bila pengguna berinteraksi dengan elemen UI. Animasi umpan balik sentuh default
+untuk tombol menggunakan kelas {@link android.graphics.drawable.RippleDrawable} baru, yang bertransisi
+di antara berbagai status dengan efek riak.</p>
+
+<p>Di sebagian besar kasus, Anda harus menerapkan fungsionalitas ini dalam XML tampilan dengan menetapkan
+latar belakang tampilan sebagai:</p>
+
+<ul>
+<li><code>?android:attr/selectableItemBackground</code> untuk riak berbatas.</li>
+<li><code>?android:attr/selectableItemBackgroundBorderless</code> untuk riak yang meluas ke luar
+tampilan. Latar belakang ini akan digambar di atas, dan dibatasi oleh, induk tampilan terdekat dengan
+latar belakang non-null.</li>
+</ul>
+
+<p class="note"><strong>Catatan:</strong> <code>selectableItemBackgroundBorderless</code> adalah
+atribut baru yang diperkenalkan di API level 21.</p>
+
+
+<p>Atau, Anda bisa mendefinisikan {@link android.graphics.drawable.RippleDrawable}
+sebagai sumber daya XML dengan menggunakan elemen <code>ripple</code>.</p>
+
+<p>Anda bisa menetapkan warna ke objek-objek {@link android.graphics.drawable.RippleDrawable}. Untuk mengubah
+warna default umpan balik sentuh, gunakan atribut <code>android:colorControlHighlight</code>
+tema.</p>
+
+<p>Untuk informasi selengkapnya, lihat referensi API bagi kelas {@link
+android.graphics.drawable.RippleDrawable}.</p>
+
+
+<h2 id="Reveal">Menggunakan Reveal Effect</h2>
+
+<p>Animasi singkap memberi pengguna kesinambungan visual saat menampilkan atau menyembunyikan sekelompok
+elemen UI. Metode {@link android.view.ViewAnimationUtils#createCircularReveal
+ViewAnimationUtils.createCircularReveal()} memungkinkan Anda menganimasikan lingkaran terpangkas
+untuk memperlihatkan atau menyembunyikan tampilan.</p>
+
+<p>Untuk memperlihatkan tampilan yang sebelumnya tidak terlihat dengan menggunakan efek ini:</p>
+
+<pre>
+// previously invisible view
+View myView = findViewById(R.id.my_view);
+
+// get the center for the clipping circle
+int cx = (myView.getLeft() + myView.getRight()) / 2;
+int cy = (myView.getTop() + myView.getBottom()) / 2;
+
+// get the final radius for the clipping circle
+int finalRadius = Math.max(myView.getWidth(), myView.getHeight());
+
+// create the animator for this view (the start radius is zero)
+Animator anim =
+    ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
+
+// make the view visible and start the animation
+myView.setVisibility(View.VISIBLE);
+anim.start();
+</pre>
+
+<p>Untuk menyembunyikan sebuah tampilan yang sebelumnya terlihat dengan menggunakan efek ini:</p>
+
+<pre>
+// previously visible view
+final View myView = findViewById(R.id.my_view);
+
+// get the center for the clipping circle
+int cx = (myView.getLeft() + myView.getRight()) / 2;
+int cy = (myView.getTop() + myView.getBottom()) / 2;
+
+// get the initial radius for the clipping circle
+int initialRadius = myView.getWidth();
+
+// create the animation (the final radius is zero)
+Animator anim =
+    ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);
+
+// make the view invisible when the animation is done
+anim.addListener(new AnimatorListenerAdapter() {
+    &#64;Override
+    public void onAnimationEnd(Animator animation) {
+        super.onAnimationEnd(animation);
+        myView.setVisibility(View.INVISIBLE);
+    }
+});
+
+// start the animation
+anim.start();
+</pre>
+
+
+<h2 id="Transitions">Menyesuaikan Transisi Aktivitas</h2>
+
+<!-- shared transition video -->
+<div style="width:290px;margin-left:35px;float:right">
+  <div class="framed-nexus5-port-span-5">
+  <video class="play-on-hover" autoplay="">
+    <source src="{@docRoot}design/material/videos/ContactsAnim.mp4">
+    <source src="{@docRoot}design/material/videos/ContactsAnim.webm">
+    <source src="{@docRoot}design/material/videos/ContactsAnim.ogv">
+  </video>
+  </div>
+  <div style="font-size:10pt;margin-left:20px;margin-bottom:30px">
+    <p class="img-caption" style="margin-top:3px;margin-bottom:10px"><strong>Gambar 1</strong> - Transisi
+    dengan elemen bersama.</p>
+    <em>Untuk memutar ulang film, klik layar perangkat</em>
+  </div>
+</div>
+
+<p>Transisi aktivitas dalam aplikasi desain bahan memberikan koneksi visual antar berbagai status
+melalui gerakan dan transformasi di antara elemen umum. Anda bisa menetapkan animasi custom untuk
+masuk ke dan keluar dari transisi dan untuk transisi elemen bersama di antara aktivitas.</p>
+
+<ul>
+<li>Transisi <strong>masuk</strong> menentukan cara tampilan di aktivitas memasuki suatu babak.
+misalnya, dalam transisi masuk <em>explode</em>, tampilan memasuki babak dari sisi luar
+dan melayang masuk ke arah tengah layar.</li>
+
+<li>Transisi <strong>keluar</strong> menentukan cara tampilan di aktivitas keluar dari suatu babak. Misalnya
+, dalam transisi keluar <em>explode</em>, tampilan akan keluar dari babak dari bagian
+tengahnya.</li>
+
+<li>Transisi <strong>elemen bersama</strong> menentukan cara menggunakan bersama suatu tampilan
+oleh dua transisi aktivitas di antara aktivitas-aktivitas ini. Misalnya, jika dua aktivitas memiliki
+gambar yang sama dengan posisi dan ukuran berbeda, transisi elemen bersama <em>changeImageTransform</em>
+mentransformasikan dan menskalakan gambar secara mulus di antara aktivitas-aktivitas ini.</li>
+</ul>
+
+<p>Android 5.0 (API level 21) mendukung transisi masuk dan transisi keluar ini:</p>
+
+<ul>
+<li><em>explode</em> - Memindahkan tampilan masuk ke atau keluar dari tengah babak.</li>
+<li><em>slide</em> - Memindahkan tampilan masuk ke atau keluar dari salah satu tepi babak.</li>
+<li><em>fade</em> - Menambahkan atau menghapus tampilan dari babak dengan mengubah opasitasnya.</li>
+</ul>
+
+<p>Transisi apa pun yang memperluas kelas {@link android.transition.Visibility} didukung
+sebagai transisi masuk atau transisi keluar. Untuk informasi selengkapnya, lihat referensi API untuk kelas
+{@link android.transition.Transition}.</p>
+
+<p>Android 5.0 (API level 21) juga mendukung transisi elemen bersama ini:</p>
+
+<ul>
+<li><em>changeBounds</em> - Menganimasikan perubahan pada batas-batas layout tampilan target.</li>
+<li><em>changeClipBounds</em> - Menganimasikan perubahan pada batas-batas pemangkasan tampilan target.</li>
+<li><em>changeTransform</em> - Menganimasikan perubahan pada skala dan rotasi tampilan target.</li>
+<li><em>changeImageTransform</em> - Menganimasikan perubahan pada ukuran dan skala gambar target.</li>
+</ul>
+
+<p>Bila Anda mengaktifkan transisi aktivitas dalam aplikasi, transisi memudar-silang default akan
+diaktifkan di antara aktivitas masuk dan aktivitas keluar.</p>
+
+<img src="{@docRoot}training/material/images/SceneTransition.png" alt="" width="600" height="405" style="margin-top:20px" />
+<p class="img-caption">
+  <strong>Gambar 2</strong> - Transisi babak dengan satu elemen bersama.
+</p>
+
+<h3>Menetapkan transisi custom</h3>
+
+<p>Pertama, aktifkan transisi konten jendela dengan atribut <code>android:windowContentTransitions</code>
+bila Anda mendefinisikan gaya yang mewarisi tema bahan. Anda juga bisa menetapkan
+transisi-transisi masuk, keluar, dan elemen bersama dalam definisi gaya:</p>
+
+<pre>
+&lt;style name="BaseAppTheme" parent="android:Theme.Material">
+  &lt;!-- enable window content transitions -->
+  &lt;item name="android:windowContentTransitions">true&lt;/item>
+
+  &lt;!-- specify enter and exit transitions -->
+  &lt;item name="android:windowEnterTransition">@transition/explode&lt;/item>
+  &lt;item name="android:windowExitTransition">@transition/explode&lt;/item>
+
+  &lt;!-- specify shared element transitions -->
+  &lt;item name="android:windowSharedElementEnterTransition">
+    &#64;transition/change_image_transform&lt;/item>
+  &lt;item name="android:windowSharedElementExitTransition">
+    &#64;transition/change_image_transform&lt;/item>
+&lt;/style>
+</pre>
+
+<p>Transisi <code>change_image_transform</code> dalam contoh ini didefinisikan sebagai berikut:</p>
+
+<pre>
+&lt;!-- res/transition/change_image_transform.xml -->
+&lt;!-- (see also Shared Transitions below) -->
+&lt;transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
+  &lt;changeImageTransform/>
+&lt;/transitionSet>
+</pre>
+
+<p>Elemen <code>changeImageTransform</code> menunjukkan
+kelas {@link android.transition.ChangeImageTransform}. Untuk informasi selengkapnya, lihat referensi
+API untuk {@link android.transition.Transition}.</p>
+
+<p>Sebaliknya, untuk mengaktifkan transisi konten jendela dalam kode Anda, panggil
+metode {@link android.view.Window#requestFeature Window.requestFeature()}:</p>
+
+<pre>
+// inside your activity (if you did not enable transitions in your theme)
+getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
+
+// set an exit transition
+getWindow().setExitTransition(new Explode());
+</pre>
+
+<p>Untuk menetapkan transisi dalam kode Anda, panggil metode-metode ini dengan objek {@link
+android.transition.Transition}:</p>
+
+<ul>
+  <li>{@link android.view.Window#setEnterTransition Window.setEnterTransition()}</li>
+  <li>{@link android.view.Window#setExitTransition Window.setExitTransition()}</li>
+  <li>{@link android.view.Window#setSharedElementEnterTransition
+      Window.setSharedElementEnterTransition()}</li>
+  <li>{@link android.view.Window#setSharedElementExitTransition
+      Window.setSharedElementExitTransition()}</li>
+</ul>
+
+<p>Metode {@link android.view.Window#setExitTransition setExitTransition()} dan {@link
+android.view.Window#setSharedElementExitTransition setSharedElementExitTransition()} mendefinisikan
+transisi keluar untuk aktivitas yang memanggil. Metode {@link android.view.Window#setEnterTransition
+setEnterTransition()} dan {@link android.view.Window#setSharedElementEnterTransition
+setSharedElementEnterTransition()} mendefinisikan transisi masuk untuk aktivitas yang dipanggil.</p>
+
+<p>Untuk mendapatkan efek penuh sebuah transisi, Anda harus mengaktifkan transisi konten jendela pada
+aktivitas yang memanggil maupun aktivitas yang dipanggil. Jika tidak, aktivitas yang memanggil akan memulai transisi keluar,
+namun kemudian Anda akan melihat transisi jendela (seperti mengelupas atau memudar).</p>
+
+<p>Untuk memulai transisi masuk sesegera mungkin, gunakan metode
+{@link android.view.Window#setAllowEnterTransitionOverlap Window.setAllowEnterTransitionOverlap()}
+pada aktivitas yang dipanggil. Ini memungkinkan Anda mendapatkan transisi masuk yang lebih dramatis.</p>
+
+<h3>Memulai aktivitas dengan menggunakan transisi</h3>
+
+<p>Jika Anda mengaktifkan transisi dan mengatur transisi keluar untuk aktivitas, transisi itu akan diaktifkan
+bila Anda menjalankan aktivitas lain sebagai berikut:</p>
+
+<pre>
+startActivity(intent,
+              ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
+</pre>
+
+<p>Jika Anda telah mengatur transisi masuk untuk aktivitas kedua, transisi juga akan diaktifkan
+bila aktivitas dimulai. Untuk menonaktifkan transisi bila Anda memulai aktivitas lain, sediakan
+bundel opsi <code>null</code>.</p>
+
+<h3>Memulai aktivitas dengan satu elemen bersama</h3>
+
+<p>Untuk membuat animasi transisi layar di antara dua aktivitas yang memiliki satu elemen bersama:</p>
+
+<ol>
+<li>Aktifkan transisi konten jendela dalam tema Anda.</li>
+<li>Tetapkan transisi elemen bersama dalam gaya Anda.</li>
+<li>Definisikan transisi Anda sebagai sumber daya XML.</li>
+<li>Tetapkan nama umum pada elemen bersama dalam kedua layout dengan
+    atribut <code>android:transitionName</code>.</li>
+<li>Gunakan metode {@link android.app.ActivityOptions#makeSceneTransitionAnimation
+ActivityOptions.makeSceneTransitionAnimation()}.</li>
+</ol>
+
+<pre>
+// get the element that receives the click event
+final View imgContainerView = findViewById(R.id.img_container);
+
+// get the common element for the transition in this activity
+final View androidRobotView = findViewById(R.id.image_small);
+
+// define a click listener
+imgContainerView.setOnClickListener(new View.OnClickListener() {
+    &#64;Override
+    public void onClick(View view) {
+        Intent intent = new Intent(this, Activity2.class);
+        // create the transition animation - the images in the layouts
+        // of both activities are defined with android:transitionName="robot"
+        ActivityOptions options = ActivityOptions
+            .makeSceneTransitionAnimation(this, androidRobotView, "robot");
+        // start the new activity
+        startActivity(intent, options.toBundle());
+    }
+});
+</pre>
+
+<p>Untuk tampilan dinamis bersama yang Anda hasilkan dalam kode, gunakan
+metode {@link android.view.View#setTransitionName View.setTransitionName()} untuk menetapkan
+nama elemen umum di kedua aktivitas.</p>
+
+<p>Untuk membalik animasi transisi babak bila Anda menyelesaikan aktivitas kedua, panggil metode
+{@link android.app.Activity#finishAfterTransition Activity.finishAfterTransition()}
+sebagai ganti {@link android.app.Activity#finish Activity.finish()}.</p>
+
+<h3>Memulai aktivitas dengan beberapa elemen bersama</h3>
+
+<p>Untuk membuat animasi transisi babak antara dua aktivitas yang memiliki lebih dari satu
+elemen bersama, definisikan elemen bersama di kedua layout dengan atribut <code>android:transitionName</code>
+ (atau gunakan metode {@link android.view.View#setTransitionName View.setTransitionName()}
+di kedua aktivitas), dan buat sebuah objek {@link android.app.ActivityOptions} sebagai berikut:</p>
+
+<pre>
+ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
+        Pair.create(view1, "agreedName1"),
+        Pair.create(view2, "agreedName2"));
+</pre>
+
+
+<h2 id="CurvedMotion">Menggunakan Gerakan Melengkung</h2>
+
+<p>Animasi dalam desain bahan mengandalkan kurva untuk pola interpolasi waktu dan
+gerakan spasial. Dengan Android 5.0 (API level 21) ke atas, Anda bisa mendefinisikan kurva pewaktuan custom dan
+pola gerakan melengkung untuk animasi.</p>
+
+<p>Kelas {@link android.view.animation.PathInterpolator} adalah interpolator baru berdasarkan sebuah
+kurva Bézier atau objek {@link android.graphics.Path}. Interpolator ini menetapkan kurva gerakan
+dalam bujur sangkar 1x1, dengan titik-titik jangkar di (0,0) dan (1,1) dan titik-titik kontrol sebagaimana ditetapkan menggunakan
+argumen konstruktor. Anda juga bisa mendefinisikan interpolator path sebagai sumber daya XML:</p>
+
+<pre>
+&lt;pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:controlX1="0.4"
+    android:controlY1="0"
+    android:controlX2="1"
+    android:controlY2="1"/>
+</pre>
+
+<p>Sistem menyediakan sumber daya XML untuk tiga kurva dasar dalam
+spesifikasi desain bahan:</p>
+
+<ul>
+  <li><code>&#64;interpolator/fast_out_linear_in.xml</code></li>
+  <li><code>&#64;interpolator/fast_out_slow_in.xml</code></li>
+  <li><code>&#64;interpolator/linear_out_slow_in.xml</code></li>
+</ul>
+
+<p>Anda bisa meneruskan objek {@link android.view.animation.PathInterpolator} ke metode {@link
+android.animation.Animator#setInterpolator Animator.setInterpolator()}.</p>
+
+<p>Kelas {@link android.animation.ObjectAnimator} memiliki konstruktor-konstruktor baru yang memungkinkan Anda menganimasikan
+koordinat bersama sebuah path dengan menggunakan dua atau beberapa properti sekaligus. Misalnya, animator berikut
+menggunakan objek {@link android.graphics.Path} untuk menganimasikan properti X dan Y sebuah tampilan:</p>
+
+<pre>
+ObjectAnimator mAnimator;
+mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
+...
+mAnimator.start();
+</pre>
+
+
+<h2 id="ViewState">Menganimasikan Perubahan Status Tampilan</h2>
+
+<p>Kelas {@link android.animation.StateListAnimator} memungkinkan Anda mendefinisikan animator yang berjalan bila
+status tampilan berubah. Contoh berikut menampilkan cara mendefinisikan {@link
+android.animation.StateListAnimator} sebagai sumber daya XML:</p>
+
+<pre>
+&lt;!-- animate the translationZ property of a view when pressed -->
+&lt;selector xmlns:android="http://schemas.android.com/apk/res/android">
+  &lt;item android:state_pressed="true">
+    &lt;set>
+      &lt;objectAnimator android:propertyName="translationZ"
+        android:duration="@android:integer/config_shortAnimTime"
+        android:valueTo="2dp"
+        android:valueType="floatType"/>
+        &lt;!-- you could have other objectAnimator elements
+             here for "x" and "y", or other properties -->
+    &lt;/set>
+  &lt;/item>
+  &lt;item android:state_enabled="true"
+    android:state_pressed="false"
+    android:state_focused="true">
+    &lt;set>
+      &lt;objectAnimator android:propertyName="translationZ"
+        android:duration="100"
+        android:valueTo="0"
+        android:valueType="floatType"/>
+    &lt;/set>
+  &lt;/item>
+&lt;/selector>
+</pre>
+
+<p>Untuk menyertakan animasi status tampilan custom ke tampilan, definisikan animator menggunakan
+elemen <code>selector</code> dalam sumber daya file XML sebagaimana dalam contoh ini, dan tetapkan ke
+tampilan Anda dengan atribut <code>android:stateListAnimator</code>. Untuk menetapkan animator daftar status
+ke sebuah tampilan dalam kode Anda, gunakan metode {@link android.animation.AnimatorInflater#loadStateListAnimator
+AnimationInflater.loadStateListAnimator()}, dan tetapkan animator ke tampilan dengan
+metode {@link android.view.View#setStateListAnimator View.setStateListAnimator()}.</p>
+
+<p>Bila tema Anda memperluas tema bahan, tombol-tombol akan memiliki animasi Z secara default. Untuk menghindari
+perilaku ini di tombol Anda, aturlah atribut <code>android:stateListAnimator</code> ke
+<code>@null</code>.</p>
+
+<p>Kelas {@link android.graphics.drawable.AnimatedStateListDrawable} memungkinkan Anda membuat drawable
+yang menampilkan animasi di antara perubahan status tampilan terkait. Sebagian widget sistem di
+Android 5.0 menggunakan animasi ini secara default. Contoh berikut menampilkan cara
+mendefinisikan {@link android.graphics.drawable.AnimatedStateListDrawable} sebagai sumber daya XML:</p>
+
+<pre>
+&lt;!-- res/drawable/myanimstatedrawable.xml -->
+&lt;animated-selector
+    xmlns:android="http://schemas.android.com/apk/res/android">
+
+    &lt;!-- provide a different drawable for each state-->
+    &lt;item android:id="@+id/pressed" android:drawable="@drawable/drawableP"
+        android:state_pressed="true"/>
+    &lt;item android:id="@+id/focused" android:drawable="@drawable/drawableF"
+        android:state_focused="true"/>
+    &lt;item android:id="@id/default"
+        android:drawable="@drawable/drawableD"/>
+
+    &lt;!-- specify a transition -->
+    &lt;transition android:fromId="@+id/default" android:toId="@+id/pressed">
+        &lt;animation-list>
+            &lt;item android:duration="15" android:drawable="@drawable/dt1"/>
+            &lt;item android:duration="15" android:drawable="@drawable/dt2"/>
+            ...
+        &lt;/animation-list>
+    &lt;/transition>
+    ...
+&lt;/animated-selector>
+</pre>
+
+
+<h2 id="AnimVector">Menganimasikan Drawable Vektor</h2>
+
+<p><a href="{@docRoot}training/material/drawables.html#VectorDrawables">Drawable Vektor </a>
+bisa diubah skalanya tanpa kehilangan definisi. Kelas {@link android.graphics.drawable.AnimatedVectorDrawable}
+memungkinkan Anda menganimasikan properti drawable vektor.</p>
+
+<p>Anda biasanya mendefinisikan drawable vektor yang dianimasikan dalam tiga file XML:</p>
+
+<ul>
+<li>Drawable vektor dengan elemen <code>&lt;vector&gt;</code> dalam
+<code>res/drawable/</code></li>
+<li>Drawable vektor animasi dengan elemen <code>&lt;animated-vector&gt;</code> dalam
+<code>res/drawable/</code></li>
+<li>Satu atau beberapa animator objek dengan elemen <code>&lt;objectAnimator&gt;</code> dalam
+<code>res/anim/</code></li>
+</ul>
+
+<p>Drawable vektor yang dianimasikan bisa menganimasikan atribut elemen <code>&lt;group&gt;</code> dan
+<code>&lt;path&gt;</code>. Elemen <code>&lt;group&gt;</code> mendefinisikan satu set
+path atau subgrup, dan elemen <code>&lt;path&gt;</code> mendefinisikan path yang harus digambar.</p>
+
+<p>Bila Anda mendefinisikan drawable vektor yang ingin dianimasikan, gunakan atribut <code>android:name</code>
+untuk menetapkan nama unik ke grup dan path, sehingga Anda bisa merujuknya dari
+definisi animator Anda. Misalnya:</p>
+
+<pre>
+&lt;!-- res/drawable/vectordrawable.xml -->
+&lt;vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="64dp"
+    android:width="64dp"
+    android:viewportHeight="600"
+    android:viewportWidth="600">
+    &lt;group
+        <strong>android:name="rotationGroup"</strong>
+        android:pivotX="300.0"
+        android:pivotY="300.0"
+        android:rotation="45.0" >
+        &lt;path
+            <strong>android:name="v"</strong>
+            android:fillColor="#000000"
+            android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
+    &lt;/group>
+&lt;/vector>
+</pre>
+
+<p>Definisi drawable vektor yang dianimasikan merujuk pada grup dan path dalam drawable vektor
+berdasarkan namanya:</p>
+
+<pre>
+&lt;!-- res/drawable/animvectordrawable.xml -->
+&lt;animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+  android:drawable="@drawable/vectordrawable" >
+    &lt;target
+        android:name="rotationGroup"
+        android:animation="@anim/rotation" />
+    &lt;target
+        android:name="v"
+        android:animation="@anim/path_morph" />
+&lt;/animated-vector>
+</pre>
+
+<p>Definisi animasi menyatakan objek {@link android.animation.ObjectAnimator} atau {@link
+android.animation.AnimatorSet}. Animator pertama dalam contoh ini memutar
+grup target sebanyak 360 derajat:</p>
+
+<pre>
+&lt;!-- res/anim/rotation.xml -->
+&lt;objectAnimator
+    android:duration="6000"
+    android:propertyName="rotation"
+    android:valueFrom="0"
+    android:valueTo="360" />
+</pre>
+
+<p>Animator kedua dalam contoh ini perlahan-lahan mengubah bentuk path drawable vektor dari satu bentuk ke
+bentuk yang lain. Kedua path harus kompatibel untuk morphing: keduanya harus memiliki jumlah perintah yang sama
+dan jumlah parameter yang sama untuk setiap perintah.</p>
+
+<pre>
+&lt;!-- res/anim/path_morph.xml -->
+&lt;set xmlns:android="http://schemas.android.com/apk/res/android">
+    &lt;objectAnimator
+        android:duration="3000"
+        android:propertyName="pathData"
+        android:valueFrom="M300,70 l 0,-70 70,70 0,0   -70,70z"
+        android:valueTo="M300,70 l 0,-70 70,0  0,140 -70,0 z"
+        android:valueType="pathType" />
+&lt;/set>
+</pre>
+
+<p>Untuk informasi selengkapnya, lihat referensi API bagi {@link
+android.graphics.drawable.AnimatedVectorDrawable}.</p>
diff --git a/docs/html-intl/intl/id/training/material/compatibility.jd b/docs/html-intl/intl/id/training/material/compatibility.jd
new file mode 100644
index 0000000..ef444c3
--- /dev/null
+++ b/docs/html-intl/intl/id/training/material/compatibility.jd
@@ -0,0 +1,168 @@
+page.title=Mempertahankan Kompatibilitas
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>Pelajaran ini mengajarkan Anda cara</h2>
+<ol>
+  <li><a href="#Theme">Mendefinisikan Gaya Alternatif</a></li>
+  <li><a href="#Layouts">Menyediakan Layout Alternatif</a></li>
+  <li><a href="#SupportLib">Menggunakan Support Library</a></li>
+  <li><a href="#CheckVersion">Memeriksa Versi Sistem</a></li>
+</ol>
+<h2>Anda juga harus membaca</h2>
+<ul>
+  <li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
+  <li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
+</ul>
+</div>
+</div>
+
+
+<p>Sebagian fitur desain bahan seperti tema bahan dan transisi aktivitas custom
+hanya tersedia pada Android 5.0 (API level 21) ke atas. Akan tetapi, Anda bisa mendesain aplikasi untuk menggunakan
+fitur-fitur ini saat dijalankan pada perangkat yang mendukung desain bahan dan tetap kompatibel
+dengan perangkat yang menjalankan rilis Android sebelumnya.</p>
+
+
+<h2 id="Theme">Mendefinisikan Gaya Alternatif</h2>
+
+<p>Anda bisa mengonfigurasi aplikasi untuk menggunakan tema bahan pada perangkat yang mendukungnya dan mengembalikan
+ke tema lama pada perangkat yang menjalankan versi Android terdahulu:</p>
+
+<ol>
+<li>Definisikan tema yang mewarisi tema lama (seperti Holo) di
+    <code>res/values/styles.xml</code>.</li>
+<li>Definisikan tema bernama sama yang mewarisi tema bahan di
+    <code>res/values-v21/styles.xml</code>.</li>
+<li>Atur tema ini sebagai tema aplikasi Anda dalam file manifes.</li>
+</ol>
+
+<p class="note"><strong>Catatan:</strong>
+Jika aplikasi Anda menggunakan tema bahan namun tidak menyediakan tema alternatif dengan cara ini,
+aplikasi itu tidak akan berjalan pada versi Android sebelum 5.0.
+</p>
+
+
+<h2 id="Layouts">Menyediakan Layout Alternatif</h2>
+
+<p>Jika layout yang Anda desain sesuai dengan panduan desain bahan tidak menggunakan salah satu
+atribut XML baru yang diperkenalkan di Android 5.0 (API level 21), layout itu akan berfungsi pada
+versi Android sebelumnya. Jika tidak, Anda bisa menyediakan layout alternatif. Anda juga bisa menyediakan
+layout alternatif untuk menyesuaikan cara aplikasi ditampilkan pada versi Android terdahulu.</p>
+
+<p>Buatlah file layout untuk Android 5.0 (API level 21) dalam <code>res/layout-v21/</code> dan
+file layout alternatif untuk versi Android terdahulu dalam <code>res/layout/</code>.
+Misalnya, <code>res/layout/my_activity.xml</code> adalah layout alternatif untuk
+<code>res/layout-v21/my_activity.xml</code>.</p>
+
+<p>Untuk menghindari duplikasi kode, definisikan gaya dalam <code>res/values/</code>, modifikasi
+gaya di <code>res/values-v21/</code> untuk API baru, dan gunakan pewarisan gaya, dengan mendefinisikan
+gaya dasar di <code>res/values/</code> dan mewarisi gaya di <code>res/values-v21/</code>.</p>
+
+
+<h2 id="SupportLib">Menggunakan Support Library</h2>
+
+<p><a href="{@docRoot}tools/support-library/features.html#v7">v7 Support Library</a>
+r21 ke atas menyertakan fitur desain bahan berikut:</p>
+
+<ul>
+<li><a href="{@docRoot}training/material/theme.html">Gaya desain bahan</a> untuk beberapa widget sistem
+    bila Anda menerapkan salah satu tema <code>Theme.AppCompat</code>.</li>
+<li><a href="{@docRoot}training/material/theme.html#ColorPalette">Atribut tema palet warna</a>
+    dalam tema <code>Theme.AppCompat</code>.</li>
+<li>Widget {@link android.support.v7.widget.RecyclerView} untuk <a href="{@docRoot}training/material/lists-cards.html#RecyclerView">
+menampilkan kumpulan data.</a></li>
+<li>Widget {@link android.support.v7.widget.CardView} untuk <a href="{@docRoot}training/material/lists-cards.html#CardView">membuat kartu</a>.</li>
+<li>Kelas {@link android.support.v7.graphics.Palette} untuk <a href="{@docRoot}training/material/drawables.html#ColorExtract">mengekstrak warna mencolok dari
+    gambar</a>.</li>
+</ul>
+
+<h3>Widget sistem</h3>
+
+<p>Tema-tema <code>Theme.AppCompat</code> menyediakan gaya desain bahan untuk widget ini:</p>
+
+<ul>
+  <li>{@link android.widget.EditText}</li>
+  <li>{@link android.widget.Spinner}</li>
+  <li>{@link android.widget.CheckBox}</li>
+  <li>{@link android.widget.RadioButton}</li>
+  <li>{@link android.support.v7.widget.SwitchCompat}</li>
+  <li>{@link android.widget.CheckedTextView}</li>
+</ul>
+
+<h3>Palet Warna</h3>
+
+<p>Untuk memperoleh gaya desain bahan dan menyesuaikan palet warna dengan Android v7 Support
+Library, terapkan salah satu tema <code>Theme.AppCompat</code>:</p>
+
+<pre>
+&lt;!-- extend one of the Theme.AppCompat themes -->
+&lt;style name="Theme.MyTheme" parent="Theme.AppCompat.Light">
+    &lt;!-- customize the color palette -->
+    &lt;item name="colorPrimary">@color/material_blue_500&lt;/item>
+    &lt;item name="colorPrimaryDark">@color/material_blue_700&lt;/item>
+    &lt;item name="colorAccent">@color/material_green_A200&lt;/item>
+&lt;/style>
+</pre>
+
+<h3>Daftar dan Kartu</h3>
+
+<p>Widget {@link android.support.v7.widget.RecyclerView} dan {@link
+android.support.v7.widget.CardView} tersedia di versi Android terdahulu melalui
+Android v7 Support Library dengan pembatasan ini:</p>
+<ul>
+<li>{@link android.support.v7.widget.CardView} memundurkan ke implementasi bayangan terprogram
+    dengan menggunakan pengisi tambahan.</li>
+<li>{@link android.support.v7.widget.CardView} tidak memangkas tampilan anaknya yang berpotongan
+    dengan sudut melengkung.</li>
+</ul>
+
+
+<h3>Dependensi</h3>
+
+<p>Untuk menggunakan fitur-fitur ini di versi Android sebelum 5.0 (API level 21), sertakan
+Android v7 Support Library dalam proyek Anda sebagai <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">dependensi Gradle</a>:</p>
+
+<pre>
+dependencies {
+    compile 'com.android.support:appcompat-v7:21.0.+'
+    compile 'com.android.support:cardview-v7:21.0.+'
+    compile 'com.android.support:recyclerview-v7:21.0.+'
+}
+</pre>
+
+
+<h2 id="CheckVersion">Memeriksa Versi Sistem</h2>
+
+<p>Fitur berikut hanya tersedia di Android 5.0 (API level 21) ke atas:</p>
+
+<ul>
+<li>Transisi aktivitas</li>
+<li>Umpan balik sentuh</li>
+<li>Animasi membuka</li>
+<li>Animasi berbasis path</li>
+<li>Drawable vektor</li>
+<li>Pewarnaan drawable</li>
+</ul>
+
+<p>Untuk menjaga kompatibilitas dengan versi Android terdahulu, periksa {@link
+android.os.Build.VERSION#SDK_INT version} sistem saat runtime sebelum Anda memanggil API untuk salah satu
+fitur ini:</p>
+
+<pre>
+// Check if we're running on Android 5.0 or higher
+if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+    // Call some material design APIs here
+} else {
+    // Implement this feature without material design
+}
+</pre>
+
+<p class="note"><strong>Catatan:</strong> Untuk menetapkan versi Android yang didukung aplikasi Anda,
+gunakan atribut <code>android:minSdkVersion</code> dan <code>android:targetSdkVersion</code>
+dalam file manifes. Untuk menggunakan fitur desain bahan di Android 5.0, atur
+atribut <code>android:targetSdkVersion</code> ke <code>21</code>. Untuk informasi selengkapnya, lihat
+panduan <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">API
+&lt;uses-sdk&gt;</a>.</p>
diff --git a/docs/html-intl/intl/id/training/material/drawables.jd b/docs/html-intl/intl/id/training/material/drawables.jd
new file mode 100644
index 0000000..493abd4
--- /dev/null
+++ b/docs/html-intl/intl/id/training/material/drawables.jd
@@ -0,0 +1,126 @@
+page.title=Bekerja dengan Drawable
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>Pelajaran ini mengajarkan Anda cara</h2>
+<ol>
+  <li><a href="#DrawableTint">Mewarnai Sumber Daya Drawable</a></li>
+  <li><a href="#ColorExtract">Mengekstrak Warna Mencolok dari Gambar</a></li>
+  <li><a href="#VectorDrawables">Membuat Drawable Vektor</a></li>
+</ol>
+<h2>Anda juga harus membaca</h2>
+<ul>
+  <li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
+  <li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
+</ul>
+</div>
+</div>
+
+<p>Kemampuan berikut untuk drawable membantu Anda mengimplementasikan desain bahan dalam aplikasi Anda:</p>
+
+<ul>
+<li>Pewarnaan drawable</li>
+<li>Ekstraksi warna mencolok</li>
+<li>Drawable vektor</li>
+</ul>
+
+<p>Pelajaran ini menampilkan cara menggunakan fitur-fitur ini dalam aplikasi Anda.</p>
+
+
+<h2 id="DrawableTint">Mewarnai Sumber Daya Drawable</h2>
+
+<p>Dengan Android 5.0 (API level 21) ke atas, Anda bisa mewarnai bitmap dan sembilan-tambalan yang didefinisikan sebagai
+alpha-mask. Anda bisa mewarnainya dengan sumber daya warna atau atribut tema yang mencocokkan ke
+sumber daya warna (misalnya, <code>?android:attr/colorPrimary</code>). Biasanya, Anda membuat aset ini
+hanya sekali dan mewarnainya secara otomatis agar cocok dengan tema Anda.</p>
+
+<p>Anda bisa menerapkan warna ke objek {@link android.graphics.drawable.BitmapDrawable} atau {@link
+android.graphics.drawable.NinePatchDrawable} dengan metode {@code setTint()}. Anda juga bisa
+mengatur warna dan mode dalam layout dengan atribut <code>android:tint</code> dan
+<code>android:tintMode</code>.</p>
+
+
+<h2 id="ColorExtract">Mengekstrak Warna Mencolok dari Gambar</h2>
+
+<p>Android Support Library r21 ke atas menyertakan kelas {@link
+android.support.v7.graphics.Palette}, yang memungkinkan Anda mengekstrak warna mencolok dari gambar.
+Kelas ini mengekstrak warna mencolok berikut:</p>
+
+<ul>
+<li>Menyala</li>
+<li>Menyala pekat</li>
+<li>Menyala pucat</li>
+<li>Pudar</li>
+<li>Pudar pekat</li>
+<li>Pudar pucat</li>
+</ul>
+
+<p>Untuk mengekstrak warna-warna ini, teruskan objek {@link android.graphics.Bitmap} ke
+metode statis {@link android.support.v7.graphics.Palette#generate Palette.generate()} dalam
+thread latar belakang tempat Anda memuat gambar. Jika Anda tidak bisa menggunakan thread itu, panggil metode
+{@link android.support.v7.graphics.Palette#generateAsync Palette.generateAsync()} dan
+sediakan listener sebagai gantinya.</p>
+
+<p>Anda bisa mengambil warna mencolok dari gambar dengan metode getter di kelas
+<code>Palette</code>, misalnya <code>Palette.getVibrantColor</code>.</p>
+
+<p>Untuk menggunakan kelas {@link android.support.v7.graphics.Palette} dalam proyek Anda, tambahkan
+<a href="{@docRoot}sdk/installing/studio-build.html#dependencies">dependensi Gradle</a> berikut ke
+modul aplikasi Anda:</p>
+
+<pre>
+dependencies {
+    ...
+    compile 'com.android.support:palette-v7:21.0.0'
+}
+</pre>
+
+<p>Untuk informasi selengkapnya, lihat referensi API untuk kelas {@link android.support.v7.graphics.Palette}.
+</p>
+
+
+<h2 id="VectorDrawables">Membuat Drawable Vektor</h2>
+
+<!-- video box -->
+<a class="notice-developers-video" href="https://www.youtube.com/watch?v=wlFVIIstKmA" style="margin-top:18px">
+<div>
+    <h3>Video</h3>
+    <p>Grafis Vektor Android</p>
+</div>
+</a>
+
+<p>Di Android 5.0 (API Level 21) ke atas, Anda bisa mendefinisikan drawable vektor, yang berubah skala tanpa
+kehilangan definisi. Anda hanya memerlukan satu file aset per gambar vektor, bukan file aset untuk
+setiap densitas layar seperti pada gambar bitmap. Untuk membuat gambar vektor, Anda mendefinisikan detail
+bentuknya dalam sebuah elemen XML <code>&lt;vector&gt;</code>.</p>
+
+<p>Contoh berikut mendefinisikan gambar vektor berbentuk hati:</p>
+
+<pre>
+&lt;!-- res/drawable/heart.xml -->
+&lt;vector xmlns:android="http://schemas.android.com/apk/res/android"
+    &lt;!-- intrinsic size of the drawable -->
+    android:height="256dp"
+    android:width="256dp"
+    &lt;!-- size of the virtual canvas -->
+    android:viewportWidth="32"
+    android:viewportHeight="32">
+
+  &lt;!-- draw a path -->
+  &lt;path android:fillColor="#8fff"
+      android:pathData="M20.5,9.5
+                        c-1.955,0,-3.83,1.268,-4.5,3
+                        c-0.67,-1.732,-2.547,-3,-4.5,-3
+                        C8.957,9.5,7,11.432,7,14
+                        c0,3.53,3.793,6.257,9,11.5
+                        c5.207,-5.242,9,-7.97,9,-11.5
+                        C25,11.432,23.043,9.5,20.5,9.5z" />
+&lt;/vector>
+</pre>
+
+<p>Gambar vektor direpresentasikan di Android sebagai objek {@link android.graphics.drawable.VectorDrawable}.
+ Untuk informasi selengkapnya tentang sintaks <code>pathData</code>, lihat <a href="http://www.w3.org/TR/SVG11/paths.html#PathData">Referensi Path SVG</a>. Untuk informasi selengkapnya
+tentang menganimasikan properti drawable vektor, lihat
+<a href="{@docRoot}training/material/animations.html#AnimVector">Menganimasikan Drawable Vektor</a>.</p>
diff --git a/docs/html-intl/intl/id/training/material/get-started.jd b/docs/html-intl/intl/id/training/material/get-started.jd
new file mode 100644
index 0000000..1a551a9
--- /dev/null
+++ b/docs/html-intl/intl/id/training/material/get-started.jd
@@ -0,0 +1,171 @@
+page.title=Memulai
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>Pelajaran ini mengajarkan Anda cara</h2>
+<ol>
+  <li><a href="#ApplyTheme">Menerapkan Tema Bahan</a></li>
+  <li><a href="#Layouts">Mendesain Layout Anda</a></li>
+  <li><a href="#Depth">Menetapkan Ketinggian di Tampilan Anda</a></li>
+  <li><a href="#ListsCards">Membuat Daftar dan Kartu</a></li>
+  <li><a href="#Animations">Menyesuaikan Animasi Anda</a></li>
+</ol>
+<h2>Anda juga harus membaca</h2>
+<ul>
+  <li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
+  <li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
+</ul>
+</div>
+</div>
+
+
+<p>Untuk membuat aplikasi dengan desain bahan:</p>
+
+<ol>
+  <li style="margin-bottom:10px">
+    Tinjaulah <a href="http://www.google.com/design/spec">spesifikasi desain bahan</a>.</li>
+  <li style="margin-bottom:10px">
+    Terapkan <strong>tema</strong> bahan ke aplikasi Anda.</li>
+  <li style="margin-bottom:10px">
+    Buat <strong>layout</strong> agar mengikuti panduan desain bahan.</li>
+  <li style="margin-bottom:10px">
+    Tetapkan <strong>ketinggian</strong> tampilan Anda untuk menghasilkan bayangan.</li>
+  <li style="margin-bottom:10px">
+    Gunakan <strong>widget</strong> sistem untuk daftar dan kartu.</li>
+  <li style="margin-bottom:10px">
+    Sesuaikan <strong>animasi</strong> di aplikasi Anda.</li>
+</ol>
+
+<h3>Mempertahankan kompatibilitas mundur</h3>
+
+<p>Anda bisa menambahkan banyak fitur desain bahan ke aplikasi sekaligus mempertahankan kompatibilitas dengan
+versi Android sebelum 5.0. Untuk informasi selengkapnya, lihat
+<a href="{@docRoot}training/material/compatibility.html">Mempertahankan Kompatibilitas</a>.</p>
+
+<h3>Memperbarui aplikasi dengan desain bahan</h3>
+
+<p>Untuk memperbarui aplikasi yang ada guna memasukkan desain bahan, perbarui layout Anda dengan mengikuti
+panduan desain bahan. Juga pastikan memasukkan kedalaman, umpan balik sentuh, dan
+animasi.</p>
+
+<h3>Membuat aplikasi baru dengan desain bahan</h3>
+
+<p>Jika Anda sedang membuat aplikasi baru dengan fitur desain bahan, <a href="http://www.google.com/design/spec">panduan desain bahan</a> akan memberi Anda
+kerangka kerja desain yang kohesif. Ikuti panduan itu dan gunakan fungsionalitas baru di
+kerangka kerja Android untuk mendesain dan mengembangkan aplikasi Anda.</p>
+
+
+<h2 id="ApplyTheme">Menerapkan Tema Bahan</h2>
+
+<p>Untuk menerapkan tema bahan dalam aplikasi Anda, tetapkan gaya yang mewarisi
+<code>android:Theme.Material</code>:</p>
+
+<pre>
+&lt;!-- res/values/styles.xml -->
+&lt;resources>
+  &lt;!-- your theme inherits from the material theme -->
+  &lt;style name="AppTheme" parent="android:Theme.Material">
+    &lt;!-- theme customizations -->
+  &lt;/style>
+&lt;/resources>
+</pre>
+
+<p>Tema bahan menyediakan widget sistem terbaru yang memungkinkan Anda mengatur palet warnanya dan
+animasi default untuk umpan balik sentuh dan transisi aktivitas. Untuk detail selengkapnya, lihat
+<a href="{@docRoot}training/material/theme.html">Menggunakan Tema Bahan</a>.</p>
+
+
+<h2 id="Layouts">Mendesain Layout Anda</h2>
+
+<p>Selain menerapkan dan menyesuaikan tema bahan, layout Anda harus mematuhi
+<a href="http://www.google.com/design/spec">panduan desain bahan</a>. Bila Anda mendesain
+layout, berikan perhatian khusus pada hal-hal berikut:</p>
+
+<ul>
+<li>Petak patokan</li>
+<li>Garis utama</li>
+<li>Pengaturan Jarak</li>
+<li>Ukuran target sentuh</li>
+<li>Struktur layout</li>
+</ul>
+
+
+<h2 id="Depth">Menetapkan Ketinggian di Tampilan Anda</h2>
+
+<p>Tampilan bisa menghasilkan bayangan, dan nilai ketinggian tampilan
+menentukan ukuran bayangan dan urutan penggambarannya. Untuk mengatur ketinggian tampilan, gunakan
+atribut <code>android:elevation</code> dalam layout:</p>
+
+<pre>
+&lt;TextView
+    android:id="&#64;+id/my_textview"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:text="&#64;string/next"
+    android:background="&#64;color/white"
+    android:elevation="5dp" />
+</pre>
+
+<p>Properti <code>translationZ</code> baru memungkinkan Anda membuat animasi yang mencerminkan
+perubahan sementara pada ketinggian tampilan. Perubahan ketinggian bisa berguna saat
+<a href="{@docRoot}training/material/animations.html#ViewState">merespons
+gerakan sentuh</a>.</p>
+
+<p>Untuk detail selengkapnya, lihat <a href="{@docRoot}training/material/shadows-clipping.html">Mendefinisikan
+Bayangan dan Memangkas Tampilan</a>.</p>
+
+
+<h2 id="ListsCards">Membuat Daftar dan Kartu</h2>
+
+<p>{@link android.support.v7.widget.RecyclerView} adalah versi {@link
+android.widget.ListView} yang lebih mudah dimasukkan dan mendukung beragam tipe layout serta memberikan peningkatan kinerja.
+{@link android.support.v7.widget.CardView} memungkinkan Anda menampilkan potongan informasi dalam kartu dengan
+tampilan konsisten di seluruh aplikasi. Contoh kode berikut memperagakan cara menyertakan
+{@link android.support.v7.widget.CardView} dalam layout Anda:</p>
+
+<pre>
+&lt;android.support.v7.widget.CardView
+    android:id="&#64;+id/card_view"
+    android:layout_width="200dp"
+    android:layout_height="200dp"
+    card_view:cardCornerRadius="3dp">
+    ...
+&lt;/android.support.v7.widget.CardView>
+</pre>
+
+<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/lists-cards.html">Membuat Daftar
+dan Kartu</a>.</p>
+
+
+<h2 id="Animations">Menyesuaikan Animasi Anda</h2>
+
+<p>Android 5.0 (API level 21) menyertakan API baru untuk membuat animasi custom di aplikasi Anda.
+Misalnya, Anda bisa mengaktifkan transisi aktivitas dan mendefinisikan transisi keluar di
+aktivitas:</p>
+
+<pre>
+public class MyActivity extends Activity {
+
+    &#64;Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        // enable transitions
+        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
+        setContentView(R.layout.activity_my);
+    }
+
+    public void onSomeButtonClicked(View view) {
+        getWindow().setExitTransition(new Explode());
+        Intent intent = new Intent(this, MyOtherActivity.class);
+        startActivity(intent,
+                      ActivityOptions
+                          .makeSceneTransitionAnimation(this).toBundle());
+    }
+}
+</pre>
+
+<p>Bila Anda memulai aktivitas lain dari aktivitas ini, transisi keluar akan diaktifkan.</p>
+
+<p>Untuk mengetahui selengkapnya tentang API animasi yang baru, lihat <a href="{@docRoot}training/material/animations.html">Mendefinisikan Animasi Custom</a>.</p>
diff --git a/docs/html-intl/intl/id/training/material/index.jd b/docs/html-intl/intl/id/training/material/index.jd
new file mode 100644
index 0000000..53697d2
--- /dev/null
+++ b/docs/html-intl/intl/id/training/material/index.jd
@@ -0,0 +1,60 @@
+page.title=Desain Bahan untuk Pengembang
+page.image=images/cards/material_2x.png
+page.metaDescription=Pelajari cara menerapkan desain bahan pada aplikasi Anda.
+
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+  <h2>Dependensi dan Prasyarat</h2>
+  <ul>
+    <li>Android 5.0 (API Level 21)</li>
+  </ul>
+</div>
+</div>
+
+<p>Desain bahan adalah panduan komprehensif untuk desain visual, gerak, dan interaksi di
+berbagai platform dan perangkat. Untuk menggunakan desain bahan di aplikasi Android, ikuti panduan
+yang dijelaskan dalam
+<a href="http://www.google.com/design/spec/material-design/introduction.html">spesifikasi desain bahan
+</a> dan gunakan komponen serta fungsionalitas baru yang tersedia di Android 5.0
+(API level 21).</p>
+
+<p>Kelas ini menampilkan kepada Anda cara membuat aplikasi desain bahan dengan elemen-elemen berikut:</p>
+
+<ul>
+<li>Tema bahan</li>
+<li>Widget untuk kartu dan daftar</li>
+<li>Bayangan custom dan pemangkasan tampilan</li>
+<li>Drawable vektor</li>
+<li>Animasi custom</li>
+</ul>
+
+<p>Kelas ini juga mengajarkan cara mempertahankan kompatibilitas dengan versi Android sebelum
+5.0 (API level 21) bila Anda menggunakan fitur desain bahan dalam aplikasi.</p>
+
+<h2>Pelajaran</h2>
+
+<dl>
+  <dt><a href="{@docRoot}training/material/get-started.html">Memulai</a></dt>
+  <dd>Pelajari cara memperbarui aplikasi Anda dengan fitur desain bahan.</dd>
+
+  <dt><a href="{@docRoot}training/material/theme.html">Menggunakan Tema Bahan</a></dt>
+  <dd>Pelajari cara menerapkan gaya desain bahan pada aplikasi Anda.</dd>
+
+  <dt><a href="{@docRoot}training/material/lists-cards.html">Membuat Daftar dan Kartu</a></dt>
+  <dd>Pelajari cara membuat daftar dan kartu dengan tampilan dan cara kerja yang konsisten menggunakan widget sistem.</dd>
+
+  <dt><a href="{@docRoot}training/material/shadows-clipping.html">Mendefinisikan Bayangan dan Memangkas Tampilan</a></dt>
+  <dd>Pelajari cara mengatur elevasi tampilan Anda untuk membuat bayangan custom dan cara memangkas tampilan.</dd>
+
+  <dt><a href="{@docRoot}training/material/drawables.html">Bekerja dengan Drawable</a></dt>
+  <dd>Pelajari cara membuat drawable vektor dan cara mewarnai sumber daya drawable.</dd>
+
+  <dt><a href="{@docRoot}training/material/animations.html">Mendefinisikan Animasi Custom</a></dt>
+  <dd>Pelajari cara membuat animasi custom untuk tampilan dan transisi aktivitas dengan elemen bersama.</dd>
+
+  <dt><a href="{@docRoot}training/material/compatibility.html">Mempertahankan Kompatibilitas</a></dt>
+  <dd>Pelajari cara mempertahankan kompatibilitas dengan versi platform sebelum Android 5.0.</dd>
+</dl>
diff --git a/docs/html-intl/intl/id/training/material/lists-cards.jd b/docs/html-intl/intl/id/training/material/lists-cards.jd
new file mode 100644
index 0000000..46dd19af
--- /dev/null
+++ b/docs/html-intl/intl/id/training/material/lists-cards.jd
@@ -0,0 +1,266 @@
+page.title=Membuat Daftar dan Kartu
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>Pelajaran ini mengajarkan Anda cara</h2>
+<ol>
+  <li><a href="#RecyclerView">Membuat Daftar</a></li>
+  <li><a href="#CardView">Membuat Kartu</a></li>
+  <li><a href="#Dependencies">Menambahkan Dependensi</a></li>
+</ol>
+<h2>Anda juga harus membaca</h2>
+<ul>
+  <li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
+  <li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
+</ul>
+</div>
+</div>
+
+
+<p>Untuk membuat daftar dan kartu yang kompleks dengan gaya desain bahan di aplikasi, Anda bisa menggunakan widget
+{@link android.support.v7.widget.RecyclerView} dan {@link android.support.v7.widget.CardView}.
+</p>
+
+
+<h2 id="RecyclerView">Membuat Daftar</h2>
+
+<p>Widget {@link android.support.v7.widget.RecyclerView} adalah
+versi {@link android.widget.ListView} yang lebih maju dan fleksibel. Widget ini adalah kontainer untuk menampilkan set data
+besar yang bisa digulir secara sangat efisien dengan mempertahankan tampilan dalam jumlah terbatas. Gunakan
+widget {@link android.support.v7.widget.RecyclerView} bila Anda memiliki kumpulan data dengan elemen
+yang berubah saat runtime berdasarkan tindakan pengguna atau kejadian jaringan.</p>
+
+<p>Kelas {@link android.support.v7.widget.RecyclerView} menyederhanakan penampilan dan penanganan
+set data yang besar dengan menyediakan:</p>
+
+<ul>
+  <li>Pengelola layout untuk memosisikan item</li>
+  <li>Animasi default untuk operasi item umum, misalnya penghapusan atau penambahan item</li>
+</ul>
+
+<p>Anda juga memiliki keluwesan untuk mendefinisikan pengelola layout custom dan animasi untuk widget {@link
+android.support.v7.widget.RecyclerView}.</p>
+
+<img src="{@docRoot}training/material/images/RecyclerView.png" alt="" width="550" height="106" />
+<p class="img-caption">
+<strong>Gambar 1</strong>. Widget <code>RecyclerView</code>.
+</p>
+
+<p>Untuk menggunakan widget {@link android.support.v7.widget.RecyclerView}, Anda harus menetapkan
+adaptor dan pengelola layout. Untuk membuat adaptor, perluas kelas {@link
+android.support.v7.widget.RecyclerView.Adapter RecyclerView.Adapter}. Detail
+implementasi bergantung pada detail set data Anda dan tipe tampilan. Untuk informasi selengkapnya,
+ lihat <a href="#RVExamples">contoh-contoh</a> di bawah.</p>
+
+<div style="float:right">
+<img src="{@docRoot}design/material/images/list_mail.png" alt="" width="250" height="426" />
+<p class="img-caption" style="margin-left:8px">
+<strong>Gambar 2</strong> - Daftar berisi <code>RecyclerView</code>.
+</p>
+</div>
+
+<p><strong>Pengelola layout</strong> memosisikan tampilan item dalam {@link
+android.support.v7.widget.RecyclerView} dan menentukan waktu untuk menggunakan ulang tampilan item yang tidak
+lagi terlihat oleh pengguna. Untuk menggunakan ulang (atau <em>mendaur ulang</em>) tampilan, pengelola layout bisa meminta
+adaptor untuk mengganti konten tampilan dengan elemen lain dalam dataset. Mendaur ulang
+tampilan dengan cara ini akan meningkatkan kinerja karena menghindari pembuatan tampilan yang tidak diperlukan atau
+melakukan pencarian {@link android.app.Activity#findViewById findViewById()} yang mahal.</p>
+
+<p>{@link android.support.v7.widget.RecyclerView} menyediakan semua pengelola layout bawaan ini:</p>
+
+<ul>
+<li>{@link android.support.v7.widget.LinearLayoutManager} menampilkan item dalam
+daftar gulir vertikal atau horizontal.</li>
+<li>{@link android.support.v7.widget.GridLayoutManager} menampilkan item dalam petak.</li>
+<li>{@link android.support.v7.widget.StaggeredGridLayoutManager} menampilkan item dalam petak zigzag.</li>
+</ul>
+
+<p>Untuk membuat pengelola layout custom, perluas kelas {@link
+android.support.v7.widget.RecyclerView.LayoutManager RecyclerView.LayoutManager}.</p>
+
+<h3>Animasi</h3>
+
+<p>Animasi untuk menambahkan dan menghapus item diaktifkan secara default di {@link
+android.support.v7.widget.RecyclerView}. Untuk menyesuaikan animasi ini, perluas kelas
+{@link android.support.v7.widget.RecyclerView.ItemAnimator RecyclerView.ItemAnimator}dan gunakan
+metode {@link android.support.v7.widget.RecyclerView#setItemAnimator RecyclerView.setItemAnimator()}.
+</p>
+
+<h3 id="RVExamples">Contoh</h3>
+
+<p>Contoh kode berikut memperagakan cara menambahkan
+{@link android.support.v7.widget.RecyclerView} ke layout:</p>
+
+<pre>
+&lt;!-- A RecyclerView with some commonly used attributes -->
+&lt;android.support.v7.widget.RecyclerView
+    android:id="@+id/my_recycler_view"
+    android:scrollbars="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"/>
+</pre>
+
+<p>Begitu Anda menambahkan widget {@link android.support.v7.widget.RecyclerView} ke layout,
+dapatkan pengatur atau handle objek itu, hubungkan dengan pengelola layout, dan sertakan adaptor untuk data
+yang akan ditampilkan:</p>
+
+<pre>
+public class MyActivity extends Activity {
+    private RecyclerView mRecyclerView;
+    private RecyclerView.Adapter mAdapter;
+    private RecyclerView.LayoutManager mLayoutManager;
+
+    &#64;Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.my_activity);
+        mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
+
+        // use this setting to improve performance if you know that changes
+        // in content do not change the layout size of the RecyclerView
+        mRecyclerView.setHasFixedSize(true);
+
+        // use a linear layout manager
+        mLayoutManager = new LinearLayoutManager(this);
+        mRecyclerView.setLayoutManager(mLayoutManager);
+
+        // specify an adapter (see also next example)
+        mAdapter = new MyAdapter(myDataset);
+        mRecyclerView.setAdapter(mAdapter);
+    }
+    ...
+}
+</pre>
+
+<p>Adaptor menyediakan akses ke item dataset Anda, membuat tampilan untuk item, dan
+mengganti konten sebagian tampilan dengan item data baru bila item semula tidak lagi
+terlihat. Contoh kode berikut menampilkan implementasi sederhana untuk sebuah dataset yang terdiri dari
+larik string yang ditampilkan dengan menggunakan widget {@link android.widget.TextView}:</p>
+
+<pre>
+public class MyAdapter extends RecyclerView.Adapter&lt;MyAdapter.ViewHolder> {
+    private String[] mDataset;
+
+    // Provide a reference to the views for each data item
+    // Complex data items may need more than one view per item, and
+    // you provide access to all the views for a data item in a view holder
+    public static class ViewHolder extends RecyclerView.ViewHolder {
+        // each data item is just a string in this case
+        public TextView mTextView;
+        public ViewHolder(TextView v) {
+            super(v);
+            mTextView = v;
+        }
+    }
+
+    // Provide a suitable constructor (depends on the kind of dataset)
+    public MyAdapter(String[] myDataset) {
+        mDataset = myDataset;
+    }
+
+    // Create new views (invoked by the layout manager)
+    &#64;Override
+    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
+                                                   int viewType) {
+        // create a new view
+        View v = LayoutInflater.from(parent.getContext())
+                               .inflate(R.layout.my_text_view, parent, false);
+        // set the view's size, margins, paddings and layout parameters
+        ...
+        ViewHolder vh = new ViewHolder(v);
+        return vh;
+    }
+
+    // Replace the contents of a view (invoked by the layout manager)
+    &#64;Override
+    public void onBindViewHolder(ViewHolder holder, int position) {
+        // - get element from your dataset at this position
+        // - replace the contents of the view with that element
+        holder.mTextView.setText(mDataset[position]);
+
+    }
+
+    // Return the size of your dataset (invoked by the layout manager)
+    &#64;Override
+    public int getItemCount() {
+        return mDataset.length;
+    }
+}
+</pre>
+
+
+<div style="float:right;margin-top:15px;margin-left:30px">
+<img src="{@docRoot}design/material/images/card_travel.png" alt="" width="225" height="383">
+<p class="img-caption" style="margin-left:12px">
+<strong>Gambar 3</strong>. Contoh kartu.
+</p>
+</div>
+
+<h2 id="CardView">Membuat Kartu</h2>
+
+<p>{@link android.support.v7.widget.CardView} memperluas kelas {@link android.widget.FrameLayout}
+dan memungkinkan Anda menampilkan informasi dalam kartu yang memiliki tampilan konsisten lintas platform. Widget {@link
+android.support.v7.widget.CardView} bisa memiliki bayangan dan sudut membulat.</p>
+
+<p>Untuk membuat kartu dengan bayangan, gunakan atribut <code>card_view:cardElevation</code>.
+{@link android.support.v7.widget.CardView} menggunakan elevasi nyata dan bayangan dinamis pada Android 5.0
+(API level 21) ke atas dan memundurkan ke implementasi bayangan terprogram pada versi terdahulu.
+Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/compatibility.html">Mempertahankan
+Kompatibilitas</a>.</p>
+
+<p>Gunakan properti-properti ini untuk menyesuaikan penampilan
+widget {@link android.support.v7.widget.CardView}:</p>
+
+<ul>
+  <li>Untuk mengatur radius sudut pada layout Anda, gunakan atribut <code>card_view:cardCornerRadius</code>.
+</li>
+  <li>Untuk mengatur radius sudut dalam kode Anda, gunakan metode <code>CardView.setRadius</code>.</li>
+  <li>Untuk mengatur warna latar belakang kartu, gunakan atribut <code>card_view:cardBackgroundColor</code>.
+</li>
+</ul>
+
+<p>Contoh kode berikut menampilkan cara menyertakan widget {@link android.support.v7.widget.CardView}
+dalam layout:</p>
+
+<pre>
+&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    xmlns:card_view="http://schemas.android.com/apk/res-auto"
+    ... >
+    &lt;!-- A CardView that contains a TextView -->
+    &lt;android.support.v7.widget.CardView
+        xmlns:card_view="http://schemas.android.com/apk/res-auto"
+        android:id="@+id/card_view"
+        android:layout_gravity="center"
+        android:layout_width="200dp"
+        android:layout_height="200dp"
+        card_view:cardCornerRadius="4dp">
+
+        &lt;TextView
+            android:id="@+id/info_text"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+    &lt;/android.support.v7.widget.CardView>
+&lt;/LinearLayout>
+</pre>
+
+<p>Untuk informasi selengkapnya, lihat referensi API untuk {@link android.support.v7.widget.CardView}.</p>
+
+
+<h2 id="Dependencies">Menambahkan Dependensi</h2>
+
+<p>Widget {@link android.support.v7.widget.RecyclerView} dan {@link android.support.v7.widget.CardView}
+adalah bagian dari <a href="{@docRoot}tools/support-library/features.html#v7">v7 Support
+Library</a>. Untuk menggunakan widget dalam proyek Anda, tambahkan
+<a href="{@docRoot}sdk/installing/studio-build.html#dependencies">dependensi Gradle</a> ini ke
+modul aplikasi Anda:</p>
+
+<pre>
+dependencies {
+    ...
+    compile 'com.android.support:cardview-v7:21.0.+'
+    compile 'com.android.support:recyclerview-v7:21.0.+'
+}
+</pre>
diff --git a/docs/html-intl/intl/id/training/material/shadows-clipping.jd b/docs/html-intl/intl/id/training/material/shadows-clipping.jd
new file mode 100644
index 0000000..5431926
--- /dev/null
+++ b/docs/html-intl/intl/id/training/material/shadows-clipping.jd
@@ -0,0 +1,133 @@
+page.title=Mendefinisikan Bayangan dan Memangkas Tampilan
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>Pelajaran ini mengajarkan Anda cara</h2>
+<ol>
+  <li><a href="#Elevation">Menetapkan Elevasi pada Tampilan Anda</a></li>
+  <li><a href="#Shadows">Menyesuaikan Bayangan dan Garis Luar Tampilan</a></li>
+  <li><a href="#Clip">Memangkas Tampilan</a></li>
+</ol>
+<h2>Anda juga harus membaca</h2>
+<ul>
+  <li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
+  <li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
+</ul>
+</div>
+</div>
+
+<p>Desain bahan memperkenalkan elevasi untuk elemen-elemen UI. Elevasi membantu pengguna memahami
+arti penting relatif masing-masing elemen dan memfokuskan perhatian pada tugas yang ada.</p>
+
+<p>Elevasi tampilan, yang dinyatakan dengan properti Z, menentukan tampilan visual
+bayangannya: tampilan dengan nilai Z lebih tinggi menghasilkan bayangan lebih besar dan lebih halus. Tampilan dengan nilai Z lebih tinggi menutupi
+tampilan dengan nilai Z lebih rendah; akan tetapi, nilai Z tampilan tidak memengaruhi ukuran tampilan.</p>
+
+<p>Bayangan digambar oleh induk tampilan yang dinaikkan, sehingga terkena pemangkasan standar tampilan,
+yang dipangkas oleh induk secara default.</p>
+
+<p>Elevasi juga berguna untuk membuat animasi tempat memunculkan widget untuk sementara di atas
+bidang tampilan saat melakukan beberapa tindakan.</p>
+
+<p>Untuk informasi selengkapnya tentang elevasi dalam desain bahan, lihat
+<a href="http://www.google.com/design/spec/what-is-material/objects-in-3d-space.html">Objek
+di ruang 3D</a>.</p>
+
+
+<h2 id="Elevation">Menetapkan Elevasi pada Tampilan Anda</h2>
+
+<p>Nilai Z untuk tampilan memiliki dua komponen:
+
+<ul>
+<li>Elevasi: Komponen statis.</li>
+<li>Transformasi: Komponen dinamis yang digunakan untuk animasi.</li>
+</ul>
+
+<p><code>Z = elevation + translationZ</code></p>
+
+<img src="{@docRoot}training/material/images/shadows-depth.png" width="580" height="261" alt="" />
+<p class="img-caption"><strong>Gambar 1</strong> - Bayangan untuk berbagai elevasi tampilan.</p>
+
+<p>Untuk mengatur elevasi tampilan dalam definisi layout, gunakan atribut <code>android:elevation</code>.
+ Untuk mengatur elevasi tampilan dalam kode aktivitas, gunakan
+metode {@link android.view.View#setElevation View.setElevation()}.</p>
+
+<p>Untuk mengatur transformasi tampilan, gunakan metode {@link android.view.View#setTranslationZ
+View.setTranslationZ()}.</p>
+
+<p>Metode {@link android.view.ViewPropertyAnimator#z ViewPropertyAnimator.z()} dan {@link
+android.view.ViewPropertyAnimator#translationZ ViewPropertyAnimator.translationZ()} yang baru memudahkan
+Anda menganimasikan elevasi tampilan. Untuk informasi selengkapnya, lihat referensi API untuk
+{@link android.view.ViewPropertyAnimator} dan panduan pengembang <a href="{@docRoot}guide/topics/graphics/prop-animation.html">Animasi Properti</a>.
+</p>
+
+<p>Anda juga bisa menggunakan {@link android.animation.StateListAnimator}
+untuk menetapkan animasi ini secara deklaratif. Ini khususnya berguna bila
+perubahan status memicu animasi, seperti saat seorang pengguna menekan tombol. Untuk informasi selengkapnya, lihat
+<a href="{@docRoot}training/material/animations.html#ViewState">Menganimasikan Perubahan Status Tampilan</a>.</p>
+
+<p>Nilai Z diukur dengan satuan dp (density-independent pixel).</p>
+
+
+<h2 id="Shadows">Menyesuaikan Bayangan dan Garis Luar Tampilan</h2>
+
+<p>Batas-batas drawable latar belakang tampilan menentukan bentuk default bayangannya.
+<strong>Garis luar</strong> menyatakan bentuk luar objek grafis dan mendefinisikan
+bidang riak untuk umpan balik sentuh.</p>
+
+<p>Perhatikan tampilan ini, yang didefinisikan dengan drawable latar belakang:</p>
+
+<pre>
+&lt;TextView
+    android:id="@+id/myview"
+    ...
+    android:elevation="2dp"
+    android:background="@drawable/myrect" />
+</pre>
+
+<p>Drawable latar belakang didefinisikan sebagai persegi panjang dengan sudut membulat:</p>
+
+<pre>
+&lt;!-- res/drawable/myrect.xml -->
+&lt;shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    &lt;solid android:color="#42000000" />
+    &lt;corners android:radius="5dp" />
+&lt;/shape>
+</pre>
+
+<p>Tampilan ini menghasilkan bayangan dengan sudut membulat, karena drawable latar belakang mendefinisikan
+garis luar tampilan. Memberikan garis luar custom akan mengesampingkan bentuk default bayangan tampilan.</p>
+
+<p>Untuk mendefinisikan garis luar custom suatu tampilan dalam kode Anda:<p>
+
+<ol>
+<li>Perluas kelas {@link android.view.ViewOutlineProvider}.</li>
+<li>Kesampingkan metode {@link android.view.ViewOutlineProvider#getOutline getOutline()}.</li>
+<li>Tetapkan penyedia garis luar baru untuk tampilan Anda dengan metode {@link
+android.view.View#setOutlineProvider View.setOutlineProvider()}.</li>
+</ol>
+
+<p>Anda bisa membuat garis luar lonjong dan persegi panjang yang bersudut membulat dengan menggunakan metode dalam
+kelas {@link android.graphics.Outline}. Penyedia garis luar default untuk tampilan memperoleh garis luar
+dari latar belakang tampilan. Untuk mencegah tampilan menghasilkan bayangan, atur penyedia garis luarnya
+ke <code>null</code>.</p>
+
+
+<h2 id="Clip">Memangkas Tampilan</h2>
+
+<p>Memangkas tampilan memudahkan Anda mengubah bentuk tampilan. Anda bisa memangkas tampilan agar
+konsistensi dengan elemen desain lainnya atau mengubah bentuk tampilan untuk merespons input pengguna.
+Anda bisa memangkas tampilan hingga area garis luarnya dengan menggunakan metode {@link android.view.View#setClipToOutline
+View.setClipToOutline()} atau atribut <code>android:clipToOutline</code>. Hanya
+garis-garis luar persegi panjang, lingkaran, dan persegi panjang bersudut bulat yang mendukung pemangkasan, seperti yang ditentukan oleh
+metode {@link android.graphics.Outline#canClip Outline.canClip()}.</p>
+
+<p>Untuk memangkas tampilan ke bentuk drawable, atur drawable sebagai latar belakang tampilan
+(seperti yang ditampilkan di atas) dan panggil metode {@link android.view.View#setClipToOutline View.setClipToOutline()}.
+</p>
+
+<p>Memangkas tampilan adalah operasi yang mahal; jadi, jangan animasikan bentuk yang Anda gunakan
+untuk memangkas tampilan. Untuk memperoleh efek ini, gunakan animasi <a href="{@docRoot}training/material/animations.html#Reveal">Reveal Effect</a>.</p>
diff --git a/docs/html-intl/intl/id/training/material/theme.jd b/docs/html-intl/intl/id/training/material/theme.jd
new file mode 100644
index 0000000..5acdcd2
--- /dev/null
+++ b/docs/html-intl/intl/id/training/material/theme.jd
@@ -0,0 +1,131 @@
+page.title=Menggunakan Tema Bahan
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>Pelajaran ini mengajarkan Anda cara</h2>
+<ol>
+  <li><a href="#ColorPalette">Menyesuaikan Palet Warna</a></li>
+  <li><a href="#StatusBar">Menyesuaikan Baris Status</a></li>
+  <li><a href="#Inheritance">Tampilan Setiap Tema</a></li>
+</ol>
+<h2>Anda juga harus membaca</h2>
+<ul>
+  <li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
+  <li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
+</ul>
+</div>
+</div>
+
+
+<p>Tema bahan yang baru menyediakan:</p>
+
+<ul>
+  <li>Widget sistem yang memungkinkan Anda mengatur palet warnanya</li>
+  <li>Animasi umpan balik sentuh untuk widget sistem</li>
+  <li>Animasi transisi aktivitas</li>
+</ul>
+
+<p>Anda bisa menyesuaikan tampilan tema bahan
+sesuai dengan identitas merek Anda dengan palet warna yang Anda kontrol. Anda bisa mewarnai action-bar dan
+baris status dengan menggunakan atribut tema, seperti yang ditampilkan dalam <a href="#fig3">Gambar 3</a>.</p>
+
+<p>Widget sistem memiliki desain baru dan animasi umpan balik sentuh. Anda bisa menyesuaikan
+palet warna, animasi umpan balik sentuh, dan transisi aktivitas untuk aplikasi.</p>
+
+<p>Tema bahan didefinisikan sebagai:</p>
+
+<ul>
+  <li><code>@android:style/Theme.Material</code> (versi gelap)</li>
+  <li><code>@android:style/Theme.Material.Light</code> (versi terang)</li>
+  <li><code>@android:style/Theme.Material.Light.DarkActionBar</code></li>
+</ul>
+
+<p>Untuk daftar gaya bahan yang bisa Anda gunakan, lihat referensi API untuk
+{@link android.R.style R.style}.</p>
+
+<!-- two columns, dark/light material theme example -->
+<div style="width:700px;margin-top:25px;margin-bottom:10px">
+<div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
+  <img src="{@docRoot}design/material/images/MaterialDark.png" width="500" height="238">
+  <div style="width:170px;margin:0 auto">
+  <p style="margin-top:8px;font-size:12px"><strong>Gambar 1</strong>. Tema bahan gelap</p>
+  </div>
+</div>
+<div style="float:left;width:250px;margin-right:0px;">
+  <img src="{@docRoot}design/material/images/MaterialLight.png" width="500" height="238">
+  <div style="width:170px;margin:0 auto">
+  <p style="margin-top:8px;font-size:12px"><strong>Gambar 2</strong>. Tema bahan terang</p>
+  </div>
+</div>
+<br style="clear:left">
+</div>
+
+<p class="note">
+<strong>Catatan:</strong> Tema bahan hanya tersedia di Android 5.0 (API level 21)
+ke atas. <a href="{@docRoot}tools/support-library/features.html#v7">v7 Support Library</a>
+menyediakan tema dengan gaya desain bahan untuk beberapa widget dan dukungan untuk menyesuaikan
+palet warna. Untuk informasi selengkapnya, lihat
+<a href="{@docRoot}training/material/compatibility.html">Mempertahankan Kompatibilitas</a>.
+</p>
+
+
+<h2 id="ColorPalette">Menyesuaikan Palet Warna</h2>
+
+<p style="margin-bottom:30px">Untuk menyesuaikan warna dasar tema agar cocok dengan merek Anda, definisikan
+warna custom menggunakan atribut tema saat Anda mewariskan dari tema bahan:</p>
+
+<pre>
+&lt;resources>
+  &lt;!-- inherit from the material theme -->
+  &lt;style name="AppTheme" parent="android:Theme.Material">
+    &lt;!-- Main theme colors -->
+    &lt;!--   your app branding color for the app bar -->
+    &lt;item name="android:colorPrimary">@color/primary&lt;/item>
+    &lt;!--   darker variant for the status bar and contextual app bars -->
+    &lt;item name="android:colorPrimaryDark">@color/primary_dark&lt;/item>
+    &lt;!--   theme UI controls like checkboxes and text fields -->
+    &lt;item name="android:colorAccent">@color/accent&lt;/item>
+  &lt;/style>
+&lt;/resources>
+</pre>
+
+<div style="float:right;margin-left:25px;margin-top:20px;margin-bottom:10px" id="fig3">
+<img src="{@docRoot}training/material/images/ThemeColors.png" width="250" height="445" />
+<p class="img-caption" style="margin-bottom:0px">
+<strong>Gambar 3.</strong> Menyesuaikan tema bahan.</p>
+</div>
+
+
+<h2 id="StatusBar">Menyesuaikan Baris Status</h2>
+
+<p>Tema bahan memungkinkan Anda menyesuaikan baris status dengan mudah; jadi Anda bisa menetapkan
+warna yang cocok dengan merek Anda dan memberikan kontras yang cukup untuk menampilkan ikon status putih. Untuk
+mengatur warna custom bagi baris status, gunakan atribut <code>android:statusBarColor</code> bila
+Anda memperluas tema bahan. Secara default, <code>android:statusBarColor</code> mewarisi
+nilai <code>android:colorPrimaryDark</code>.</p>
+
+<p>Anda juga bisa menggambar sendiri di belakang baris status. Misalnya, jika Anda ingin menampilkan
+baris status secara transparan di atas foto, dengan gradasi gelap yang halus untuk memastikan
+ikon status putih tetap terlihat. Caranya, atur atribut <code>android:statusBarColor</code> ke
+<code>&#64;android:color/transparent</code> dan sesuaikan flag jendela seperti yang diperlukan. Anda juga bisa
+menggunakan metode {@link android.view.Window#setStatusBarColor Window.setStatusBarColor()} untuk
+animasi atau pemudaran.</p>
+
+<p class="note">
+<strong>Catatan:</strong> Baris status harus selalu memiliki delineasi yang jelas dari
+toolbar utama, kecuali bila Anda menampilkan gambar detail atau konten media tepi-ke-tepi di belakang
+baris ini dan bila Anda menggunakan gradasi untuk memastikan ikon tetap terlihat.
+</p>
+
+<p>Bila Anda menyesuaikan baris navigasi dan baris status, jadikan keduanya transparan atau modifikasi
+baris status saja. Baris navigasi harus tetap hitam di semua kasus lainnya.</p>
+
+
+<h2 id="Inheritance">Tampilan Setiap Tema</h3>
+
+<p>Elemen dalam definisi layout XML bisa menetapkan atribut <code>android:theme</code>,
+yang merujuk sumber daya tema. Atribut ini memodifikasi tema untuk elemen itu dan setiap
+elemen anak, yang berguna untuk mengubah palet warna tema dalam porsi tertentu
+pada antarmuka.</p>
diff --git a/docs/html-intl/intl/id/training/tv/playback/picture-in-picture.jd b/docs/html-intl/intl/id/training/tv/playback/picture-in-picture.jd
new file mode 100644
index 0000000..41af6de
--- /dev/null
+++ b/docs/html-intl/intl/id/training/tv/playback/picture-in-picture.jd
@@ -0,0 +1,213 @@
+page.title=Gambar-dalam-gambar
+page.keywords=pratinjau,sdk,PIP,Gambar-dalam-gambar
+page.tags=androidn
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>Dalam dokumen ini</h2>
+<ol>
+  <li><a href="#declaring">Mendeklarasikan Bahwa Aktivitas Anda Mendukung
+Gambar-dalam-gambar</a></li>
+  <li><a href="#pip_button">Mengalihkan Aktivitas Anda ke Gambar-dalam-gambar</a>
+</li>
+  <li><a href="#handling_ui">Menangani UI Selama Gambar-dalam-gambar</a>
+</li>
+  <li><a href="#continuing_playback">Melanjutkan Pemutaran Video Saat dalam
+Gambar-dalam-gambar</a></li>
+  <li><a href="#single_playback">Menggunakan Aktivitas Pemutaran Tunggal untuk
+ Gambar-dalam-gambar</a></li>
+  <li><a href="#best">Praktik Terbaik</a></li>
+</ol>
+
+<h2>Lihat Juga</h2>
+<ol>
+  <li><a href="{@docRoot}preview/features/multi-window.html">Dukungan
+Multi-Jendela</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>Di Android N, pengguna Android TV sekarang bisa menonton video
+dalam jendela yang disematkan di sudut layar saat menyusuri
+aplikasi. Mode gambar-dalam-gambar (PIP) memungkinkan aplikasi menjalankan aktivitas
+video dalam jendela yang disematkan selagi aktivitas lain tetap berjalan di
+latar belakang. Jendela PIP memungkinkan pengguna melakukan multitasking saat menggunakan aplikasi Anda, yang
+membantu pengguna menjadi lebih produktif.</p>
+
+<p>Aplikasi Anda bisa memutuskan kapan memicu mode PIP. Inilah beberapa contoh
+kapan memasuki mode PIP:</p>
+
+<ul>
+<li>Aplikasi Anda bisa memindahkan video ke dalam mode PIP bila pengguna mengarah
+mundur dari video untuk menjelajah materi lainnya.</li>
+<li>Aplikasi Anda bisa mengalihkan video ke dalam mode PIP selagi pengguna menonton akhir episode
+dari materi. Layar utama menampilkan informasi
+promosi atau rangkuman tentang episode berikutnya dalam seri tersebut.</li>
+<li>Aplikasi Anda bisa menyediakan suatu cara bagi pengguna untuk mengantre materi tambahan selagi
+mereka menonton video. Video terus dimainkan dalam mode PIP selagi layar
+utama menampilkan aktivitas pemilihan materi.</li>
+</ul>
+
+<p>Jendela PIP memiliki luas 240x135 dp dan ditampilkan di layer paling atas pada salah satu
+dari empat sudut layar, yang dipilih oleh sistem. Pengguna bisa memunculkan
+menu PIP yang memungkinkan mereka untuk beralih mode dari jendela PIP ke layar penuh, atau menutup jendela
+PIP, dengan menekan dan menahan tombol <b>Beranda</b> pada remote. Jika video
+lain mulai diputar pada layar utama, jendela PIP secara otomatis
+ditutup. Pengguna juga bisa menutup jendela PIP melalui Recents.</p>
+
+<img src="{@docRoot}images/android-7.0/pip-active.png" />
+<p class="img-caption"><strong>Gambar 1.</strong> Video
+Gambar-dalam-gambar terlihat di sudut layar selagi pengguna menjelajahi materi pada layar
+utama.</p>
+
+<p>PIP memanfaatkan API multi-jendela yang tersedia di Android N untuk
+menyediakan jendela hamparan video yang disematkan. Untuk menambahkan PIP ke aplikasi, Anda harus
+mendaftarkan aktivitas yang mendukung PIP, mengalihkan aktivitas Anda ke mode PIP bila
+diperlukan, serta memastikan elemen UI disembunyikan dan pemutaran video berlanjut bila
+aktivitas dalam mode PIP.</p>
+
+<h2 id="declaring">Mendeklarasikan Bahwa Aktivitas Anda Mendukung Gambar-dalam-gambar</h2>
+
+<p>Secara default, sistem tidak secara otomatis mendukung PIP untuk aplikasi.
+Jika Anda ingin mendukung PIP dalam aplikasi, daftarkan aktivitas
+video Anda dalam manifes dengan menyetel
+<code>android:supportsPictureInPicture</code> dan
+<code>android:resizeableActivity</code> ke <code>true</code>. Juga, tetapkan
+bahwa aktivitas Anda menangani perubahan konfigurasi layout sehingga aktivitas
+Anda tidak diluncurkan ulang saat terjadi perubahan layout selama transisi mode PIP.</p>
+
+<pre>
+&lt;activity android:name="VideoActivity"
+    android:resizeableActivity="true"
+    android:supportsPictureInPicture="true"
+    android:configChanges=
+        "screenSize|smallestScreenSize|screenLayout|orientation"
+    ...
+</pre>
+
+<p>Saat mendaftarkan aktivitas Anda, ingatlah bahwa dalam mode PIP aktivitas
+Anda akan ditampilkan pada jendela hamparan kecil pada layar TV. Aktivitas
+pemutaran video dengan UI minimal akan memberikan pengalaman pengguna terbaik. Aktivitas yang
+mengandung elemen UI kecil mungkin tidak memberikan pengalaman pengguna yang baik
+ketika beralih ke mode PIP, karena pengguna tidak dapat melihat elemen UI secara jelas
+di jendela PIP.</p>
+
+<h2 id="pip_button">Mengalihkan Aktivitas Anda ke Gambar-dalam-gambar</h2>
+
+Bila Anda perlu untuk mengalihkan aktivitas ke mode PIP, panggil
+<code>Activity.enterPictureInPictureMode()</code>. Contoh berikut mengalihkan
+ke mode PIP bila pengguna memilih tombol PIP khusus pada baris
+kontrol media:</p>
+
+<pre>
+&#64;Override
+public void onActionClicked(Action action) {
+    if (action.getId() == R.id.lb_control_picture_in_picture) {
+        getActivity().enterPictureInPictureMode();
+        return;
+    }
+    ...
+</pre>
+
+<p>Menambahkan tombol PIP ke baris kontrol media Anda akan memungkinkan pengguna dengan mudah beralih
+ke mode PIP selagi mengontrol pemutaran video.</p>
+
+<img src="{@docRoot}images/android-7.0/pip-button.png" />
+<p class="img-caption"><strong>Gambar 1.</strong> Tombol
+gambar-dalam-gambar pada baris kontrol media.</p>
+
+<p>Android N menyertakan kelas
+<code>PlaybackControlsRow.PictureInPictureAction</code> baru yang mendefinisikan
+tindakan PIP baris kontrol dan menggunakan ikon PIP.</p>
+
+<h2 id="handling_ui">Menangani UI Selama Gambar-dalam-gambar</h2>
+
+<p>Bila aktivitas memasuki mode PIP, aktivitas Anda seharusnya hanya menampilkan pemutaran
+video. Buang elemen UI sebelum aktivitas Anda memasuki PIP,
+dan pulihkan elemen ini bila aktivitas Anda beralih ke layar penuh lagi.
+Ganti <code>Activity.onPictureInPictureModeChanged()</code> atau
+<code>Fragment.onPictureInPictureModeChanged()</code> dan aktifkan atau
+nonaktifkan elemen UI saat diperlukan, misalnya:</p>
+
+<pre>
+&#64;Override
+public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
+    if (isInPictureInPictureMode) {
+        // Hide the controls in picture-in-picture mode.
+        ...
+    } else {
+        // Restore the playback UI based on the playback status.
+        ...
+    }
+}
+</pre>
+
+<h2 id="continuing_playback">Melanjutkan Pemutaran Video Saat dalam
+Gambar-dalam-gambar</h2>
+
+<p>Bila aktivitas Anda beralih ke PIP, sistem akan menganggap aktivitas tersebut berada dalam
+keadaan berhenti sementara, dan akan memanggil metode <code>onPause()</code> aktivitas Anda. Pemutaran
+video tidak boleh berhenti sementara dan harus terus diputar jika aktivitas tersebut
+berhenti sementara karena mode PIP. Periksa PIP dalam metode
+<code>onPause()</code> aktivitas Anda dan tangani pemutaran dengan tepat,
+misalnya:</p>
+
+<pre>
+&#64;Override
+public void onPause() {
+    // If called while in PIP mode, do not pause playback
+    if (isInPictureInPictureMode()) {
+        // Continue playback
+        ...
+    }
+    // If paused but not in PIP, pause playback if necessary
+    ...
+}
+</pre>
+
+<p>Bila aktivitas meninggalkan mode PIP dan kembali ke mode layar penuh, sistem
+akan melanjutkan aktivitas Anda dan memanggil metode <code>onResume()</code>.</p>
+
+<h2 id="single_playback">Menggunakan Aktivitas Pemutaran Tunggal untuk
+ Gambar-dalam-gambar</h2>
+
+<p>Di aplikasi Anda, seorang pengguna bisa memilih video baru saat menyusuri materi di
+layar utama, selagi aktivitas pemutaran video dalam mode PIP. Putar
+video baru di aktivitas pemutaran yang ada dalam mode layar penuh, sebagai ganti
+meluncurkan aktivitas baru yang dapat membingungkan pengguna.</p>
+
+<p>Guna memastikan aktivitas tunggal digunakan untuk permintaan pemutaran video dan
+beralih ke atau dari mode PIP bila dibutuhkan, setel
+<code>android:launchMode</code> aktivitas ke <code>singleTask</code> dalam manifes Anda:
+</p>
+
+<pre>
+&lt;activity android:name="VideoActivity"
+    ...
+    android:supportsPictureInPicture="true"
+    android:launchMode="singleTask"
+    ...
+</pre>
+
+<p>Di aktivitas Anda, ganti {@link android.app.Activity#onNewIntent
+Activity.onNewIntent()} dan tangani video baru, yang akan menghentikan pemutaran video
+jika diperlukan.</p>
+
+<h2 id="best">Praktik Terbaik</h2>
+
+<p>PIP ditujukan untuk aktivitas yang memutar video layar penuh. Saat mengalihkan
+aktivitas Anda ke mode PIP, hindari menampilkan apa pun selain materi video.
+Pantau saat aktivitas Anda memasuki mode PIP dan sembunyikan elemen UI, seperti dijelaskan
+dalam <a href="#handling_ui">Menangani UI Selama Gambar-dalam-gambar</a>.</p>
+
+<p>Karena jendela PIP ditampilkan sebagai jendela mengambang di sudut
+layar, Anda harus menghindari menampilkan informasi penting di layar utama
+di area mana saja yang bisa terhalang oleh jendela PIP.</p>
+
+<p>Bila aktivitas ada berada dalam mode PIP, secara default aktivitas itu tidak mendapatkan fokus masukan. Untuk
+menerima kejadian masukan saat dalam mode PIP, gunakan
+<code>MediaSession.setMediaButtonReceiver()</code>.</p>
diff --git a/docs/html-intl/intl/id/training/tv/tif/content-recording.jd b/docs/html-intl/intl/id/training/tv/tif/content-recording.jd
new file mode 100644
index 0000000..3389dbf
--- /dev/null
+++ b/docs/html-intl/intl/id/training/tv/tif/content-recording.jd
@@ -0,0 +1,142 @@
+page.title=Perekaman TV
+page.keywords=pratinjau,sdk,tv,perekaman
+page.tags=androidn
+page.image=images/cards/card-nyc_2x.jpg
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+  <h2>Dalam dokumen ini</h2>
+  <ol>
+    <li><a href="#supporting">Menunjukkan Dukungan untuk Perekaman</a></li>
+    <li><a href="#recording">Merekam Sesi</a></li>
+    <li><a href="#errors">Menangani Kesalahan Perekaman</a></li>
+    <li><a href="#sessions">Mengelola Sesi yang Direkam</a></li>
+    <li><a href="#best">Praktik Terbaik</a></li>
+  </ol>
+</div>
+</div>
+
+<p>Layanan masukan TV memungkinkan pengguna menghentikan sementara dan melanjutkan pemutaran saluran melalui
+API perekaman. Android N telah berkembang hingga ke perekaman
+dengan memungkinkan pengguna menyimpan beberapa sesi rekaman.</p>
+
+<p>Pengguna bisa menjadwalkan rekaman terlebih dahulu, atau memulai rekaman sambil menonton
+suatu acara. Setelah sistem menyimpan rekaman, pengguna bisa menjelajah, menata,
+dan memutar kembali rekaman tersebut menggunakan aplikasi TV di sistem.</p>
+
+<p>Jika Anda ingin menyediakan fungsi perekaman untuk layanan masukan TV,
+Anda harus menunjukkan pada sistem bahwa aplikasi Anda mendukung perekaman, mengimplementasikan
+kemampuan merekam program, menangani dan mengomunikasikan kesalahan yang muncul
+selama perekaman, dan mengelola sesi perekaman Anda.</p>
+
+<p class="note"><strong>Catatan:</strong> Aplikasi Live Channels belum
+menyediakan cara bagi pengguna untuk membuat atau mengakses perekaman. Hingga dibuat perubahan
+di aplikasi Live Channels, mungkin sulit menguji sepenuhnya pengalaman
+perekaman untuk layanan masukan TV Anda.</p>
+
+<h2 id="supporting">Menunjukkan Dukungan untuk Perekaman</h2>
+
+<p>Untuk memberi tahu sistem bahwa layanan masukan TV Anda mendukung perekaman, setel
+atribut <code>android:canRecord</code> di file XML metadata layanan Anda
+ke <code>true</code>:
+</p>
+
+<pre>
+&lt;tv-input xmlns:android="http://schemas.android.com/apk/res/android"
+  <b>android:canRecord="true"</b>
+  android:setupActivity="com.example.sampletvinput.SampleTvInputSetupActivity" /&gt;
+</pre>
+
+<p>Untuk informasi selengkapnya mengenai layanan file metadata, lihat
+<a href="{@docRoot}training/tv/tif/tvinput.html#manifest">Mendeklarasikan Layanan Masukan TV Anda
+di Manifes</a>.
+</p>
+
+<p>Atau, Anda bisa menunjukkan dukungan perekaman dalam kode Anda menggunakan
+langkah-langkah ini:</p>
+
+<ol>
+<li>Dalam metode <code>TvInputService.onCreate()</code> Anda, buat objek
+<code>TvInputInfo</code> baru menggunakan kelas <code>TvInputInfo.Builder</code>.
+</li>
+<li>Saat membuat objek <code>TvInputInfo</code> baru, panggil
+<code>setCanRecord(true)</code> sebelum memanggil <code>build()</code> untuk
+ menunjukkan layanan Anda mendukung perekaman.</li>
+<li>Daftarkan objek <code>TvInputInfo</code> Anda pada sistem dengan memanggil
+<code>TvInputManager.updateTvInputInfo()</code>.</li>
+</ol>
+
+<h2 id="recording">Merekam Sesi</h2>
+
+<p>Setelah layanan masukan TV Anda mendaftar bahwa mendukung fungsionalitas
+perekaman, sistem akan memanggil
+<code>TvInputService.onCreateRecordingSession()</code> bila perlu untuk mengakses
+implementasi perekaman aplikasi Anda. Implementasikan subkelas
+<code>TvInputService.RecordingSession</code> Anda sendiri dan kembalikan
+bila callback <code>onCreateRecordingSession()</code> dipicu.
+ Subkelas ini bertanggung jawab mengalihkan ke saluran data yang benar,
+merekam data yang diminta, dan memberitahukan status perekaman serta kesalahan ke
+sistem.</p>
+
+<p>Bila sistem memanggil <code>RecordingSession.onTune()</code>, dengan meneruskan
+URI saluran, setel ke saluran yang ditetapkan URI. Beri tahu sistem bahwa
+aplikasi Anda telah disetel ke saluran yang diinginkan dengan memanggil <code>notifyTuned()</code>,
+atau, jika aplikasi Anda tidak bisa disetel ke saluran yang tepat, panggil
+<code>notifyError()</code>.</p>
+
+<p>Sistem berikutnya akan memanggil callback <code>RecordingSession.onStartRecording()</code>.
+ Aplikasi Anda harus segera mulai merekam. Bila sistem memanggil
+callback ini, sistem mungkin akan memberikan URI yang berisi informasi tentang program
+yang akan direkam. Bila perekaman selesai, Anda perlu menyalin data
+ini ke tabel data <code>RecordedPrograms</code>.</p>
+
+<p>Terakhir, sistem akan memanggil <code>RecordingSession.onStopRecording()</code>.
+Pada tahap ini, aplikasi Anda harus segera berhenti merekam. Anda juga perlu
+membuat entri dalam tabel <code>RecordedPrograms</code>. Entri ini harus
+menyertakan URI data sesi yang direkam dalam kolom
+<code>RecordedPrograms.COLUMN_RECORDING_DATA_URI</code>, dan informasi
+program yang diberikan sistem dalam panggilan awal ke
+<code>onStartRecording()</code>.</p>
+
+<p>Untuk detail selengkapnya tentang cara mengakses tabel <code>RecordedPrograms</code>
+lihat <a href="#sessions">Mengelola Sesi yang Direkam</a>.</p>
+
+<h2 id="errors">Menangani Kesalahan Perekaman</h2>
+
+<p>Jika terjadi kesalahan selama perekaman, yang menghasilkan data terekam yang tidak bisa digunakan,
+beri tahu sistem dengan memanggil <code>RecordingSession.notifyError()</code>.
+Begitu juga, Anda bisa memanggil <code>notifyError()</code> setelah sesi rekaman dibuat
+agar sistem mengetahui bahwa aplikasi Anda tidak bisa lagi merekam sesi.</p>
+
+<p>Jika terjadi kesalahan selama perekaman, namun Anda ingin menyediakan rekaman parsial
+yang bisa digunakan pengguna untuk pemutaran, panggil
+<code>RecordingSession.notifyRecordingStopped()</code> untuk memungkinkan sistem
+menggunakan sesi parsial.</p>
+
+<h2 id="sessions">Mengelola Sesi yang Direkam</h2>
+
+<p>Sistem menyimpan informasi untuk semua sesi yang direkam dari semua
+aplikasi saluran yang mampu merekam dalam tabel penyedia materi <code>TvContract.RecordedPrograms</code>.
+ Informasi ini bisa diakses lewat URI materi
+<code>RecordedPrograms.Uri</code>. Gunakan API penyedia materi untuk
+membaca, menambahkan, dan menghapus entri dari tabel ini.</p>
+
+<p>Untuk informasi selengkapnya tentang menangani data penyedia materi, lihat
+<a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
+Dasar-Dasar Penyedia Materi</a>.</p>
+
+<h2 id="best">Praktik Terbaik</h2>
+
+<p>Perangkat TV mungkin memiliki penyimpanan terbatas, jadi pertimbangkan sebaik mungkin saat
+mengalokasikan penyimpanan untuk menyimpan sesi rekaman. Gunakan
+<code>RecordingCallback.onError(RECORDING_ERROR_INSUFFICIENT_SPACE)</code> bila
+tidak cukup ruang untuk menyimpan sesi rekaman.</p>
+
+<p>Bila pengguna memulai perekaman, Anda harus memulai perekaman data
+secepatnya. Untuk memfasilitasinya, selesaikan setiap tugas yang memakan waktu di awal,
+seperti mengakses dan mengalokasikan ruang penyimpanan, saat sistem memanggil callback
+<code>onCreateRecordingSession()</code>. Hal ini akan memungkinkan Anda memulai
+perekaman dengan segera bila callback <code>onStartRecording()</code>
+dipicu.</p>
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index 3458bdc..8ddb982 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -817,8 +817,11 @@
   to: https://code.google.com/p/android/issues/list?can=2&q=label%3ADevPreview-N
 - from: /preview/bugreports/...
   to: https://code.google.com/p/android/issues/list?can=2&q=label%3ADevPreview-N
+- from: /preview/setup-sdk.html
+  to: /studio/index.html
 - from: /2016/03/first-preview-of-android-n-developer.html
   to: http://android-developers.blogspot.com/2016/03/first-preview-of-android-n-developer.html
+
 - from: /reference/org/apache/http/...
   to: /about/versions/marshmallow/android-6.0-changes.html#behavior-apache-http-client
 - from: /shareables/...
@@ -1164,81 +1167,81 @@
 
 # Android Studio help button redirects
 - from: /r/studio-ui/vector-asset-studio.html
-  to: /studio/write/vector-asset-studio.html?utm_medium=android-studio
+  to: /studio/write/vector-asset-studio.html?utm_source=android-studio
 - from: /r/studio-ui/image-asset-studio.html
-  to: /studio/write/image-asset-studio.html?utm_medium=android-studio
+  to: /studio/write/image-asset-studio.html?utm_source=android-studio
 - from: /r/studio-ui/project-structure.html
-  to: /studio/projects/index.html?utm_medium=android-studio
+  to: /studio/projects/index.html?utm_source=android-studio
 - from: /r/studio-ui/android-monitor.html
-  to: /studio/profile/android-monitor.html?utm_medium=android-studio
+  to: /studio/profile/android-monitor.html?utm_source=android-studio
 - from: /r/studio-ui/am-logcat.html
-  to: /studio/debug/am-logcat.html?utm_medium=android-studio
+  to: /studio/debug/am-logcat.html?utm_source=android-studio
 - from: /r/studio-ui/am-memory.html
-  to: /studio/profile/am-memory.html?utm_medium=android-studio
+  to: /studio/profile/am-memory.html?utm_source=android-studio
 - from: /r/studio-ui/am-cpu.html
-  to: /studio/profile/am-cpu.html?utm_medium=android-studio
+  to: /studio/profile/am-cpu.html?utm_source=android-studio
 - from: /r/studio-ui/am-gpu.html
-  to: /studio/profile/am-gpu.html?utm_medium=android-studio
+  to: /studio/profile/am-gpu.html?utm_source=android-studio
 - from: /r/studio-ui/am-network.html
-  to: /studio/profile/am-network.html?utm_medium=android-studio
+  to: /studio/profile/am-network.html?utm_source=android-studio
 - from: /r/studio-ui/am-hprof.html
-  to: /studio/profile/am-hprof.html?utm_medium=android-studio
+  to: /studio/profile/am-hprof.html?utm_source=android-studio
 - from: /r/studio-ui/am-allocation.html
-  to: /studio/profile/am-allocation.html?utm_medium=android-studio
+  to: /studio/profile/am-allocation.html?utm_source=android-studio
 - from: /r/studio-ui/am-methodtrace.html
-  to: /studio/profile/am-methodtrace.html?utm_medium=android-studio
+  to: /studio/profile/am-methodtrace.html?utm_source=android-studio
 - from: /r/studio-ui/am-sysinfo.html
-  to: /studio/profile/am-sysinfo.html?utm_medium=android-studio
+  to: /studio/profile/am-sysinfo.html?utm_source=android-studio
 - from: /r/studio-ui/am-screenshot.html
-  to: /studio/debug/am-screenshot.html?utm_medium=android-studio
+  to: /studio/debug/am-screenshot.html?utm_source=android-studio
 - from: /r/studio-ui/am-video.html
-  to: /studio/debug/am-video.html?utm_medium=android-studio
+  to: /studio/debug/am-video.html?utm_source=android-studio
 - from: /r/studio-ui/avd-manager.html
-  to: /studio/run/managing-avds.html?utm_medium=android-studio
+  to: /studio/run/managing-avds.html?utm_source=android-studio
 - from: /r/studio-ui/rundebugconfig.html
-  to: /studio/run/rundebugconfig.html?utm_medium=android-studio
+  to: /studio/run/rundebugconfig.html?utm_source=android-studio
 - from: /r/studio-ui/devicechooser.html
-  to: /studio/run/emulator.html?utm_medium=android-studio
+  to: /studio/run/emulator.html?utm_source=android-studio
 - from: /r/studio-ui/virtualdeviceconfig.html
-  to: /studio/run/managing-avds.html?utm_medium=android-studio
+  to: /studio/run/managing-avds.html?utm_source=android-studio
 - from: /r/studio-ui/emulator.html
-  to: /studio/run/emulator.html?utm_medium=android-studio
+  to: /studio/run/emulator.html?utm_source=android-studio
 - from: /r/studio-ui/instant-run.html
-  to: /studio/run/index.html?utm_medium=android-studio#instant-run
+  to: /studio/run/index.html?utm_source=android-studio#instant-run
 - from: /r/studio-ui/test-recorder.html
-  to: http://tools.android.com/tech-docs/test-recorder
+  to: /studio/test/espresso-test-recorder.html?utm_source=android-studio
 - from: /r/studio-ui/export-licenses.html
   to: http://tools.android.com/tech-docs/new-build-system/license
 - from: /r/studio-ui/experimental-to-stable-gradle.html
   to: http://tools.android.com/tech-docs/new-build-system/gradle-experimental/experimental-to-stable-gradle
 - from: /r/studio-ui/sdk-manager.html
-  to: /studio/intro/update.html?utm_medium=android-studio#sdk-manager
+  to: /studio/intro/update.html?utm_source=android-studio#sdk-manager
 - from: /r/studio-ui/newjclass.html
-  to: /studio/write/create-java-class.html?utm_medium=android-studio
+  to: /studio/write/create-java-class.html?utm_source=android-studio
 - from: /r/studio-ui/menu-help.html
-  to: /studio/intro/index.html?utm_medium=android-studio
+  to: /studio/intro/index.html?utm_source=android-studio
 - from: /r/studio-ui/menu-start.html
-  to: /training/index.html?utm_medium=android-studio
+  to: /training/index.html?utm_source=android-studio
 - from: /r/studio-ui/run-with-work-profile.html
-  to: /studio/run/index.html#ir-work-profile?utm_medium=android-studio
+  to: /studio/run/index.html?utm_source=android-studio#ir-work-profile
 - from: /r/studio-ui/am-gpu-debugger.html
-  to: /studio/profile/am-gpu.html?utm_medium=android-studio
+  to: /studio/profile/am-gpu.html?utm_source=android-studio
 - from: /r/studio-ui/theme-editor.html
-  to: /studio/write/theme-editor.html?utm_medium=android-studio
+  to: /studio/write/theme-editor.html?utm_source=android-studio
 - from: /r/studio-ui/translations-editor.html
-  to: /studio/write/translations-editor.html?utm_medium=android-studio
+  to: /studio/write/translations-editor.html?utm_source=android-studio
 - from: /r/studio-ui/debug.html
-  to: /studio/debug/index.html?utm_medium=android-studio
+  to: /studio/debug/index.html?utm_source=android-studio
 - from: /r/studio-ui/run.html
-  to: /studio/run/index.html?utm_medium=android-studio
+  to: /studio/run/index.html?utm_source=android-studio
 - from: /r/studio-ui/layout-editor.html
-  to: /studio/write/layout-editor.html?utm_medium=android-studio
+  to: /studio/write/layout-editor.html?utm_source=android-studio
 - from: /r/studio-ui/project-window.html
-  to: /studio/projects/index.html?utm_medium=android-studio
+  to: /studio/projects/index.html?utm_source=android-studio
 - from: /r/studio-ui/lint-inspection-results.html
-  to: /studio/write/lint.html?utm_medium=android-studio
+  to: /studio/write/lint.html?utm_source=android-studio
 - from: /r/studio-ui/gradle-console.html
-  to: /studio/run/index.html#gradle-console?utm_medium=android-studio
+  to: /studio/run/index.html?utm_source=android-studio#gradle-console
 
 # Redirects from (removed) N Preview documentation
 - from: /preview/features/afw.html
@@ -1281,7 +1284,3 @@
   to: /topic/performance/background-optimization.html
 - from: /preview/features/data-saver.html
   to: /training/basics/network-ops/data-saver.html
-
-# Temporary redirect
-- from: /ndk/guides/cmake.html
-  to: https://sites.google.com/a/android.com/tools/tech-docs/external-c-builds#TOC-CMake-Variables-List
\ No newline at end of file
diff --git a/docs/html/about/versions/nougat/android-7.0.jd b/docs/html/about/versions/nougat/android-7.0.jd
index 1ca540c..8ef8bd6 100644
--- a/docs/html/about/versions/nougat/android-7.0.jd
+++ b/docs/html/about/versions/nougat/android-7.0.jd
@@ -44,7 +44,7 @@
         <li><a href="#vr">VR Support</a></li>
         <li><a href="#print_svc">Print Service Enhancements</a></li>
         <li><a href="#virtual_files">Virtual Files</a></li>
-        <li><a href="#framemetrics_api">FrameMetricsListener API</a></li>
+        <li><a href="#framemetrics_api">Frame Metrics API</a></li>
       </ol>
 </div>
 </div>
@@ -434,9 +434,8 @@
 </p>
 
 <p>
-  For information about creating an app tile, see the documentation for
-  <code>android.service.quicksettings.Tile</code> in the downloadable <a href=
-  "{@docRoot}preview/setup-sdk.html#docs-dl">API Reference</a>.
+  For information about creating an app tile, see the reference documentation
+  for {@link android.service.quicksettings.Tile Tile}.
 </p>
 
 
@@ -465,9 +464,8 @@
 through any medium, such as a VOIP endpoint or forwarding phones.</p>
 
 <p>
-  For more information, see <code>android.provider.BlockedNumberContract</code>
-  in the downloadable <a href="{@docRoot}preview/setup-sdk.html#docs-dl">API
-  Reference</a>.
+  For more information, see the reference documentation for
+  {@link android.provider.BlockedNumberContract BlockedNumberContract}.
 </p>
 
 <h2 id="call_screening">Call Screening</h2>
@@ -486,9 +484,8 @@
 </ul>
 
 <p>
-  For more information, see <code>android.telecom.CallScreeningService</code>
-  in the downloadable <a href="{@docRoot}preview/setup-sdk.html#docs-dl">API
-  Reference</a>.
+  For more information, see the reference documentation for
+  {@link android.telecom.CallScreeningService CallScreeningService}.
 </p>
 
 
@@ -780,8 +777,9 @@
 features such as face-tracking, eye-tracking, point scanning, and so on, to
 meet the needs of those users.</p>
 
-<p>For more information, see <code>android.accessibilityservice.GestureDescription</code>
-  in the downloadable <a href="{@docRoot}preview/setup-sdk.html#docs-dl">API Reference</a>.</p>
+<p>For more information, see the reference documentation for
+{@link android.accessibilityservice.GestureDescription GestureDescription}.
+</p>
 
 
 <h2 id="direct_boot">Direct Boot</h2>
@@ -972,9 +970,8 @@
   from the system and from the app in focus. The system retrieves these
   shortcuts automatically from the app’s menu if the shortcuts exist. You can
   also provide your own fine-tuned shortcuts lists for the screen. You can do
-  this by overriding the new <code>Activity.onProvideKeyboardShortcuts()</code>
-  method, described in the downloadable <a href=
-  "{@docRoot}preview/setup-sdk.html#docs-dl">API Reference</a>.
+  this by overriding the {@link android.view.Window.Callback#onProvideKeyboardShortcuts
+  onProvideKeyboardShortcuts()} method.
 </p>
 
 <p class="note">
@@ -986,7 +983,8 @@
 
 <p>
   To trigger Keyboard Shortcuts Helper from anywhere in your app, call
-  {@code Activity.requestKeyboardShortcutsHelper()} for the relevant activity.
+  {@link android.app.Activity#requestShowKeyboardShortcuts requestShowKeyboardShortcuts()}
+  from the relevant activity.
 </p>
 
 <h2 id="custom_pointer_api">
@@ -1062,37 +1060,32 @@
 
 <ul>
   <li>You can set an icon from a resource ID by calling
-  <code>PrinterInfo.Builder.setResourceIconId()</code>
+  {@link android.print.PrinterInfo.Builder#setIconResourceId setIconResourceId()}.
   </li>
 
   <li>You can show an icon from the network by calling
-  <code>PrinterInfo.Builder.setHasCustomPrinterIcon()</code>, and setting a
-  callback for when the icon is requested using
-  <code>android.printservice.PrinterDiscoverySession.onRequestCustomPrinterIcon()</code>
+  {@link android.print.PrinterInfo.Builder#setHasCustomPrinterIcon setHasCustomPrinterIcon()},
+  and setting a callback for when the icon is requested using
+  {@link android.printservice.PrinterDiscoverySession#onRequestCustomPrinterIcon onRequestCustomPrinterIcon()}.
   </li>
 </ul>
 
 <p>
   In addition, you can provide a per-printer activity to display additional
-  information by calling <code>PrinterInfo.Builder.setInfoIntent()</code>.
+  information by calling {@link android.print.PrinterInfo.Builder#setInfoIntent setInfoIntent()}.
 </p>
 
 <p>
   You can indicate the progress and status of print jobs in the print job
   notification by calling
-  <code>android.printservice.PrintJob.setProgress()</code> and
-  <code>android.printservice.PrintJob.setStatus()</code>, respectively.
+  {@link android.printservice.PrintJob#setProgress setProgress()} and
+  {@link android.printservice.PrintJob#setStatus setStatus()}, respectively.
 </p>
 
-<p>
-  For more information about these methods, see the downloadable <a href=
-  "{@docRoot}preview/setup-sdk.html#docs-dl">API Reference</a>.
-</p>
-
-<h2 id="framemetrics_api">FrameMetricsListener API</h2>
+<h2 id="framemetrics_api">Frame Metrics API</h2>
 
 <p>
-The FrameMetricsListener API allows an app to monitor its UI rendering
+The Frame Metrics API allows an app to monitor its UI rendering
 performance. The API provides this capability by exposing a streaming Pub/Sub API to transfer frame
 timing info for the app's current window. The data returned is
 equivalent to that which <code><a href="{@docRoot}tools/help/shell.html#shellcommands">adb shell</a>
@@ -1100,7 +1093,7 @@
 </p>
 
 <p>
-You can use FrameMetricsListener to measure interaction-level UI
+You can use the Frame Metrics API to measure interaction-level UI
 performance in production, without a USB connection. This API
 allows collection of data at a much higher granularity than does
 {@code adb shell dumpsys gfxinfo}. This higher granularity is possible because
@@ -1112,16 +1105,15 @@
 </p>
 
 <p>
-To monitor a window, implement the <code>FrameMetricsListener.onMetricsAvailable()</code>
-callback method and register it on that window. For more information, refer to
-the {@code FrameMetricsListener} class documentation in
-the downloadable <a href="{@docRoot}preview/setup-sdk.html#docs-dl">API Reference</a>.
+To monitor a window, implement the
+{@link android.view.Window.OnFrameMetricsAvailableListener#onFrameMetricsAvailable OnFrameMetricsAvailableListener.onFrameMetricsAvailable()}
+callback method and register it on that window.
 </p>
 
 <p>
-The API provides a {@code FrameMetrics} object, which contains timing data that
-the rendering subsystem reports for various milestones in a frame lifecycle.
-The supported metrics are: {@code UNKNOWN_DELAY_DURATION},
+The API provides a {@link android.view.FrameMetrics FrameMetrics} object, which
+contains timing data that the rendering subsystem reports for various milestones
+in a frame lifecycle. The supported metrics are: {@code UNKNOWN_DELAY_DURATION},
 {@code INPUT_HANDLING_DURATION}, {@code ANIMATION_DURATION},
 {@code LAYOUT_MEASURE_DURATION}, {@code DRAW_DURATION}, {@code SYNC_DURATION},
 {@code COMMAND_ISSUE_DURATION}, {@code SWAP_BUFFERS_DURATION},
diff --git a/docs/html/develop/index.jd b/docs/html/develop/index.jd
index b1d7388..564dbf9 100644
--- a/docs/html/develop/index.jd
+++ b/docs/html/develop/index.jd
@@ -15,20 +15,25 @@
     <div class="cols dac-hero-content">
       <div class="col-1of2 col-push-1of2 dac-hero-figure">
         <img class="dac-hero-image" style="padding-top:32px"
-          src="/images/develop/hero-layout-editor_2x.png">
+          src="/images/develop/hero-layout-editor_2x.png"
+          srcset="/images/develop/hero-layout-editor_2x.png 2x,
+                  /images/develop/hero-layout-editor.png 1x">
       </div>
       <div class="col-1of2 col-pull-1of2" style="margin-bottom:40px">
         <h1 class="dac-hero-title">
             <a style="color:inherit" href="{@docRoot}studio/index.html">
-            Android Studio 2.2 <nobr>is here!</nobr></a></h1>
+            Android Studio 2.2</a></h1>
 
-<p class="dac-hero-description">The latest version of Android Studio includes a
-rewritten <b>layout editor</b> with the new constraint layout,
-helping you build rich UI with less work.</p>
+<p class="dac-hero-description">There are 20+ new features in this release
+focused on helping you code faster and smarter. With Android Studio 2.2 you
+can:</p>
 
-
-<p class="dac-hero-description">With over 20 new features, Android Studio
-2.2 helps you code faster and smarter.</p>
+<ul class="dac-hero-description">
+  <li>Develop your app user interface faster with the new Layout Editor &amp;
+    Constraint Layout</li>
+  <li>Develop smarter with the APK analyzer &amp; expanded code analysis</li>
+  <li>Develop with the the latest Android 7.0 Nougat APIs &amp; features</li>
+</ul>
 
 <p style="margin-top:24px">
     <a class="dac-hero-cta" href="{@docRoot}studio/index.html">
@@ -36,9 +41,9 @@
       Get Android Studio 2.2
     </a>
   &nbsp;&nbsp;&nbsp;&nbsp;<wbr>
-    <a class="dac-hero-cta" href="{@docRoot}studio/releases/index.html">
+    <a class="dac-hero-cta" href="{@docRoot}studio/features.html">
     <span class="dac-sprite dac-auto-chevron"></span>
-    See the release notes</a>
+    See more features</a>
 </p>
 
       </div>
diff --git a/docs/html/distribute/tools/promote/brand.jd b/docs/html/distribute/tools/promote/brand.jd
index 409dfdd..ba2bed7 100644
--- a/docs/html/distribute/tools/promote/brand.jd
+++ b/docs/html/distribute/tools/promote/brand.jd
@@ -34,30 +34,31 @@
     <ul>
     <li>Android&trade; should have a trademark symbol the first time it appears in a creative.</li>
     <li>Android should always be capitalized and is never plural or possessive.</li>
-    <li>"Android" cannot be used in names of applications or accessory products,
-    including phones, tablets, TVs, speakers, headphones, watches, and other devices. Instead use "for Android".
+    <li>"Android", or anything confusingly similar to "Android", cannot be used
+    in names of applications or accessory products, including phones, tablets, TVs,
+    speakers, headphones, watches, and other devices. Instead, use "for Android".
       <ul>
-        <li><span style="color:red">Incorrect</span>: "Android MediaPlayer"</li>
+        <li><span style="color:red">Incorrect</span>: "Android MediaPlayer" or "Ndroid MediaPlayer"</li>
         <li><span style="color:green">Correct</span>: "MediaPlayer for Android"</li>
       </ul>
-      <p>If used with your logo, "for Android" should be no larger than 90% of your logo’s size.
-      First instance of this use should be followed by a TM symbol, "for Android&trade;".</p>
+      <p>If used with your logo, "for Android" should be no larger than 90% of your logo's size.
+      The first instance of this use should be followed by a TM symbol: "for Android&trade;".</p>
     </li>
-    <li>"Android TV", "Android Wear" and "Android Auto" may only be used to identify or market
+    <li>"Android TV", "Android Wear", and "Android Auto" may only be used to identify or market
       products or services with prior approval.  Use "for Android" or "with Android" for all
-      other Android-based products
+      other Android-based products.
       <ul>
         <li><span style="color:red">Incorrect</span>: "Android TV Streaming Stick",
           "Streaming Stick with Android TV"</li>
         <li><span style="color:green">Correct</span>: "Streaming Stick with Android"</li>
       </ul>
       <p>If used with your logo, "for Android" or "with Android" should be no larger than 90% of
-        your logo’s size. First instance of this use should be followed by a TM symbol,
+        your logo's size. The first instance of this use should be followed by a TM symbol:
         "for Android&trade;".</p>
     </li>
-    <li>Android may be used as a descriptor, as long as it is followed by a
-        proper generic term. (Think of "Android" as a term used in place of
-        "the Android platform.")
+    <li>Android may be used as a descriptor in text, as long as it is followed by a
+        proper generic term and is not the name of your product, app, or service.
+        Think of "Android" as a term used in place of "the Android platform."
       <ul>
         <li><span style="color:red">Incorrect</span>: "Android MediaPlayer" or "Android XYZ app"</li>
         <li><span style="color:green">Correct</span>: "Android features" or "Android applications"</li>
@@ -100,7 +101,9 @@
 <h4 style="clear:right">Android logo</h4>
 
 <div style="float:right;width:210px;margin-left:30px;margin-top:-10px">
-  <img alt="" src="{@docRoot}images/brand/android_logo_no.png">
+  <img alt="" src="{@docRoot}images/brand/android_logo_no.png"
+    srcset="{@docRoot}images/brand/android_logo_no.png 1x,
+    {@docRoot}images/brand/android_logo_no_2x.png 2x">
 </div>
 
 <p>The Android logo may not be used.</p>
diff --git a/docs/html/distribute/users/build-buzz.jd b/docs/html/distribute/users/build-buzz.jd
index 7bc6f6c..65aa44a 100644
--- a/docs/html/distribute/users/build-buzz.jd
+++ b/docs/html/distribute/users/build-buzz.jd
@@ -28,9 +28,6 @@
     Link to Your Apps in Google Play
   </h2>
 
-
-</div>
-
 <p>
   After publishing your apps, you can take Android users directly to your
   app/games detail page on Google Play by <a href=
@@ -64,9 +61,6 @@
     Use the Google Play Badge
   </h2>
 
-
-</div>
-
 <div class="figure" style="margin:0 3em;">
   <img src="{@docRoot}images/gp-build-buzz-uplift-1.png">
 </div>
diff --git a/docs/html/google/play/filters.jd b/docs/html/google/play/filters.jd
index 50cc807..a73b17f 100644
--- a/docs/html/google/play/filters.jd
+++ b/docs/html/google/play/filters.jd
@@ -382,9 +382,12 @@
   suspended, users will not be able to reinstall or update it, even if it appears in their Downloads.</p> </td></tr>
   <tr>
   <td valign="top">Priced
-    Status</td> <td valign="top"><p>Not all users can see paid apps. To show paid apps, a device
-must have a SIM card and be running Android 1.1 or later, and it must be in a
-country (as determined by SIM carrier) in which paid apps are available.</p></td>
+    Status</td> <td valign="top"><p>Not all users can see paid apps. To show
+    paid apps, a device must be running Android 1.1 or later, and it must be in
+    a country where paid apps are available. If a device has a SIM card, the SIM
+    carrier determines whether paid apps are available. If a device doesn't have
+    a SIM card, the device's IP address is used to determine whether the device
+    is in a country where paid apps are available.</p></td>
 </tr> <tr>
   <td valign="top">Country Targeting</td> <td valign="top"> <p>When you upload your app to
     Google Play, you can select the countries in which to distribute your app
diff --git a/docs/html/guide/_book.yaml b/docs/html/guide/_book.yaml
index 20ee483..13c948c 100644
--- a/docs/html/guide/_book.yaml
+++ b/docs/html/guide/_book.yaml
@@ -399,11 +399,6 @@
   - title: App Install Location
     path: /guide/topics/data/install-location.html
 
-- title: Libraries
-  path: /topic/libraries/index.html
-  section:
-  - include: /topic/libraries/_book.yaml
-
 - title: Administration
   path: /guide/topics/admin/index.html
   section:
diff --git a/docs/html/guide/components/intents-common.jd b/docs/html/guide/components/intents-common.jd
index e6c9fc6..47174d2 100644
--- a/docs/html/guide/components/intents-common.jd
+++ b/docs/html/guide/components/intents-common.jd
@@ -2155,7 +2155,7 @@
 <p><b>Example intent:</b></p>
 <pre>
 public void openWifiSettings() {
-    Intent intent = new Intent(Intent.ACTION_WIFI_SETTINGS);
+    Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
     if (intent.resolveActivity(getPackageManager()) != null) {
         startActivity(intent);
     }
diff --git a/docs/html/guide/topics/connectivity/nfc/nfc.jd b/docs/html/guide/topics/connectivity/nfc/nfc.jd
index 520f520..881a75f 100644
--- a/docs/html/guide/topics/connectivity/nfc/nfc.jd
+++ b/docs/html/guide/topics/connectivity/nfc/nfc.jd
@@ -487,19 +487,22 @@
 intent and gets the NDEF messages from an intent extra.</p>
 
 <pre>
-public void onResume() {
-    super.onResume();
+&#64;Override
+protected void onNewIntent(Intent intent) {
+    super.onNewIntent(intent);
     ...
-    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
-        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
-        if (rawMsgs != null) {
-            msgs = new NdefMessage[rawMsgs.length];
-            for (int i = 0; i &lt; rawMsgs.length; i++) {
-                msgs[i] = (NdefMessage) rawMsgs[i];
+    if (intent != null &amp;&amp; NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
+        Parcelable[] rawMessages =
+            intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
+        if (rawMessages != null) {
+            NdefMessage[] messages = new NdefMessage[rawMessages.length];
+            for (int i = 0; i < rawMessages.length; i++) {
+                messages[i] = (NdefMessage) rawMessages[i];
             }
+            // Process the messages array.
+            ...
         }
     }
-    //process the msgs array
 }
 </pre>
 
diff --git a/docs/html/guide/topics/graphics/2d-graphics.jd b/docs/html/guide/topics/graphics/2d-graphics.jd
index 9cae53c..d7dd038 100644
--- a/docs/html/guide/topics/graphics/2d-graphics.jd
+++ b/docs/html/guide/topics/graphics/2d-graphics.jd
@@ -21,6 +21,7 @@
     </li>
     <li><a href="#shape-drawable">Shape Drawable</a></li>
     <li><a href="#nine-patch">Nine-patch</a></li>
+    <li><a href="#vector-drawable">Vector Drawables</a></li>
   </ol>
 
   <h2>See also</h2>
@@ -428,58 +429,66 @@
          of the object it's attached to.
          -->
 
-         <h2 id="nine-patch">Nine-patch</h2>
+<h2 id="nine-patch">Nine-patch</h2>
 
-         <p>A {@link android.graphics.drawable.NinePatchDrawable} graphic is a stretchable bitmap
-image,           which Android
-           will automatically resize to accommodate the contents of the View in which you have
-placed it as the           background.
-           An example use of a NinePatch is the backgrounds used by standard Android buttons &mdash;
-           buttons must stretch to accommodate strings of various lengths. A NinePatch drawable is a
-standard           PNG
-           image that includes an extra 1-pixel-wide border. It must be saved with the extension
-           <code>.9.png</code>,
-           and saved into the <code>res/drawable/</code> directory of your project.
-         </p>
-         <p>
-           The border is used to define the stretchable and static areas of
-           the image. You indicate a stretchable section by drawing one (or more) 1-pixel-wide
-           black line(s) in the left and top part of the border (the other border pixels should
-           be fully transparent or white). You can have as many stretchable sections as you want:
-           their relative size stays the same, so the largest sections always remain the largest.
-         </p>
-         <p>
-           You can also define an optional drawable section of the image (effectively,
-           the padding lines) by drawing a line on the right and bottom lines.
-           If a View object sets the NinePatch as its background and then specifies the
-           View's text, it will stretch itself so that all the text fits inside only
-           the area designated by the right and bottom lines (if included). If the
-           padding lines are not included, Android uses the left and top lines to
-           define this drawable area.
-         </p>
-         <p>To clarify the difference between the different lines, the left and top lines define
-           which pixels of the image are allowed to be replicated in order to stretch the image.
-           The bottom and right lines define the relative area within the image that the contents
-           of the View are allowed to lie within.</p>
-         <p>
-           Here is a sample NinePatch file used to define a button:
-         </p>
-         <img src="{@docRoot}images/ninepatch_raw.png" alt="" />
-
-         <p>This NinePatch defines one stretchable area with the left and top lines
-           and the drawable area with the bottom and right lines. In the top image, the dotted grey
-           lines identify the regions of the image that will be replicated in order to stretch the
-image. The           pink
-           rectangle in the bottom image identifies the region in which the contents of the View are
-allowed.
-           If the contents don't fit in this region, then the image will be stretched so that they
-do.
+<p>
+  A {@link android.graphics.drawable.NinePatchDrawable} graphic is a
+  stretchable bitmap image, which Android will automatically resize to
+  accommodate the contents of the View in which you have placed it as the
+  background. An example use of a NinePatch is the backgrounds used by
+  standard Android buttons — buttons must stretch to accommodate strings of
+  various lengths. A NinePatch drawable is a standard PNG image that includes
+  an extra 1-pixel-wide border. It must be saved with the extension
+  <code>.9.png</code>, and saved into the <code>res/drawable/</code> directory
+  of your project.
 </p>
 
-<p>The <a href="{@docRoot}tools/help/draw9patch.html">Draw 9-patch</a> tool offers
-   an extremely handy way to create your NinePatch images, using a WYSIWYG graphics editor. It
-even raises warnings if the region you've defined for the stretchable area is at risk of
-producing drawing artifacts as a result of the pixel replication.
+<p>
+  The border is used to define the stretchable and static areas of the image.
+  You indicate a stretchable section by drawing one (or more) 1-pixel-wide
+  black line(s) in the left and top part of the border (the other border
+  pixels should be fully transparent or white). You can have as many
+  stretchable sections as you want: their relative size stays the same, so the
+  largest sections always remain the largest.
+</p>
+
+<p>
+  You can also define an optional drawable section of the image (effectively,
+  the padding lines) by drawing a line on the right and bottom lines. If a
+  View object sets the NinePatch as its background and then specifies the
+  View's text, it will stretch itself so that all the text fits inside only
+  the area designated by the right and bottom lines (if included). If the
+  padding lines are not included, Android uses the left and top lines to
+  define this drawable area.
+</p>
+
+<p>
+  To clarify the difference between the different lines, the left and top
+  lines define which pixels of the image are allowed to be replicated in order
+  to stretch the image. The bottom and right lines define the relative area
+  within the image that the contents of the View are allowed to lie within.
+</p>
+
+<p>
+  Here is a sample NinePatch file used to define a button:
+</p>
+<img src="{@docRoot}images/ninepatch_raw.png" alt="">
+<p>
+  This NinePatch defines one stretchable area with the left and top lines and
+  the drawable area with the bottom and right lines. In the top image, the
+  dotted grey lines identify the regions of the image that will be replicated
+  in order to stretch the image. The pink rectangle in the bottom image
+  identifies the region in which the contents of the View are allowed. If the
+  contents don't fit in this region, then the image will be stretched so that
+  they do.
+</p>
+
+<p>
+  The <a href="{@docRoot}tools/help/draw9patch.html">Draw 9-patch</a> tool
+  offers an extremely handy way to create your NinePatch images, using a
+  WYSIWYG graphics editor. It even raises warnings if the region you've
+  defined for the stretchable area is at risk of producing drawing artifacts
+  as a result of the pixel replication.
 </p>
 
 <h3>Example XML</h3>
@@ -516,3 +525,265 @@
 </p>
 
 <img src="{@docRoot}images/ninepatch_examples.png" alt=""/>
+
+<h2 id="vector-drawable">
+  Vector Drawables
+</h2>
+
+<p>
+  A {@link android.graphics.drawable.VectorDrawable} graphic replaces multiple
+  PNG assets with a single vector graphic. The vector graphic is defined in an
+  XML file as a set of points, lines, and curves along with its associated
+  color information.
+</p>
+
+<p>
+  The major advantage of using a vector graphic is image scalability. Using
+  vector graphics resizes the same file for different screen densities without
+  loss of image quality. This results in smaller APK files and less developer
+  maintenance. You can also use vector images for animation by using multiple
+  XML files instead of multiple images for each display resolution.
+</p>
+
+<p>
+  Let's go through an example to understand the benefits. An image of size 100
+  x 100 dp may render good quality on a smaller display resolution. On larger
+  devices, the app might want to use a 400 x 400 dp version of the image.
+  Normally, developers create multiple versions of an asset to cater to
+  different screen densities. This approach consumes more development efforts,
+  and results in a larger APK, which takes more space on the device.
+</p>
+
+<p>
+  As of Android 5.0 (API level 21), there are two classes that support vector
+  graphics as a drawable resource: {@link
+  android.graphics.drawable.VectorDrawable} and {@link
+  android.graphics.drawable.AnimatedVectorDrawable}. For more information
+  about using the VectorDrawable and the AnimatedVectorDrawable classes, read
+  the <a href="#vector-drawable-class">About VectorDrawable class</a> and
+  <a href="#animated-vector-drawable-class">About AnimatedVectorDrawable
+  class</a> sections.
+</p>
+
+<h3 id="vector-drawable-class">About VectorDrawable class</h3>
+<p>
+  {@link android.graphics.drawable.VectorDrawable} defines a static drawable
+  object. Similar to the SVG format, each vector graphic is defined as a tree
+  hierachy, which is made up of <code>path</code> and <code>group</code> objects.
+  Each <code>path</code> contains the geometry of the object's outline and
+  <code>group</code> contains details for transformation. All paths are drawn
+  in the same order as they appear in the XML file.
+</p>
+
+<img src="{@docRoot}images/guide/topics/graphics/vectorpath.png" alt=""/>
+<p class="img-caption">
+  <strong>Figure 1.</strong> Sample hierarchy of a vector drawable asset
+</p>
+
+
+<p>
+  The <a href="{@docRoot}studio/write/vector-asset-studio.html">Vector Asset
+  Studio</a> tool offers a simple way to add a vector graphic to the project
+  as an XML file.
+</p>
+
+<h4>
+  Example XML
+</h4>
+
+<p>
+  Here is a sample <code>VectorDrawable</code> XML file that renders an image
+  of a battery in the charging mode.
+</p>
+
+<pre>
+&lt;!-- res/drawable/battery_charging.xml --&gt;
+&lt;vector xmlns:android="http://schemas.android.com/apk/res/android"
+    &lt;!-- intrinsic size of the drawable --&gt;
+    android:height="24dp"
+    android:width="24dp"
+    &lt;!-- size of the virtual canvas --&gt;
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0"&gt;
+   &lt;group
+         android:name="rotationGroup"
+         android:pivotX="10.0"
+         android:pivotY="10.0"
+         android:rotation="15.0" &gt;
+      &lt;path
+        android:name="vect"
+        android:fillColor="#FF000000"
+        android:pathData="M15.67,4H14V2h-4v2H8.33C7.6,4 7,4.6 7,5.33V9h4.93L13,7v2h4V5.33C17,4.6 16.4,4 15.67,4z"
+        android:fillAlpha=".3"/&gt;
+      &lt;path
+        android:name="draw"
+        android:fillColor="#FF000000"
+        android:pathData="M13,12.5h2L11,20v-5.5H9L11.93,9H7v11.67C7,21.4 7.6,22 8.33,22h7.33c0.74,0 1.34,-0.6 1.34,-1.33V9h-4v3.5z"/&gt;
+   &lt;/group&gt;
+&lt;/vector&gt;
+</pre>
+
+<p>This XML renders the following image:
+</p>
+
+<img src=
+"{@docRoot}images/guide/topics/graphics/ic_battery_charging_80_black_24dp.png"
+alt=""/>
+
+<h3 id="animated-vector-drawable-class">
+  About AnimatedVectorDrawable class
+</h3>
+
+<p>
+  {@link android.graphics.drawable.AnimatedVectorDrawable
+  AnimatedVectorDrawable} adds animation to the properties of a vector
+  graphic. You can define an animated vector graphic as three separate
+  resource files or as a single XML file defining the entire drawable. Let's
+  look at both the approaches for better understanding: <a href=
+  "#multiple-files">Multiple XML files</a> and <a href="#single-file">Single
+  XML file</a>.
+</p>
+
+<h4 id="multiple-files">
+  Multiple XML files
+</h4>
+<p>
+  By using this approach, you can define three separate XML files:
+
+<ul>
+  <li>A {@link android.graphics.drawable.VectorDrawable} XML file.
+  </li>
+
+  <li>
+  An {@link android.graphics.drawable.AnimatedVectorDrawable} XML file that
+defines the target {@link android.graphics.drawable.VectorDrawable}, the
+target paths and groups to animate, the properties, and the animations defined
+as {@link android.animation.ObjectAnimator ObjectAnimator} objects or {@link
+android.animation.AnimatorSet AnimatorSet} objects.
+  </li>
+
+  <li>An animator XML file.
+  </li>
+</ul>
+</p>
+
+<h5>
+  Example of multiple XML files
+</h5>
+<p>
+  The following XML files demonstrate the animation of a vector graphic.
+
+<ul>
+  <li>VectorDrawable's XML file: <code>vd.xml</code>
+  </li>
+
+  <li style="list-style: none; display: inline">
+<pre>
+&lt;vector xmlns:android="http://schemas.android.com/apk/res/android"
+   android:height="64dp"
+   android:width="64dp"
+   android:viewportHeight="600"
+   android:viewportWidth="600" &gt;
+   &lt;group
+      android:name="rotationGroup"
+      android:pivotX="300.0"
+      android:pivotY="300.0"
+      android:rotation="45.0" &gt;
+      &lt;path
+         android:name="vectorPath"
+         android:fillColor="#000000"
+         android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" /&gt;
+   &lt;/group&gt;
+&lt;/vector&gt;
+</pre>
+  </li>
+
+  <li>AnimatedVectorDrawable's XML file: <code>avd.xml</code>
+  </li>
+
+  <li style="list-style: none; display: inline">
+<pre>
+&lt;animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+   android:drawable="@drawable/vd" &gt;
+     &lt;target
+         android:name="rotationGroup"
+         android:animation="@anim/rotation" /&gt;
+     &lt;target
+         android:name="vectorPath"
+         android:animation="@anim/path_morph" /&gt;
+&lt;/animated-vector&gt;
+</pre>
+  </li>
+
+  <li>Animator XML files that are used in the AnimatedVectorDrawable's XML
+  file: <code>rotation.xml</code> and <code>path_morph.xml</code>
+  </li>
+
+  <li style="list-style: none; display: inline">
+<pre>
+&lt;objectAnimator
+   android:duration="6000"
+   android:propertyName="rotation"
+   android:valueFrom="0"
+   android:valueTo="360" /&gt;
+</pre>
+
+<pre>
+&lt;set xmlns:android="http://schemas.android.com/apk/res/android"&gt;
+   &lt;objectAnimator
+      android:duration="3000"
+      android:propertyName="pathData"
+      android:valueFrom="M300,70 l 0,-70 70,70 0,0   -70,70z"
+      android:valueTo="M300,70 l 0,-70 70,0  0,140 -70,0 z"
+      android:valueType="pathType"/&gt;
+&lt;/set&gt;
+</pre>
+  </li>
+</ul>
+</p>
+<h4 id="single-file">
+  Single XML file
+</h4>
+
+<p>
+  By using this approach, you can merge the related XML files into a single
+  XML file through the XML Bundle Format. At the time of building the app, the
+  <code>aapt</code> tag creates separate resources and references them in the
+  animated vector. This approach requires Build Tools 24 or higher, and the
+  output is backward compatible.
+</p>
+
+<h5>
+  Example of a single XML file
+</h5>
+<pre>
+&lt;animated-vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:aapt="http://schemas.android.com/aapt"&gt;
+    &lt;aapt:attr name="android:drawable"&gt;
+        &lt;vector
+            android:width="24dp"
+            android:height="24dp"
+            android:viewportWidth="24"
+            android:viewportHeight="24"&gt;
+            &lt;path
+                android:name="root"
+                android:strokeWidth="2"
+                android:strokeLineCap="square"
+                android:strokeColor="?android:colorControlNormal"
+                android:pathData="M4.8,13.4 L9,17.6 M10.4,16.2 L19.6,7" /&gt;
+        &lt;/vector&gt;
+    &lt;/aapt:attr&gt;
+    &lt;target android:name="root"&gt;
+        &lt;aapt:attr name="android:animation"&gt;
+            &lt;objectAnimator
+                android:propertyName="pathData"
+                android:valueFrom="M4.8,13.4 L9,17.6 M10.4,16.2 L19.6,7"
+                android:valueTo="M6.4,6.4 L17.6,17.6 M6.4,17.6 L17.6,6.4"
+                android:duration="300"
+                android:interpolator="@android:interpolator/fast_out_slow_in"
+                android:valueType="pathType" /&gt;
+        &lt;/aapt:attr&gt;
+    &lt;/target&gt;
+&lt;/animated-vector&gt;
+</pre>
\ No newline at end of file
diff --git a/docs/html/guide/topics/manifest/provider-element.jd b/docs/html/guide/topics/manifest/provider-element.jd
index 1947849..0e729c3 100644
--- a/docs/html/guide/topics/manifest/provider-element.jd
+++ b/docs/html/guide/topics/manifest/provider-element.jd
@@ -215,17 +215,15 @@
 </p></dd>
 
 <dt><a name="multi"></a>{@code android:multiprocess}</dt>
-<dd>Whether or not an instance of the content provider can be created in
-every client process &mdash; "{@code true}" if instances can run in multiple
-processes, and "{@code false}" if not.  The default value is "{@code false}".
+<dd>If the app runs in multiple processes, this attribute determines whether
+multiple instances of the content provder are created. If <code>true</code>,
+each of the app's processes has its own content provider object. If
+<code>false</code>, the app's processes share only one content provider object.
+The default value is <code>false</code>.
 
-<p>
-Normally, a content provider is instantiated in the process of the
-application that defined it.  However, if this flag is set to "{@code true}",
-the system can create an instance in every process where there's a client
-that wants to interact with it, thus avoiding the overhead of interprocess
-communication.
-</p></dd>
+<p>Setting this flag to <code>true</code> may improve performance by reducing
+the overhead of interprocess communication, but it also increases the memory
+footprint of each process.</p></dd>
 
 <dt><a name="nm"></a>{@code android:name}</dt>
 <dd>The name of the class that implements the content provider, a subclass of
diff --git a/docs/html/guide/topics/manifest/receiver-element.jd b/docs/html/guide/topics/manifest/receiver-element.jd
index 800ee8a..c866047 100644
--- a/docs/html/guide/topics/manifest/receiver-element.jd
+++ b/docs/html/guide/topics/manifest/receiver-element.jd
@@ -33,8 +33,18 @@
 declare it in the manifest file with this element.  The other is to create
 the receiver dynamically in code and register it with the <code>{@link
 android.content.Context#registerReceiver Context.registerReceiver()}</code>
-method.  See the {@link android.content.BroadcastReceiver} class description
-for more on dynamically created receivers.
+method. For more information about how to dynamically create receivers, see the
+{@link android.content.BroadcastReceiver} class description.
+</p>
+
+<p class="warning">
+    <strong>Warning:</strong> Limit how many broadcast
+    receivers you set in your app. Having too many broadcast receivers can
+    affect your app's performance and the battery life of users' devices.
+    For more information about APIs you can use instead of the
+    {@link android.content.BroadcastReceiver} class for scheduling background
+    work, see
+    <a href="/topic/performance/background-optimization.html">Background Optimizations</a>.
 </p></dd>
 
 <dt>attributes:</dt>
diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd
index 26ae59f..843fe1c 100755
--- a/docs/html/guide/topics/manifest/uses-feature-element.jd
+++ b/docs/html/guide/topics/manifest/uses-feature-element.jd
@@ -512,10 +512,11 @@
 
 <li>Next, locate the <code>aapt</code> tool, if it is not already in your PATH.
 If you are using SDK Tools r8 or higher, you can find <code>aapt</code> in the
-<code>&lt;<em>SDK</em>&gt;/platform-tools/</code> directory.
+<code>&lt;<em>SDK</em>&gt;/build-tools/&lt;<em>tools version number</em>&gt;</code>
+directory.
 <p class="note"><strong>Note:</strong> You must use the version of
-<code>aapt</code> that is provided for the latest Platform-Tools component available. If
-you do not have the latest Platform-Tools component, download it using the <a
+<code>aapt</code> that is provided for the latest Build-Tools component available. If
+you do not have the latest Build-Tools component, download it using the <a
 href="{@docRoot}studio/intro/update.html">Android SDK Manager</a>.
 </p></li>
 <li>Run <code>aapt</code> using this syntax: </li>
@@ -1732,7 +1733,7 @@
     </p>
     <p>
       <code>android.hardware.location.network</code>
-      (Only when target API level is 20 orlower.)
+      (Only when target API level is 20 or lower.)
     </p>
   </td>
 <!--  <td></td> -->
@@ -1745,7 +1746,7 @@
     </p>
     <p>
       <code>android.hardware.location.gps</code>
-      (Only when target API level is 20 orlower.)
+      (Only when target API level is 20 or lower.)
     </p>
   </td>
 
diff --git a/docs/html/guide/topics/providers/content-provider-creating.jd b/docs/html/guide/topics/providers/content-provider-creating.jd
index ec6909c..59dc108 100755
--- a/docs/html/guide/topics/providers/content-provider-creating.jd
+++ b/docs/html/guide/topics/providers/content-provider-creating.jd
@@ -460,7 +460,7 @@
                  * present. Get the last path segment from the URI; this is the _ID value.
                  * Then, append the value to the WHERE clause for the query
                  */
-                selection = selection + "_ID = " uri.getLastPathSegment();
+                selection = selection + "_ID = " + uri.getLastPathSegment();
                 break;
 
             default:
diff --git a/docs/html/guide/topics/ui/controls/togglebutton.jd b/docs/html/guide/topics/ui/controls/togglebutton.jd
index e0549ec..181647c 100644
--- a/docs/html/guide/topics/ui/controls/togglebutton.jd
+++ b/docs/html/guide/topics/ui/controls/togglebutton.jd
@@ -14,6 +14,7 @@
   <ol>
     <li>{@link android.widget.ToggleButton}</li>
     <li>{@link android.widget.Switch}</li>
+    <li>{@link android.support.v7.widget.SwitchCompat}</li>
     <li>{@link android.widget.CompoundButton}</li>
   </ol>
 </div>
@@ -21,9 +22,12 @@
 
 <p>A toggle button allows the user to change a setting between two states.</p>
 
-<p>You can add a basic toggle button to your layout with the {@link android.widget.ToggleButton}
-object. Android 4.0 (API level 14) introduces another kind of toggle button called a switch that
-provides a slider control, which you can add with a {@link android.widget.Switch} object.</p>
+<p>You can add a basic toggle button to your layout with the
+{@link android.widget.ToggleButton} object. Android 4.0 (API level 14)
+introduces another kind of toggle button called a switch that provides a slider
+control, which you can add with a {@link android.widget.Switch} object.
+{@link android.support.v7.widget.SwitchCompat} is a version of the Switch
+widget which runs on devices back to API 7.</p>
 
 <p>
   If you need to change a button's state yourself, you can use the {@link
diff --git a/docs/html/guide/topics/ui/drag-drop.jd b/docs/html/guide/topics/ui/drag-drop.jd
index 8871c87..8e4297f 100644
--- a/docs/html/guide/topics/ui/drag-drop.jd
+++ b/docs/html/guide/topics/ui/drag-drop.jd
@@ -152,7 +152,7 @@
     drag event listeners or callback methods of each View in the layout. The listeners or callback
     methods can use the metadata to decide if they want to accept the data when it is dropped.
     If the user drops the data over a View object, and that View object's listener or callback
-    method has previously told the system that it wants to accept the drop, then the system sends
+    method has previously told the system that it wants to accept the data, then the system sends
     the data to the listener or callback method in a drag event.
 </p>
 <p>
@@ -226,7 +226,8 @@
     </dt>
     <dd>
         The user releases the drag shadow within the bounding box of a View that can accept the
-        data. The system sends the View object's listener a drag event with action type
+        data, but not within its descendant view that can accept the data. The system sends the View
+        object's listener a drag event with action type
         {@link android.view.DragEvent#ACTION_DROP}. The drag event contains the data that was
         passed to the system in the call to
         {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
@@ -317,6 +318,10 @@
             application calls
 {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()} and
             gets a drag shadow.
+            <p>
+                If the listener wants to continue receiving drag events for this operation, it must
+                return boolean <code>true</code> to the system.
+            </p>
         </td>
     </tr>
     <tr>
@@ -324,9 +329,7 @@
         <td>
             A View object's drag event listener receives this event action type when the drag shadow
             has just entered the bounding box of the View. This is the first event action type the
-            listener receives when the drag shadow enters the bounding box. If the listener wants to
-            continue receiving drag events for this operation, it must return boolean
-            <code>true</code> to the system.
+            listener receives when the drag shadow enters the bounding box.
         </td>
     </tr>
     <tr>
@@ -334,7 +337,8 @@
         <td>
             A View object's drag event listener receives this event action type after it receives a
             {@link android.view.DragEvent#ACTION_DRAG_ENTERED} event while the drag shadow is
-            still within the bounding box of the View.
+            still within the bounding box of the View and not within a descendant view that can
+            accept the data.
         </td>
     </tr>
     <tr>
@@ -343,7 +347,8 @@
             A View object's drag event listener receives this event action type after it receives a
             {@link android.view.DragEvent#ACTION_DRAG_ENTERED} and at least one
             {@link android.view.DragEvent#ACTION_DRAG_LOCATION} event, and after the user has moved
-            the drag shadow outside the bounding box of the View.
+            the drag shadow outside the bounding box of the View or into a descendant view that can
+            accept the data.
         </td>
     </tr>
     <tr>
@@ -395,7 +400,7 @@
         <td style="text-align: center;">X</td>
         <td style="text-align: center;">X</td>
         <td style="text-align: center;">X</td>
-        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">X</td>
         <td style="text-align: center;">&nbsp;</td>
         <td style="text-align: center;">&nbsp;</td>
     </tr>
@@ -711,8 +716,7 @@
         If the listener can accept a drop, it should return <code>true</code>. This tells
         the system to continue to send drag events to the listener.
         If it can't accept a drop, it should return <code>false</code>, and the system
-        will stop sending drag events until it sends out
-        {@link android.view.DragEvent#ACTION_DRAG_ENDED}.
+        will stop sending drag events for the current drag operation.
     </li>
 </ol>
 <p>
@@ -754,7 +758,8 @@
     <li>
         {@link android.view.DragEvent#ACTION_DRAG_EXITED}:  This event is sent to a listener that
         previously received {@link android.view.DragEvent#ACTION_DRAG_ENTERED}, after
-        the drag shadow is no longer within the bounding box of the listener's View.
+        the drag shadow is no longer within the bounding box of the listener's View or it's within
+        the bounding box of a descendant view that can accept the data.
     </li>
 </ul>
 <p>
diff --git a/docs/html/guide/topics/ui/multi-window.jd b/docs/html/guide/topics/ui/multi-window.jd
index dede557..bab582d 100644
--- a/docs/html/guide/topics/ui/multi-window.jd
+++ b/docs/html/guide/topics/ui/multi-window.jd
@@ -215,7 +215,7 @@
   Set this attribute in your manifest's <a href=
   "{@docRoot}guide/topics/manifest/activity-element"><code>&lt;activity&gt;</code></a>
   node to indicate whether the activity supports <a href=
-  "{@docRoot}training/tv/playback/picture-in-picture.jd">Picture-in-Picture</a>
+  "{@docRoot}training/tv/playback/picture-in-picture.html">Picture-in-Picture</a>
   display. This attribute is ignored if <code>android:resizeableActivity</code>
   is false.
 </p>
diff --git a/docs/html/images/brand/android_logo_no.png b/docs/html/images/brand/android_logo_no.png
index 8de22d8..946bc49 100644
--- a/docs/html/images/brand/android_logo_no.png
+++ b/docs/html/images/brand/android_logo_no.png
Binary files differ
diff --git a/docs/html/images/brand/android_logo_no_2x.png b/docs/html/images/brand/android_logo_no_2x.png
new file mode 100644
index 0000000..8434c79
--- /dev/null
+++ b/docs/html/images/brand/android_logo_no_2x.png
Binary files differ
diff --git a/docs/html/images/develop/hero-layout-editor.png b/docs/html/images/develop/hero-layout-editor.png
new file mode 100644
index 0000000..195150e
--- /dev/null
+++ b/docs/html/images/develop/hero-layout-editor.png
Binary files differ
diff --git a/docs/html/images/develop/hero-layout-editor_2x.png b/docs/html/images/develop/hero-layout-editor_2x.png
index 56dfbf3..60c3d24 100644
--- a/docs/html/images/develop/hero-layout-editor_2x.png
+++ b/docs/html/images/develop/hero-layout-editor_2x.png
Binary files differ
diff --git a/docs/html/images/guide/topics/graphics/ic_battery_charging_80_black_24dp.png b/docs/html/images/guide/topics/graphics/ic_battery_charging_80_black_24dp.png
new file mode 100644
index 0000000..44a4e86
--- /dev/null
+++ b/docs/html/images/guide/topics/graphics/ic_battery_charging_80_black_24dp.png
Binary files differ
diff --git a/docs/html/images/guide/topics/graphics/vectorpath.png b/docs/html/images/guide/topics/graphics/vectorpath.png
new file mode 100644
index 0000000..592bab67
--- /dev/null
+++ b/docs/html/images/guide/topics/graphics/vectorpath.png
Binary files differ
diff --git a/docs/html/images/tools/sdk-manager-support-libs.png b/docs/html/images/tools/sdk-manager-support-libs.png
deleted file mode 100644
index cb4cea5..0000000
--- a/docs/html/images/tools/sdk-manager-support-libs.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/images/tools/studio-sdk-manager-packages.png b/docs/html/images/tools/studio-sdk-manager-packages.png
deleted file mode 100644
index 79ea912..0000000
--- a/docs/html/images/tools/studio-sdk-manager-packages.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index 39e3d73..78fc848 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -73,14 +73,19 @@
       </a>
     </div>
     <div class="col-7of16 col-pull-6of16">
-        <h1 class="dac-hero-title" style="color:#004d40">Android Studio 2.2!</h1>
-<p class="dac-hero-description" style="color:#004d40">The latest update is
-packed with over 20 new features, like a rewritten layout editor with the
-new constraint layout, support for Android 7.0 Nougat, Espresso test recording,
-enhanced Jack compiler / Java 8 support, expanded C++ support with CMake and
-NDK-Build, and much more!</p>
-<p class="dac-hero-description" style="color:#004d40">Android Studio 2.2
-helps you code faster and smarter.</p>
+        <h1 class="dac-hero-title" style="color:#004d40">Android Studio 2.2</h1>
+
+<p class="dac-hero-description" style="color:#004d40">Packed with 20+ new
+features, Android Studio 2.2 focuses on speed, smarts, and Android platform
+support.</p>
+
+<p class="dac-hero-description" style="color:#004d40">Develop faster with
+features such as the new Layout Editor, and develop smarter with the new APK
+analyzer, expanded code analysis and more.</p>
+
+<p class="dac-hero-description" style="color:#004d40">Plus, this update
+includes support for all the latest developer features in Android 7.0 Nougat,
+with an updated emulator to test them all out.</p>
 
 <p style="margin-top:24px">
    <a class="dac-hero-cta" href="/studio/index.html" style="color:#004d40">
@@ -88,9 +93,9 @@
       Get Android Studio 2.2
     </a>
   &nbsp;&nbsp;&nbsp;&nbsp;<wbr>
-   <a class="dac-hero-cta" href="/studio/releases/index.html" style="color:#004d40">
+   <a class="dac-hero-cta" href="/studio/features.html" style="color:#004d40">
     <span class="dac-sprite dac-auto-chevron"></span>
-    See the release notes</a>
+    See more features</a>
 </p>
     </div>
   </div>
diff --git a/docs/html/jd_extras_en.js b/docs/html/jd_extras_en.js
index e4bd368..f76cf36 100644
--- a/docs/html/jd_extras_en.js
+++ b/docs/html/jd_extras_en.js
@@ -1032,6 +1032,17 @@
     "type":"distribute"
   },
   {
+    "title": "Play Games Quality",
+    "category": "google",
+    "summary": "Meet the basic expectations of game players through compelling features and an intuitive, well-designed UI.",
+    "url": "https://developers.google.com/games/services/checklist",
+    "group": "",
+    "keywords": ["games", "play games", "quality"],
+    "tags": [],
+    "image": "images/cards/distribute/engage/card-game-services.png",
+    "type": "distribute"
+  },
+  {
     "title":"Get Started with Analytics",
     "category":"google",
     "summary":"Get advanced insight into how players discover and play your games.",
@@ -2979,7 +2990,7 @@
     "timestamp": 1383243492000,
     "image": "images/cards/google-search_2x.png",
     "title": "Set Up App Indexing",
-    "summary": "Surface your app content in Google seaerch. Deep link direct to your apps.",
+    "summary": "Surface your app content in Google search. Deep link direct to your apps.",
     "keywords": ["search", "appindexing", "engagement", "getusers"],
     "type": "distribute",
     "category": "google"
@@ -4376,6 +4387,7 @@
       "distribute/essentials/quality/wear.html",
       "distribute/essentials/quality/tv.html",
       "distribute/essentials/quality/auto.html",
+      "https://developers.google.com/games/services/checklist",
       "distribute/essentials/quality/billions.html",
       "https://developers.google.com/edu/guidelines"
     ]
diff --git a/docs/html/training/accessibility/service.jd b/docs/html/training/accessibility/service.jd
index 9965cf8..c034145 100755
--- a/docs/html/training/accessibility/service.jd
+++ b/docs/html/training/accessibility/service.jd
@@ -200,7 +200,7 @@
 }
 </pre>
 
-<h2 id="query">Query the View Hierarchy's for More Context</h2>
+<h2 id="query">Query the View Hierarchy for More Context</h2>
 <p>This step is optional, but highly useful. The Android platform provides the ability for an
 {@link android.accessibilityservice.AccessibilityService} to query the view
 hierarchy, collecting information about the UI component that generated an event, and
diff --git a/docs/html/training/articles/perf-anr.jd b/docs/html/training/articles/perf-anr.jd
index 2eda4fa..58db3e2 100644
--- a/docs/html/training/articles/perf-anr.jd
+++ b/docs/html/training/articles/perf-anr.jd
@@ -14,6 +14,14 @@
   <li><a href="#Reinforcing">Reinforcing Responsiveness</a></li>
 </ol>
 
+<h2>You should also read</h2>
+<ul>
+  <li><a href="/topic/performance/background-optimization.html">Background Optimizations</a>
+  <li><a href="/topic/performance/scheduling.html">Intelligent Job-Scheduling</a>
+  <li><a href="/training/monitoring-device-state/manifest-receivers.html">Manipulating Broadcast Receivers On Demand</a>
+  <li><a href="/guide/components/intents-filters.html">Intents and Intent Filters</a>
+</ul>
+
 </div>
 </div>
 
@@ -165,6 +173,16 @@
 potentially long running action needs to be taken in response to an intent
 broadcast.</p>
 
+<p>
+  Another common issue with {@link android.content.BroadcastReceiver} objects
+  occurs when they execute too frequently. Frequent background execution can
+  reduce the amount of memory available to other apps.
+  For more information about how to enable and disable
+  {@link android.content.BroadcastReceiver} objects efficiently, see
+  <a href="/training/monitoring-device-state/manifest-receivers.html">Manipulating
+    Broadcast Receivers on Demand</a>.
+</p>
+
 <p class="note"><strong>Tip:</strong>
 You can use {@link android.os.StrictMode} to help find potentially
 long running operations such as network or database operations that
diff --git a/docs/html/training/camera/videobasics.jd b/docs/html/training/camera/videobasics.jd
index 6da239a..b20cfef 100644
--- a/docs/html/training/camera/videobasics.jd
+++ b/docs/html/training/camera/videobasics.jd
@@ -108,7 +108,7 @@
 
 <pre>
 &#64;Override
-protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
     if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == RESULT_OK) {
         Uri videoUri = intent.getData();
         mVideoView.setVideoURI(videoUri);
diff --git a/docs/html/training/monitoring-device-state/battery-monitoring.jd b/docs/html/training/monitoring-device-state/battery-monitoring.jd
index db75aaf..bab9c9c 100644
--- a/docs/html/training/monitoring-device-state/battery-monitoring.jd
+++ b/docs/html/training/monitoring-device-state/battery-monitoring.jd
@@ -141,10 +141,11 @@
 condition by listening for {@link android.content.Intent#ACTION_BATTERY_LOW} and {@link
 android.content.Intent#ACTION_BATTERY_OKAY}.</p>
 
-<pre>&lt;receiver android:name=".BatteryLevelReceiver">
-&lt;intent-filter>
-  &lt;action android:name="android.intent.action.ACTION_BATTERY_LOW"/>
-  &lt;action android:name="android.intent.action.ACTION_BATTERY_OKAY"/>
+<pre>
+&lt;receiver android:name=".BatteryLevelReceiver">
+  &lt;intent-filter>
+    &lt;action android:name="android.intent.action.BATTERY_LOW"/>
+    &lt;action android:name="android.intent.action.BATTERY_OKAY"/>
   &lt;/intent-filter>
 &lt;/receiver></pre>
 
diff --git a/docs/html/training/monitoring-device-state/connectivity-monitoring.jd b/docs/html/training/monitoring-device-state/connectivity-monitoring.jd
index 2dd904f..c63822b 100644
--- a/docs/html/training/monitoring-device-state/connectivity-monitoring.jd
+++ b/docs/html/training/monitoring-device-state/connectivity-monitoring.jd
@@ -33,7 +33,7 @@
 <p>Some of the most common uses for repeating alarms and background services is to schedule regular
 updates of application data from Internet resources, cache data, or execute long running downloads.
 But if you aren't connected to the Internet, or the connection is too slow to complete your
-download, why both waking the device to schedule the update at all?</p>
+download, why bother waking the device to schedule the update at all?</p>
 
 <p>You can use the {@link android.net.ConnectivityManager} to check that you're actually
 connected to the Internet, and if so, what type of connection is in place.</p>
diff --git a/docs/html/training/monitoring-device-state/manifest-receivers.jd b/docs/html/training/monitoring-device-state/manifest-receivers.jd
index 3e36dba..5efa2fa 100644
--- a/docs/html/training/monitoring-device-state/manifest-receivers.jd
+++ b/docs/html/training/monitoring-device-state/manifest-receivers.jd
@@ -21,7 +21,10 @@
 
 <h2>You should also read</h2>
 <ul>
-  <li><a href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a>
+  <li><a href="/topic/performance/background-optimization.html">Background Optimizations</a>
+  <li><a href="/topic/performance/scheduling.html">Intelligent Job-Scheduling</a>
+  <li><a href="/training/articles/perf-anr.html">Keeping Your App Responsive</a>
+  <li><a href="/guide/components/intents-filters.html">Intents and Intent Filters</a>
 </ul>
 
 </div>
@@ -32,13 +35,22 @@
 your application manifest. Then within each of these receivers you simply reschedule your recurring
 alarms based on the current device state.</p>
 
-<p>A side-effect of this approach is that your app will wake the device each time any of these
-receivers is triggered&mdash;potentially much more frequently than required.</p>
-
 <p>A better approach is to disable or enable the broadcast receivers at runtime. That way you can
 use the receivers you declared in the manifest as passive alarms that are triggered by system events
 only when necessary.</p>
 
+<p class="warning">
+    <strong>Warning:</strong> Limit how many broadcast
+    receivers you set in your app. Instead of using broadcast receivers,
+    consider using other APIs for
+    performing background work. For example, in Android 5.0 (API level 21) and
+    higher, you can use the {@link android.app.job.JobScheduler} class for
+    assigning work to be completed in the background.
+    For more information about APIs you can use instead of the
+    {@link android.content.BroadcastReceiver} class for scheduling background
+    work, see
+    <a href="{@docRoot}topic/performance/background-optimization.html">Background Optimizations</a>.
+</p>
 
 <h2 id="ToggleReceivers">Toggle and Cascade State Change Receivers to Improve Efficiency </h2>
 
diff --git a/docs/html/training/testing/ui-testing/espresso-testing.jd b/docs/html/training/testing/ui-testing/espresso-testing.jd
index d3d31de..3d2bca7 100644
--- a/docs/html/training/testing/ui-testing/espresso-testing.jd
+++ b/docs/html/training/testing/ui-testing/espresso-testing.jd
@@ -24,17 +24,11 @@
         </h2>
 
         <ol>
-          <li>
-            <a href="#setup">Set Up Espresso</a>
-          </li>
+          <li><a href="#setup">Set Up Espresso</a></li>
 
-          <li>
-            <a href="#build">Create an Espresso Test Class</a>
-          </li>
+          <li><a href="#build">Create an Espresso Test Class</a></li>
 
-          <li>
-            <a href="#run">Run Espresso Tests on a Device or Emulator</a>
-          </li>
+          <li><a href="#run">Run Espresso Tests on a Device or Emulator</a></li>
         </ol>
 
         <h2>
@@ -59,31 +53,40 @@
             class="external-link">Android Testing Codelab</a></li>
         </ul>
       </div>
-    </div>
+</div>
 
     <p>
       Testing user interactions
       within a single app helps to ensure that users do not
-      encounter unexpected results or have a poor experience when interacting with your app.
-      You should get into the habit of creating user interface (UI) tests if you need to verify
+      encounter unexpected results or have a poor
+      experience when interacting with your app.
+      You should get into the habit of creating
+      user interface (UI) tests if you need to verify
       that the UI of your app is functioning correctly.
     </p>
 
     <p>
       The Espresso testing framework, provided by the
       <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>,
-      provides APIs for writing UI tests to simulate user interactions within a
-      single target app. Espresso tests can run on devices running Android 2.2 (API level 8) and
-      higher. A key benefit of using Espresso is that it provides automatic synchronization of test
-      actions with the UI of the app you are testing. Espresso detects when the main thread is idle,
-      so it is able to run your test commands at the appropriate time, improving the reliability of
-      your tests. This capability also relieves you from having to adding any timing workarounds,
-      such as a sleep period, in your test code.
+      provides APIs for writing UI tests to simulate
+      user interactions within a
+      single target app. Espresso tests can run on
+      devices running Android 2.3.3 (API level 10) and
+      higher. A key benefit of using Espresso is
+      that it provides automatic synchronization of test
+      actions with the UI of the app you are testing.
+      Espresso detects when the main thread is idle,
+      so it is able to run your test commands
+      at the appropriate time, improving the reliability of
+      your tests. This capability also relieves you
+      from having to add any timing workarounds,
+      such as {@link java.lang.Thread#sleep(long) Thread.sleep()}
+      in your test code.
     </p>
 
     <p>
-      The Espresso testing framework is an instrumentation-based API and works
-      with the
+      The Espresso testing framework is
+      an instrumentation-based API and works with the
       <a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code
       AndroidJUnitRunner}</a> test runner.
     </p>
@@ -92,105 +95,139 @@
       Set Up Espresso
     </h2>
 
-<p>Before building your UI test with Espresso, make sure to configure your test source code
-location and project dependencies, as described in
-<a href="{@docRoot}training/testing/start/index.html#config-instrumented-tests">
-Getting Started with Testing</a>.</p>
+<p>
+  Before building your UI test with Espresso,
+  make sure to configure your test source code
+  location and project dependencies, as described in
+  <a href="{@docRoot}training/testing/start/index.html#config-instrumented-tests">Getting Started with Testing</a>.
+</p>
 
-<p>In the {@code build.gradle} file of your Android app module, you must set a dependency
-  reference to the Espresso library:</p>
+<p>
+  In the {@code build.gradle} file of your Android app
+  module, you must set a dependency
+  reference to the Espresso library:
+</p>
 
 <pre>
 dependencies {
-    ...
-    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
+    // Other dependencies ...
+    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
 }
 </pre>
 
-<p>Turn off animations on your test device &mdash; leaving system animations turned on in the test
-device might cause unexpected results or may lead your test to fail. Turn off animations from
-<em>Settings</em> by opening <em>Developing Options</em> and turning all the following options off:
+<p>
+  Turn off animations on your test device &mdash;
+  leaving system animations turned on in the test
+  device might cause unexpected results or may
+  lead your test to fail. Turn off animations from
+  <em>Settings</em> by opening <em>Developer options</em>
+  and turning all the following options off:
 </p>
-        <ul>
-          <li>
-            <strong>Window animation scale</strong>
-          </li>
 
-          <li>
-            <strong>Transition animation scale</strong>
-          </li>
+<p>
+  <ul>
+    <li>
+      <strong>Window animation scale</strong>
+    </li>
 
-          <li>
-            <strong>Animator duration scale</strong>
-          </li>
-        </ul>
-      </li>
-    </ul>
-<p>If you want to set up your project to use Espresso features other than what the core API
+    <li>
+      <strong>Transition animation scale</strong>
+    </li>
+
+    <li>
+      <strong>Animator duration scale</strong>
+    </li>
+  </ul>
+</p>
+
+<p>
+  If you want to set up your project to use Espresso
+  features other than what the core API
   provides, see this
   <a href="https://google.github.io/android-testing-support-library/docs/espresso/index.html"
   class="external-link">resource</a>.</p>
 
-    <h2 id="build">
-      Create an Espresso Test Class
-    </h2>
+<!-- Section 2 -->
 
-    <p>
-      To create an Espresso test, create a Java class that follows this programming model:
-    </p>
+<h2 id="build">
+  Create an Espresso Test Class
+</h2>
 
-    <ol>
-      <li>Find the UI component you want to test in an {@link android.app.Activity} (for example, a
-      sign-in button in the app) by calling the
-      <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
-        {@code onView()}</a> method, or the
-      <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">
-      {@code onData()}</a> method for {@link android.widget.AdapterView} controls.
-      </li>
+<p>
+  To create an Espresso test, create a Java
+  class that follows this programming model:
+</p>
 
-      <li>Simulate a specific user interaction to perform on that UI component, by calling the
-      <a href="{@docRoot}reference/android/support/test/espresso/ViewInteraction.html#perform(android.support.test.espresso.ViewAction...)">{@code ViewInteraction.perform()}</a>
-      or
-      <a href="{@docRoot}reference/android/support/test/espresso/DataInteraction.html#perform(android.support.test.espresso.ViewAction...)">{@code DataInteraction.perform()}</a>
-      method and passing in the user action (for example, click on the sign-in button). To sequence
-      multiple actions on the same UI component, chain them using a comma-separated list in your
-      method argument.
-      </li>
+<ol>
+  <li>
+    Find the UI component you want to test in
+    an {@link android.app.Activity} (for example, a
+    sign-in button in the app) by calling the
+    <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
+    {@code onView()}</a> method, or the
+    <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">
+    {@code onData()}</a> method for {@link android.widget.AdapterView} controls.
+  </li>
 
-      <li>Repeat the steps above as necessary, to simulate a user flow across multiple
-      activities in the target app.
-      </li>
+  <li>
+    Simulate a specific user interaction to
+    perform on that UI component, by calling the
+    <a href="{@docRoot}reference/android/support/test/espresso/ViewInteraction.html#perform(android.support.test.espresso.ViewAction...)">{@code ViewInteraction.perform()}</a>
+    or
+    <a href="{@docRoot}reference/android/support/test/espresso/DataInteraction.html#perform(android.support.test.espresso.ViewAction...)">{@code DataInteraction.perform()}</a>
+    method and passing in the user action
+    (for example, click on the sign-in button). To sequence
+    multiple actions on the same UI component, chain them using a comma-separated list in your
+    method argument.
+  </li>
 
-      <li>Use the
+  <li>
+    Repeat the steps above as necessary, to simulate a user flow across multiple
+    activities in the target app.
+  </li>
+
+  <li>
+    Use the
     <a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html">{@code ViewAssertions}</a>
-        methods to check that the UI reflects the expected
-      state or behavior, after these user interactions are performed.
-      </li>
-    </ol>
+    methods to check that the UI reflects the expected
+    state or behavior, after these user interactions are performed.
+  </li>
+</ol>
 
-    <p>
-      These steps are covered in more detail in the sections below.
-    </p>
+<p>
+  These steps are covered in more detail in the sections below.
+</p>
 
-    <p>
-      The following code snippet shows how your test class might invoke this basic workflow:
-    </p>
+<p>
+  The following code snippet shows how your test
+  class might invoke this basic workflow:
+</p>
 
 <pre>
 onView(withId(R.id.my_view))            // withId(R.id.my_view) is a ViewMatcher
         .perform(click())               // click() is a ViewAction
         .check(matches(isDisplayed())); // matches(isDisplayed()) is a ViewAssertion
 </pre>
-<h3 id="espresso-atr">Using Espresso with ActivityTestRule</h3>
+
+<!-- Section 2.1 -->
+
+<h3 id="espresso-atr">
+  Using Espresso with ActivityTestRule
+</h3>
+
 <p>
-The following section describes how to create a new Espresso test in the JUnit 4 style and use
-<a href="{@docRoot}reference/android/support/test/rule/ActivityTestRule.html">
-{@code ActivityTestRule}</a> to reduce the amount of boilerplate code you need to write. By using
-<a href="{@docRoot}reference/android/support/test/rule/ActivityTestRule.html">
-{@code ActivityTestRule}</a>, the testing framework launches the activity under test
-before each test method annotated with <code>&#64;Test</code> and before any method annotated with
-<code>&#64;Before</code>. The framework handles shutting down the activity after the test finishes
-and all methods annotated with <code>&#64;After</code> are run.</p>
+  The following section describes how to create a
+  new Espresso test in the JUnit 4 style and use
+  <a href="{@docRoot}reference/android/support/test/rule/ActivityTestRule.html">{@code ActivityTestRule}</a>
+  to reduce the amount of boilerplate code you need to write. By using
+  <a href="{@docRoot}reference/android/support/test/rule/ActivityTestRule.html">{@code ActivityTestRule}</a>,
+  the testing framework launches the activity under test
+  before each test method annotated with
+  <code>&#64;Test</code> and before any method annotated with
+  <code>&#64;Before</code>. The framework handles
+  shutting down the activity after the test finishes
+  and all methods annotated with <code>&#64;After</code> are run.
+</p>
 
 <pre>
 package com.example.android.testing.espresso.BasicSample;
@@ -234,103 +271,57 @@
 }
 </pre>
 
-    <h3 id="espresso-aitc2">
-      Using Espresso with ActivityInstrumentationTestCase2
-    </h3>
-<p>The following section describes how to migrate to Espresso if you have existing test classes
-subclassed from {@link android.test.ActivityInstrumentationTestCase2} and you don't want to rewrite
-them to use JUnit4.</p>
-<p class="note"><strong>Note:</strong> For new UI tests, we strongly recommend that you write your
-test in the JUnit 4 style and use the
-<a href="{@docRoot}reference/android/support/test/rule/ActivityTestRule.html">
-{@code ActivityTestRule}</a> class, instead of
-{@link android.test.ActivityInstrumentationTestCase2}.</p>
-    <p>
-      If you are subclassing {@link android.test.ActivityInstrumentationTestCase2}
-      to create your Espresso test class, you must inject an
-      {@link android.app.Instrumentation} instance into your test class. This step is required in
-      order for your Espresso test to run with the
-      <a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code AndroidJUnitRunner}</a>
-      test runner.
-    </p>
+<!-- Section 2.2 -->
 
-    <p>
-      To do this, call the
-      {@link android.test.InstrumentationTestCase#injectInstrumentation(android.app.Instrumentation) injectInstrumentation()}
-      method and pass in the result of
-      <a href="{@docRoot}reference/android/support/test/InstrumentationRegistry.html#getInstrumentation()">
-      {@code InstrumentationRegistry.getInstrumentation()}</a>, as shown in the following code
-      example:
-    </p>
+<h3 id="accessing-ui-components">
+  Accessing UI Components
+</h3>
 
-<pre>
-import android.support.test.InstrumentationRegistry;
+<p>
+  Before Espresso can interact with the app
+  under test, you must first specify the UI component
+  or <em>view</em>. Espresso supports the use of
+  <a href="http://hamcrest.org/" class="external-link">Hamcrest matchers</a>
+  for specifying views and adapters in your app.
+</p>
 
-public class MyEspressoTest
-        extends ActivityInstrumentationTestCase2&lt;MyActivity&gt; {
+<p>
+  To find the view, call the
+  <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">{@code onView()}</a>
+  method and pass in a view matcher that
+  specifies the view that you are targeting. This is
+  described in more detail in
+  <a href="#specifying-view-matcher">Specifying a View Matcher</a>.
+  The <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">{@code onView()}</a>
+  method returns a
+  <a href="{@docRoot}reference/android/support/test/espresso/ViewInteraction.html">{@code ViewInteraction}</a>
+  object that allows your test to interact with the view.
+  However, calling the
+  <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
+  {@code onView()}</a>
+  method may not work if you want to locate a view in
+  an {@link android.support.v7.widget.RecyclerView} layout.
+  In this case, follow the instructions in
+  <a href="#locating-adpeterview-view">Locating a view in an AdapterView</a>
+  instead.
+</p>
 
-    private MyActivity mActivity;
+<p class="note">
+  <strong>Note</strong>:
+  The <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">{@code onView()}</a>
+  method does not check if the view you specified is
+  valid. Instead, Espresso searches only the
+  current view hierarchy, using the matcher provided.
+  If no match is found, the method throws a
+  <a href="{@docRoot}reference/android/support/test/espresso/NoMatchingViewException.html">{@code NoMatchingViewException}</a>.
+</p>
 
-    public MyEspressoTest() {
-        super(MyActivity.class);
-    }
-
-    &#64;Before
-    public void setUp() throws Exception {
-        super.setUp();
-        injectInstrumentation(InstrumentationRegistry.getInstrumentation());
-        mActivity = getActivity();
-    }
-
-   ...
-}
-</pre>
-
-<p class="note"><strong>Note:</strong> Previously, {@link android.test.InstrumentationTestRunner}
-would inject the {@link android.app.Instrumentation} instance, but this test runner is being
-deprecated.</p>
-
-    <h3 id="accessing-ui-components">
-      Accessing UI Components
-    </h3>
-
-    <p>
-      Before Espresso can interact with the app under test, you must first specify the UI component
-      or <em>view</em>. Espresso supports the use of
-<a href="http://hamcrest.org/" class="external-link">Hamcrest matchers</a>
-      for specifying views and adapters in your app.
-    </p>
-
-    <p>
-      To find the view, call the <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
-      {@code onView()}</a>
-      method and pass in a view matcher that specifies the view that you are targeting. This is
-      described in more detail in <a href="#specifying-view-matcher">Specifying a View Matcher</a>.
-      The <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
-      {@code onView()}</a> method returns a
-      <a href="{@docRoot}reference/android/support/test/espresso/ViewInteraction.html">
-      {@code ViewInteraction}</a>
-      object that allows your test to interact with the view.
-      However, calling  the <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
-      {@code onView()}</a> method may not work if you want to locate a view in
-      an {@link android.widget.AdapterView} layout. In this case, follow the instructions in
-      <a href="#locating-adpeterview-view">Locating a view in an AdapterView</a> instead.
-    </p>
-
-    <p class="note">
-      <strong>Note</strong>: The <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
-      {@code onView()}</a> method does not check if the view you specified is
-      valid. Instead, Espresso searches only the current view hierarchy, using the matcher provided.
-      If no match is found, the method throws a
-      <a href="{@docRoot}reference/android/support/test/espresso/NoMatchingViewException.html">
-      {@code NoMatchingViewException}</a>.
-    </p>
-
-    <p>
-      The following code snippet shows how you might write a test that accesses an
-      {@link android.widget.EditText} field, enters a string of text, closes the virtual keyboard,
-      and then performs a button click.
-    </p>
+<p>
+  The following code snippet shows how you might write a test that accesses an
+  {@link android.widget.EditText} field,
+  enters a string of text, closes the virtual keyboard,
+  and then performs a button click.
+</p>
 
 <pre>
 public void testChangeText_sameActivity() {
@@ -344,231 +335,464 @@
 }
 </pre>
 
-    <h4 id="specifying-view-matcher">
-      Specifying a View Matcher
-    </h4>
+<!-- Section 2.2.1 -->
+<h4 id="specifying-view-matcher">
+  Specifying a View Matcher
+</h4>
 
-    <p>
-      You can specify a view matcher by using these approaches:
-    </p>
+<p>
+  You can specify a view matcher by using these approaches:
+</p>
 
-    <ul>
-      <li>Calling methods in the
-        <a href="{@docRoot}reference/android/support/test/espresso/matcher/ViewMatchers.html">
-        {@code ViewMatchers}</a> class. For example, to find a view by looking for a text string it
-        displays, you can call a method like this:
-        <pre>
+<ul>
+  <li>Calling methods in the
+    <a href="{@docRoot}reference/android/support/test/espresso/matcher/ViewMatchers.html">{@code ViewMatchers}</a>
+    class. For example, to find a view by looking for a text string it
+    displays, you can call a method like this:
+<pre>
 onView(withText("Sign-in"));
 </pre>
 
-<p>Similarly you can call
-<a href="{@docRoot}reference/android/support/test/espresso/matcher/ViewMatchers.html#withId(int)">
-{@code withId()}</a> and providing the resource ID ({@code R.id}) of the view, as shown in the
-following example:</p>
+    <p>
+      Similarly you can call
+      <a href="{@docRoot}reference/android/support/test/espresso/matcher/ViewMatchers.html#withId(int)">{@code withId()}</a>
+      and providing the resource ID ({@code R.id}) of the view,
+      as shown in the
+      following example:
+    </p>
 
 <pre>
 onView(withId(R.id.button_signin));
 </pre>
 
     <p>
-      Android resource IDs are not guaranteed to be unique. If your test attempts to match to a
+      Android resource IDs are not guaranteed to be unique.
+      If your test attempts to match to a
       resource ID used by more than one view, Espresso throws an
-<a href="{@docRoot}reference/android/support/test/espresso/AmbiguousViewMatcherException.html">
-  {@code AmbiguousViewMatcherException}</a>.
+      <a href="{@docRoot}reference/android/support/test/espresso/AmbiguousViewMatcherException.html">{@code AmbiguousViewMatcherException}</a>.
     </p>
-      </li>
-      <li>Using the Hamcrest
-      <a href="http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matchers.html"
-         class="external-link">{@code Matchers}</a> class. You can use the
-      {@code allOf()} methods to combine multiple matchers, such as
-      {@code containsString()} and {@code instanceOf()}. This approach allows you to
-      filter the match results more narrowly, as shown in the following example:
+  </li>
+
+  <li>
+    Using the Hamcrest
+    <a href="http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matchers.html"
+    class="external-link">{@code Matchers}</a> class. You can use the
+    {@code allOf()} methods to combine multiple matchers, such as
+    {@code containsString()} and {@code instanceOf()}.
+    This approach allows you to
+    filter the match results more narrowly, as shown in the following example:
+
 <pre>
 onView(allOf(withId(R.id.button_signin), withText("Sign-in")));
 </pre>
-<p>You can use the {@code not} keyword to filter for views that don't correspond to the matcher, as
-shown in the following example:</p>
+
+    <p>
+      You can use the {@code not} keyword to filter
+      for views that don't correspond to the matcher, as
+      shown in the following example:
+    </p>
+
 <pre>
 onView(allOf(withId(R.id.button_signin), not(withText("Sign-out"))));
 </pre>
-<p>To use these methods in your test, import the {@code org.hamcrest.Matchers} package. To
-learn more about Hamcrest matching, see the
-<a href="http://hamcrest.org/" class="external-link">Hamcrest site</a>.
+
+    <p>
+      To use these methods in your test,
+      import the {@code org.hamcrest.Matchers} package. To
+      learn more about Hamcrest matching, see the
+      <a href="http://hamcrest.org/" class="external-link">Hamcrest site</a>.
+    </p>
+  </li>
+</ul>
+
+<p>
+  To improve the performance of your Espresso tests,
+  specify the minimum matching information
+  needed to find your target view. For example,
+  if a view is uniquely identifiable by its
+  descriptive text, you do not need to specify
+  that it is also assignable from the
+  {@link android.widget.TextView} instance.
 </p>
-      </li>
-    </ul>
 
-    <p>
-      To improve the performance of your Espresso tests, specify the minimum matching information
-      needed to find your target view. For example, if a view is uniquely identifiable by its
-      descriptive text, you do not need to specify that it is also assignable from the
-      {@link android.widget.TextView} instance.
-    </p>
+<!-- Section 2.2.2 -->
 
-    <h4 id="#locating-adpeterview-view">
-      Locating a view in an AdapterView
-    </h4>
+<h4 id="#locating-adpeterview-view">
+  Locating a view in an AdapterView
+</h4>
 
-    <p>
-      In an {@link android.widget.AdapterView} widget, the view is dynamically populated with child
-      views at runtime. If the target view you want to test is inside an
-      {@link android.widget.AdapterView}
-      (such as a {@link android.widget.ListView}, {@link android.widget.GridView}, or
-      {@link android.widget.Spinner}), the
-<a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
-  {@code onView()}</a> method might not work because only a
-      subset of the views may be loaded in the current view hierarchy.
-    </p>
+<p>
+  In an {@link android.widget.AdapterView} widget,
+  the view is dynamically populated with child
+  views at runtime. If the target view you want to test is inside an
+  {@link android.widget.AdapterView}
+  (such as a {@link android.widget.ListView},
+  {@link android.widget.GridView}, or
+  {@link android.widget.Spinner}), the
+  <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">{@code onView()}</a>
+  method might not work because only a
+  subset of the views may be loaded in the current view hierarchy.
+</p>
 
-    <p>
-      Instead, call the <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">{@code onData()}</a>
-      method to obtain a
-      <a href="{@docRoot}reference/android/support/test/espresso/DataInteraction.html">
-      {@code DataInteraction}</a>
-      object to access the target view element. Espresso handles loading the target view element
-      into the current view hierarchy. Espresso also takes care of scrolling to the target element,
-      and putting the element into focus.
-    </p>
-
-    <p class="note">
-      <strong>Note</strong>: The
+<p>
+  Instead, call the
   <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">{@code onData()}</a>
-      method does not check if if the item you specified corresponds with a view. Espresso searches
-      only the current view hierarchy. If no match is found, the method throws a
-      <a href="{@docRoot}reference/android/support/test/espresso/NoMatchingViewException.html">
-        {@code NoMatchingViewException}</a>.
-    </p>
+  method to obtain a
+  <a href="{@docRoot}reference/android/support/test/espresso/DataInteraction.html">{@code DataInteraction}</a>
+  object to access the target view element.
+  Espresso handles loading the target view element
+  into the current view hierarchy. Espresso
+  also takes care of scrolling to the target element,
+  and putting the element into focus.
+</p>
 
-    <p>
-      The following code snippet shows how you can use the
-      <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">{@code onData()}</a>
-      method together
-      with Hamcrest matching to search for a specific row in a list that contains a given string.
-      In this example, the {@code LongListActivity} class contains a list of strings exposed
-      through a {@link android.widget.SimpleAdapter}.
-    </p>
+<p class="note">
+  <strong>Note</strong>: The
+  <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">{@code onData()}</a>
+  method does not check if the item you
+  specified corresponds with a view. Espresso searches
+  only the current view hierarchy. If no match is found, the method throws a
+  <a href="{@docRoot}reference/android/support/test/espresso/NoMatchingViewException.html">{@code NoMatchingViewException}</a>.
+</p>
+
+<p>
+  The following code snippet shows how you can use the
+  <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">{@code onData()}</a>
+  method together
+  with Hamcrest matching to search for a specific
+  row in a list that contains a given string.
+  In this example, the {@code LongListActivity} class
+  contains a list of strings exposed
+  through a {@link android.widget.SimpleAdapter}.
+</p>
 
 <pre>
 onData(allOf(is(instanceOf(Map.class)),
-        hasEntry(equalTo(LongListActivity.ROW_TEXT), is(str))));
+        hasEntry(equalTo(LongListActivity.ROW_TEXT), is("test input")));
 </pre>
 
-    <h3 id="perform-actions">
-      Performing Actions
-    </h3>
+<!-- Section 2.3 -->
 
-    <p>
-      Call the <a href="{@docRoot}reference/android/support/test/espresso/ViewInteraction.html#perform(android.support.test.espresso.ViewAction...)">{@code ViewInteraction.perform()}</a>
-      or
-      <a href="{@docRoot}reference/android/support/test/espresso/DataInteraction.html#perform(android.support.test.espresso.ViewAction...)">{@code DataInteraction.perform()}</a>
-      methods to
-      simulate user interactions on the UI component. You must pass in one or more
-      <a href="{@docRoot}reference/android/support/test/espresso/ViewAction.html">{@code ViewAction}</a>
-      objects as arguments. Espresso fires each action in sequence according to
-      the given order, and executes them in the main thread.
-    </p>
+<h3 id="perform-actions">Performing Actions</h3>
 
-    <p>
-      The
-      <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html">{@code ViewActions}</a>
-      class provides a list of helper methods for specifying common actions.
-      You can use these methods as convenient shortcuts instead of creating and configuring
-      individual <a href="{@docRoot}reference/android/support/test/espresso/ViewAction.html">{@code ViewAction}</a>
-      objects. You can specify such actions as:
-    </p>
+<p>
+  Call the
+  <a href="{@docRoot}reference/android/support/test/espresso/ViewInteraction.html#perform(android.support.test.espresso.ViewAction...)">{@code ViewInteraction.perform()}</a>
+  or
+  <a href="{@docRoot}reference/android/support/test/espresso/DataInteraction.html#perform(android.support.test.espresso.ViewAction...)">{@code DataInteraction.perform()}</a>
+  methods to
+  simulate user interactions on the UI component. You must pass in one or more
+  <a href="{@docRoot}reference/android/support/test/espresso/ViewAction.html">{@code ViewAction}</a>
+  objects as arguments. Espresso fires each action in sequence according to
+  the given order, and executes them in the main thread.
+</p>
 
-    <ul>
-      <li>
-       <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#click()">{@code ViewActions.click()}</a>:
-       Clicks on the view.
-      </li>
+<p>
+  The
+  <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html">{@code ViewActions}</a>
+  class provides a list of helper methods for specifying common actions.
+  You can use these methods as convenient shortcuts
+  instead of creating and configuring individual
+  <a href="{@docRoot}reference/android/support/test/espresso/ViewAction.html">{@code ViewAction}</a>
+  objects. You can specify such actions as:
+</p>
 
-      <li>
-       <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#typeText(java.lang.String)">{@code ViewActions.typeText()}</a>:
-       Clicks on a view and enters a specified string.
-      </li>
+<ul>
+  <li>
+   <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#click()">{@code ViewActions.click()}</a>:
+   Clicks on the view.
+  </li>
 
-      <li>
-       <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#scrollTo()">{@code ViewActions.scrollTo()}</a>:
-       Scrolls to the view. The
-        target view must be subclassed from {@link android.widget.ScrollView}
-        and the value of its
-        <a href="http://developer.android.com/reference/android/view/View.html#attr_android:visibility">{@code android:visibility}</a>
-        property must be {@link android.view.View#VISIBLE}. For views that extend
-        {@link android.widget.AdapterView} (for example,
-        {@link android.widget.ListView}),
-        the
-        <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">{@code onData()}</a>
-        method takes care of scrolling for you.
-      </li>
+  <li>
+   <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#typeText(java.lang.String)">{@code ViewActions.typeText()}</a>:
+   Clicks on a view and enters a specified string.
+  </li>
 
-      <li>
-       <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#pressKey(int)">{@code ViewActions.pressKey()}</a>:
-       Performs a key press using a specified keycode.
-      </li>
+  <li>
+    <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#scrollTo()">{@code ViewActions.scrollTo()}</a>:
+    Scrolls to the view. The
+    target view must be subclassed from {@link android.widget.ScrollView}
+    and the value of its
+    <a href="http://developer.android.com/reference/android/view/View.html#attr_android:visibility">{@code android:visibility}</a>
+    property must be {@link android.view.View#VISIBLE}. For views that extend
+    {@link android.widget.AdapterView} (for example,
+    {@link android.widget.ListView}), the
+    <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">{@code onData()}</a>
+    method takes care of scrolling for you.
+  </li>
 
-      <li>
-      <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#clearText()">{@code ViewActions.clearText()}</a>:
-      Clears the text in the target view.
-      </li>
-    </ul>
+  <li>
+    <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#pressKey(int)">{@code ViewActions.pressKey()}</a>:
+    Performs a key press using a specified keycode.
+  </li>
 
-    <p>
-      If the target view is inside a {@link android.widget.ScrollView}, perform the
-      <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#scrollTo()">{@code ViewActions.scrollTo()}</a>
-      action first to display the view in the screen before other proceeding
-      with other actions. The
-      <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#scrollTo()">{@code ViewActions.scrollTo()}</a>
-      action will have no effect if the view is already displayed.
-    </p>
+  <li>
+    <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#clearText()">{@code ViewActions.clearText()}</a>:
+  Clears the text in the target view.
+  </li>
+</ul>
 
-    <h3 id="verify-results">
-      Verifying Results
-    </h3>
+<p>
+  If the target view is inside a {@link android.widget.ScrollView},
+  perform the
+  <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#scrollTo()">{@code ViewActions.scrollTo()}</a>
+  action first to display the view in the screen before other proceeding
+  with other actions. The
+  <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#scrollTo()">{@code ViewActions.scrollTo()}</a>
+  action will have no effect if the view is already displayed.
+</p>
 
-    <p>
-      Call the
-      <a href="{@docRoot}reference/android/support/test/espresso/ViewInteraction.html#check(android.support.test.espresso.ViewAssertion)">{@code ViewInteraction.check()}</a>
-      or
-      <a href="{@docRoot}reference/android/support/test/espresso/DataInteraction.html#check(android.support.test.espresso.ViewAssertion)">{@code DataInteraction.check()}</a>
-      method to assert
-      that the view in the UI matches some expected state. You must pass in a
-      <a href="{@docRoot}reference/android/support/test/espresso/ViewAssertion.html">
-      {@code ViewAssertion}</a> object as the argument. If the assertion fails, Espresso throws
-      an {@link junit.framework.AssertionFailedError}.
-    </p>
+<!-- Section 2.4 -->
 
-    <p>
-      The
+<h3 id="intents">
+  Test your activities in isolation with Espresso Intents
+</h3>
+
+<p>
+  <a href="https://google.github.io/android-testing-support-library/docs/espresso/intents/index.html" class="external-link">Espresso Intents</a>
+  enables validation and stubbing of intents sent out by an app.
+  With Espresso Intents, you can test an app, activity, or service in isolation
+  by intercepting outgoing intents, stubbing the result, and sending it back to
+  the component under test.
+</p>
+
+<p>
+  To begin testing with Espresso Intents, you need
+  to add the following line to your app's build.gradle file:
+</p>
+
+<pre>
+dependencies {
+  // Other dependencies ...
+  androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.2'
+}
+</pre>
+
+<p>
+  To test an intent, you need to create an instance of the
+  <a href="{@docRoot}reference/android/support/test/espresso/intent/rule/IntentsTestRule.html">IntentsTestRule</a>
+  class, which is very similar to the
+  <a href="{@docRoot}reference/android/support/test/rule/ActivityTestRule.html">ActivityTestRule</a>
+  class.
+  The
+  <a href="{@docRoot}reference/android/support/test/espresso/intent/rule/IntentsTestRule.html">IntentsTestRule</a>
+  class initializes Espresso Intents before each test,
+  terminates the host activity,
+  and releases Espresso Intents after each test.
+</p>
+
+<p>
+  The test class shown in the following codes snippet provides a simple
+  test for an explicit intent. It tests the activities and intents created in the
+  <a href="{@docRoot}training/basics/firstapp/index.html">Building Your First App</a>
+  tutorial.
+</p>
+
+<pre>
+&#64;Large
+&#64;RunWith(AndroidJUnit4.class)
+public class SimpleIntentTest {
+
+    private static final String MESSAGE = "This is a test";
+    private static final String PACKAGE_NAME = "com.example.myfirstapp";
+
+    /* Instantiate an IntentsTestRule object. */
+    &#64;Rule
+    public IntentsTestRule&lg;MainActivity&gt; mIntentsRule =
+      new IntentsTestRule&lg;&gt;(MainActivity.class);
+
+    &#64;Test
+    public void verifyMessageSentToMessageActivity() {
+
+        // Types a message into a EditText element.
+        onView(withId(R.id.edit_message))
+                .perform(typeText(MESSAGE), closeSoftKeyboard());
+
+        // Clicks a button to send the message to another
+        // activity through an explicit intent.
+        onView(withId(R.id.send_message)).perform(click());
+
+        // Verifies that the DisplayMessageActivity received an intent
+        // with the correct package name and message.
+        intended(allOf(
+                hasComponent(hasShortClassName(".DisplayMessageActivity")),
+                toPackage(PACKAGE_NAME),
+                hasExtra(MainActivity.EXTRA_MESSAGE, MESSAGE)));
+
+    }
+}
+</pre>
+
+<p>
+  For more information about Espresso Intents, see the
+  <a href="https://google.github.io/android-testing-support-library/docs/espresso/intents/index.html"
+  class="external-link">Espresso Intents
+  documentation on the Android Testing Support Library site</a>.
+  You can also download the
+  <a href="https://github.com/googlesamples/android-testing/tree/master/ui/espresso/IntentsBasicSample"
+  class="external-link">IntentsBasicSample</a> and
+  <a href="https://github.com/googlesamples/android-testing/tree/master/ui/espresso/IntentsAdvancedSample"
+  class="external-link">IntentsAdvancedSample</a>
+  code samples.
+</p>
+
+<!-- Section 2.5 -->
+
+<h3 id="webviews">
+  Testing WebViews with Espresso Web
+</h3>
+
+<p>
+  Espresso Web allows you to test {@link android.webkit.WebView} components
+  contained within an activity. It uses the
+  <a href="http://docs.seleniumhq.org/docs/03_webdriver.jsp"
+  class="external-link">WebDriver API</a> to inspect and control the
+  behavior of a {@link android.webkit.WebView}.
+</p>
+
+<p>
+  To begin testing with Espresso Web, you need
+  to add the following line to your app's build.gradle file:
+</p>
+
+<pre>
+dependencies {
+  // Other dependencies ...
+  androidTestCompile 'com.android.support.test.espresso:espresso-web:2.2.2'
+}
+</pre>
+
+<p>
+  When creating a test using Espresso Web, you need to enable
+  JavaScript on the {@link android.webkit.WebView} when you instantiate the
+  <a href="{@docRoot}reference/android/support/test/rule/ActivityTestRule.html">ActivityTestRule</a>
+  object to test the activity. In the tests, you can select
+  HTML elements displayed in the
+  {@link android.webkit.WebView} and simulate user interactions, like
+  entering text into a text box and then clicking a button. After the actions
+  are completed, you can then verify that the results on the
+  Web page match the results that you expect.
+</p>
+
+<p>
+  In the following code snippet, the class tests
+  a {@link android.webkit.WebView} component with the id value 'webview'
+  in the activity being tested.
+  The <code>verifyValidInputYieldsSuccesfulSubmission()</code> test selects an
+  <code>&lt;input&gt;</code> element on the
+  Web page, enters some text, and checks text that appears in
+  another element.
+</p>
+
+<pre>
+&#64;LargeTest
+&#64;RunWith(AndroidJUnit4.class)
+public class WebViewActivityTest {
+
+    private static final String MACCHIATO = "Macchiato";
+    private static final String DOPPIO = "Doppio";
+
+    &#64;Rule
+    public ActivityTestRule<WebViewActivity> mActivityRule =
+        new ActivityTestRule<WebViewActivity>(WebViewActivity.class,
+            false /* Initial touch mode */, false /*  launch activity */) {
+
+        &#64;Override
+        protected void afterActivityLaunched() {
+            // Enable JavaScript.
+            onWebView().forceJavascriptEnabled();
+        }
+    }
+
+    &#64;Test
+    public void typeTextInInput_clickButton_SubmitsForm() {
+       // Lazily launch the Activity with a custom start Intent per test
+       mActivityRule.launchActivity(withWebFormIntent());
+
+       // Selects the WebView in your layout.
+       // If you have multiple WebViews you can also use a
+       // matcher to select a given WebView, onWebView(withId(R.id.web_view)).
+       onWebView()
+           // Find the input element by ID
+           .withElement(findElement(Locator.ID, "text_input"))
+           // Clear previous input
+           .perform(clearElement())
+           // Enter text into the input element
+           .perform(DriverAtoms.webKeys(MACCHIATO))
+           // Find the submit button
+           .withElement(findElement(Locator.ID, "submitBtn"))
+           // Simulate a click via JavaScript
+           .perform(webClick())
+           // Find the response element by ID
+           .withElement(findElement(Locator.ID, "response"))
+           // Verify that the response page contains the entered text
+           .check(webMatches(getText(), containsString(MACCHIATO)));
+    }
+}
+</pre>
+
+<p>
+  For more information about Espresso Web, see the
+  <a href="https://google.github.io/android-testing-support-library/docs/espresso/web/index.html"
+  class="external-link">Espresso
+  Web documentation on the Android Testing Support Library site.</a>.
+  You can also download this code snippet as part of the
+  <a href="https://github.com/googlesamples/android-testing/tree/master/ui/espresso/WebBasicSample"
+  class="external-link">Espresso Web code sample</a>.
+</p>
+
+<!-- Section 2.6 -->
+
+<h3 id="verify-results">
+  Verifying Results
+</h3>
+
+<p>
+  Call the
+  <a href="{@docRoot}reference/android/support/test/espresso/ViewInteraction.html#check(android.support.test.espresso.ViewAssertion)">{@code ViewInteraction.check()}</a>
+  or
+  <a href="{@docRoot}reference/android/support/test/espresso/DataInteraction.html#check(android.support.test.espresso.ViewAssertion)">{@code DataInteraction.check()}</a>
+  method to assert
+  that the view in the UI matches some expected state. You must pass in a
+  <a href="{@docRoot}reference/android/support/test/espresso/ViewAssertion.html">{@code ViewAssertion}</a>
+  object as the argument. If the assertion fails, Espresso throws
+  an {@link junit.framework.AssertionFailedError}.
+</p>
+
+<p>
+  The
   <a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html">{@code ViewAssertions}</a>
-      class provides a list of helper methods for specifying common
-      assertions. The assertions you can use include:
-    </p>
+  class provides a list of helper methods for specifying common
+  assertions. The assertions you can use include:
+</p>
 
-    <ul>
-      <li>
-        <a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html#doesNotExist()">{@code doesNotExist}</a>:
-Asserts that there is no view matching the specified criteria in the current view hierarchy.
-      </li>
+<ul>
+  <li>
+    <a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html#doesNotExist()">{@code doesNotExist}</a>:
+    Asserts that there is no view matching the specified
+    criteria in the current view hierarchy.
+  </li>
 
-      <li>
-        <a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html#matches(org.hamcrest.Matcher&lt;? super android.view.View&gt;)">{@code matches}</a>:
-        Asserts that the specified view exists in the current view hierarchy
-        and its state matches some given Hamcrest matcher.
-      </li>
+  <li>
+    <a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html#matches(org.hamcrest.Matcher&lt;? super android.view.View&gt;)">{@code matches}</a>:
+    Asserts that the specified view exists in the current view hierarchy
+    and its state matches some given Hamcrest matcher.
+  </li>
 
-      <li>
-       <a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html#selectedDescendantsMatch(org.hamcrest.Matcher&lt;android.view.View&gt;, org.hamcrest.Matcher&lt;android.view.View&gt;)">{@code selectedDescendentsMatch}</a>
-       : Asserts that the specified children views for a
-        parent view exist, and their state matches some given Hamcrest matcher.
-      </li>
-    </ul>
+  <li>
+    <a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html#selectedDescendantsMatch(org.hamcrest.Matcher&lt;android.view.View&gt;, org.hamcrest.Matcher&lt;android.view.View&gt;)">{@code selectedDescendentsMatch}</a>:
+    Asserts that the specified children views for a
+    parent view exist, and their state matches some given Hamcrest matcher.
+  </li>
+</ul>
 
-    <p>
-      The following code snippet shows how you might check that the text displayed in the UI has
-      the same value as the text previously entered in the
-      {@link android.widget.EditText} field.
-    </p>
+<p>
+  The following code snippet shows how you might
+  check that the text displayed in the UI has
+  the same value as the text previously entered in the
+  {@link android.widget.EditText} field.
+</p>
+
 <pre>
 public void testChangeText_sameActivity() {
     // Type text and then press the button.
@@ -580,14 +804,22 @@
 }
 </pre>
 
-<h2 id="run">Run Espresso Tests on a Device or Emulator</h2>
+<!-- Section 3 -->
+
+<h2 id="run">
+  Run Espresso Tests on a Device or Emulator
+</h2>
+
 <p>
-You can run Espresso tests from <a href="{@docRoot}studio/index.html">Android Studio</a> or
-from the command-line. Make sure to specify
-<a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">
-  {@code AndroidJUnitRunner}</a> as the default instrumentation runner in your project.
+  You can run Espresso tests from
+  <a href="{@docRoot}studio/index.html">Android Studio</a> or
+  from the command-line. Make sure to specify
+  <a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code AndroidJUnitRunner}</a>
+  as the default instrumentation runner in your project.
 </p>
+
 <p>
-To run your Espresso test, follow the steps for running instrumented tests
-described in <a href="{@docRoot}training/testing/start/index.html#run-instrumented-tests">
-Getting Started with Testing</a>.</p>
+  To run your Espresso test, follow the steps for running instrumented tests
+  described in
+  <a href="{@docRoot}training/testing/start/index.html#run-instrumented-tests">Getting Started with Testing</a>.
+</p>
diff --git a/docs/html/training/volley/index.jd b/docs/html/training/volley/index.jd
index a8c4b84..d3645d9 100755
--- a/docs/html/training/volley/index.jd
+++ b/docs/html/training/volley/index.jd
@@ -42,7 +42,7 @@
 <li>Automatic scheduling of network requests.</li>
 <li>Multiple concurrent network connections.</li>
 <li>Transparent disk and memory response caching with standard HTTP
-<a href=http://en.wikipedia.org/wiki/Cache_coherence">cache coherence</a>.</li>
+<a href="http://en.wikipedia.org/wiki/Cache_coherence">cache coherence</a>.</li>
 <li>Support for request prioritization.</li>
 <li>Cancellation request API. You can cancel a single request, or you can set blocks or
 scopes of requests to cancel.</li>
@@ -66,13 +66,22 @@
 <a href="https://android.googlesource.com/platform/frameworks/volley">AOSP</a>
 repository at {@code frameworks/volley} and contains the main request dispatch pipeline
 as well as a set of commonly applicable utilities, available in the Volley "toolbox." The
-easiest way to add Volley to your project is to clone the Volley repository and set it as
-a library project:</p>
+easiest way to add Volley to your project is to add the following dependency to your app's
+build.gradle file:
+
+<pre class="no-pretty-print">
+dependencies {
+    ...
+    compile 'com.android.volley:volley:1.0.0'
+}
+</pre>
+
+You can also clone the Volley repository and set it as a library project:</p>
 
 <ol>
 <li>Git clone the repository by typing the following at the command line:
 
-<pre>
+<pre class="no-pretty-print">
 git clone https://android.googlesource.com/platform/frameworks/volley
 </pre>
 </li>
diff --git a/docs/html/wear/images/partners/mkors.png b/docs/html/wear/images/partners/mkors.png
new file mode 100644
index 0000000..2f1e8ec
--- /dev/null
+++ b/docs/html/wear/images/partners/mkors.png
Binary files differ
diff --git a/docs/html/wear/images/partners/nixon.png b/docs/html/wear/images/partners/nixon.png
new file mode 100644
index 0000000..8674da2
--- /dev/null
+++ b/docs/html/wear/images/partners/nixon.png
Binary files differ
diff --git a/docs/html/wear/images/partners/polar.png b/docs/html/wear/images/partners/polar.png
new file mode 100644
index 0000000..2faeb06
--- /dev/null
+++ b/docs/html/wear/images/partners/polar.png
Binary files differ
diff --git a/docs/html/wear/index.jd b/docs/html/wear/index.jd
index f9bdef5..1eb08be 100644
--- a/docs/html/wear/index.jd
+++ b/docs/html/wear/index.jd
@@ -267,6 +267,9 @@
             <div class="col-4">
               <img src="/wear/images/partners/mips.png" alt="MIPS">
             </div>
+            <div class="col-4">
+              <img src="/wear/images/partners/mkors.png" alt=Michael Kors">
+            </div>
              <div class="col-4">
               <img src="/wear/images/partners/mobvoi.png" alt="Mobvoi">
             </div>
@@ -277,6 +280,12 @@
               <img src="/wear/images/partners/nb.png" alt="New Balance">
             </div>
             <div class="col-4">
+              <img src="/wear/images/partners/nixon.png" alt="Nixon">
+            </div>
+            <div class="col-4">
+              <img src="/wear/images/partners/polar.png" alt="Polar">
+            </div>
+            <div class="col-4">
               <img src="/wear/images/partners/qualcomm.png" alt="Qualcomm">
             </div>
             <div class="col-4">
diff --git a/docs/html/wear/preview/_book.yaml b/docs/html/wear/preview/_book.yaml
index a231fb5..54d5442 100644
--- a/docs/html/wear/preview/_book.yaml
+++ b/docs/html/wear/preview/_book.yaml
@@ -8,18 +8,24 @@
 - title: API Overview
   path: /wear/preview/api-overview.html
   section:
-  - title: Notification Improvements
-    path: /wear/preview/features/notifications.html
-  - title: Input Method Framework
-    path: /wear/preview/features/ime.html
   - title: Complications
     path: /wear/preview/features/complications.html
   - title: Navigation and Actions
     path: /wear/preview/features/ui-nav-actions.html
+  - title: Curved Layout
+    path: /wear/preview/features/wearable-recycler-view.html
+  - title: Notification Improvements
+    path: /wear/preview/features/notifications.html
   - title: Bridging for Notifications
     path: /wear/preview/features/bridger.html
+  - title: Input Method Framework
+    path: /wear/preview/features/ime.html
   - title: Wrist Gestures
     path: /wear/preview/features/gestures.html
+  - title: Standalone apps
+    path: /wear/preview/features/standalone-apps.html
+  - title: App Distribution
+    path: /wear/preview/features/app-distribution.html
 
 - title: Get Started
   path: /wear/preview/start.html
diff --git a/docs/html/wear/preview/api-overview.jd b/docs/html/wear/preview/api-overview.jd
index 0b3ac6b..f4612a2 100644
--- a/docs/html/wear/preview/api-overview.jd
+++ b/docs/html/wear/preview/api-overview.jd
@@ -13,15 +13,16 @@
           <ol>
             <li><a href="#complications">Complications</a></li>
             <li><a href="#drawers">Navigation and Action Drawers</a></li>
+            <li><a href="#wrv">Curved Layout</a></li>
           </ol>
         </li>
 
         <li><a href="#notify">Notifications and Input</a>
           <ol>
-            <li><a href="#expanded">Expanded Notification</a></li>
-            <li><a href="#messaging">Messaging Style Notification</a></li>
+            <li><a href="#expanded">Expanded Notifications</a></li>
+            <li><a href="#messaging">Messaging Style Notifications</a></li>
+            <li><a href="#inline-action">Inline Action</a></li>
             <li><a href="#smart-replies">Smart Reply</a></li>
-            <li><a href="#content-action">Notification Content Action</a>
             <li><a href="#remote-input">Remote Input</a></li>
             <li><a href="#bridging">Bridging Mode</a></li>
             <li><a href="#imf">Input Method Framework</a></li>
@@ -40,308 +41,447 @@
 </div>
 </div>
 
+    <p>
+      Wear 2.0 is still in active development, but you can try it as part of
+      the Wear 2.0 Developer Preview. The sections below highlight some of the
+      new features for developers.
+    </p>
 
+    <h2 id="ui">
+      User Interface Improvements
+    </h2>
 
-<p>
-  The Android Wear Preview API is still in active development, but you can try
-  it now as part of the Wear 2.0 Developer Preview. The sections below
-  highlight some of the new features for Android Wear developers.
-</p>
+    <p>
+      The preview introduces powerful additions to the user interface, opening
+      up exciting possibilities to developers.
+    </p>
 
+    <h3 id="complications">
+      Complications
+    </h3>
 
-<h2 id="ui">User Interface Improvements</h2>
+    <img src="{@docRoot}wear/preview/images/complications-main-image.png"
+    height="320" style="float:right;margin:10px 0 0 40px">
+    <p>
+      A <a href=
+      "https://en.wikipedia.org/wiki/Complication_(horology)">complication</a>
+      is a feature of a watch face that displays more than hours and minutes,
+      such as a battery indicator or a step counter. The Complications API thus
+      helps watch face developers create visual features and the data
+      connections they require.
+    </p>
 
-<p>
-  The preview introduces powerful additions to the user interface, opening up
-  exciting possibilities to developers. A complication
-  is any feature in a watch face that displays more than hours and
-  minutes. With the Complications API, watch faces can display extra information
-  and separate apps can expose complication data. The navigation and action
-  drawers provide users with new ways to interact with apps.
-</p>
+    <p>
+      Watch faces that use this API can display extra information without
+      needing code for getting the underlying data. Data providers can supply
+      data to any watch face using the API.
+    </p>
 
+    <p>
+      For information about this API, see <a href=
+      "{@docRoot}wear/preview/features/complications.html">Watch Face
+      Complications</a>.
+    </p>
 
-<h3 id="complications">Complications</h3>
-<img src="{@docRoot}wear/preview/images/complications-main-image.png"
-  height="320" style="float:right;margin:10px 0 0 40px" />
+    <h3 id="drawers">
+      Navigation and Action Drawers
+    </h3>
 
-<p>
-  A <a href=
-  "https://en.wikipedia.org/wiki/Complication_(horology)">complication</a> is a
-  feature of a watch face that displays more than hours and minutes, such as a
-  battery indicator or a step counter. The Complications API thus helps watch face
-  developers create visual features and the data connections they
-  require.
-</p>
+    <p>
+      Wear 2.0 introduces two new widgets, navigation drawer and action drawer.
+      These widgets give your users new ways to interact with your app. The
+      navigation drawer appears at the top of the screen and allows users to
+      navigate between app views. The action drawer appears at the bottom of
+      the screen and allows users to choose from a list of actions associated
+      with the current usage context. These drawers are accessible to users
+      when they edge swipe from the top or bottom of the screen; they peek when
+      users scroll in an opposite direction.
+    </p>
 
-<p>
-  Watch faces that use this API can display extra information without needing
-  code for getting the underlying data. Data providers can supply data to any
-  watch face using the API.
-</p>
+    <div class="cols">
+      <div class="col-2of6">
+        <img src="{@docRoot}wear/preview/images/nav_drawer.gif" height="240"
+        alt="" style="padding:.5em">
+      </div>
 
-<p>For information about this API,
-see <a href="{@docRoot}wear/preview/features/complications.html">
- Watch Face Complications</a>.
-</p>
+      <div class="col-2of6">
+        <img src="{@docRoot}wear/preview/images/action_drawer.gif" height="240"
+        alt="" style="padding:.5em;">
+      </div>
+    </div>
 
-<h3 id="drawers">Navigation and Action drawers</h3>
+    <p>
+      To learn how to add these widgets to your app, see <a href=
+      "{@docRoot}wear/preview/features/ui-nav-actions.html">Wear Navigation and
+      Actions</a>.
+    </p>
 
-<p>Wear 2.0 introduces two new widgets, navigation drawer and action drawer. These
- widgets give your users new ways to interact with your app. The navigation drawer
-  appears at the top of the screen and allows users to navigate between app views.
-   The  action drawer appears at the bottom of the screen and allows users to choose
-    from a list of actions associated with the current usage context.  These drawers
-     are accessible to users when they edge swipe from the top or bottom of the
-     screen; they peek when users scroll in an opposite direction.
-</p>
+    <h3 id="wrv">
+      Curved Layout
+    </h3>
 
-<div class="cols">
-  <div class="col-2of6">
-    <img src="{@docRoot}wear/preview/images/nav_drawer.gif"
-      height="240" alt="" style="padding:.5em">
-  </div>
-  <div class="col-2of6">
-    <img src="{@docRoot}wear/preview/images/action_drawer.gif"
-      height="240" alt="" style="padding:.5em;">
-  </div>
-</div>
+    <p>
+      Wear 2.0 introduces the <code>WearableRecyclerView</code> class for
+      displaying and manipulating a vertical list of items,
+      optimized for round displays.
+    </p>
 
-<p>
-  To learn how to add these widgets to your app, see
-  <a href="{@docRoot}wear/preview/features/ui-nav-actions.html">
-  Wear Navigation and Actions</a>.
-</p>
+    <p>
+      The key features include the following:
+    </p>
 
+    <ul>
+      <li>A curved layout on round devices
+      </li>
 
-<h2 id="notify">Notifications and Input</h2>
+      <li>A circular scrolling gesture, which can be toggled on and off
+      </li>
+    </ul>
 
-<p>In Wear 2.0, we’ve redesigned the key experiences on the watch to be even more
- intuitive and provide users new ways to respond to messages. Some of the highlights
-  are below; for a complete list of changes, see
-  <a href="{@docRoot}wear/preview/features/notifications.html">Notification Changes in Wear 2.0</a>.
+    <p>
+      To learn how to create a curved layout optimized for round devices, see
+      <a href=
+      "https://developer.android.com/wear/preview/features/wearable-recycler-view.html">
+      Curved Layout</a>.
+    </p>
 
+    <h2 id="notify">
+      Notifications and Input
+    </h2>
 
-<img src="{@docRoot}wear/preview/images/expanded_diagram.png" height="340"
-  style="float:left;margin:10px 20px 0 0" />
-<h3 id="expanded">Expanded notifications</h3>
+    <p>
+      In Wear 2.0, we’ve redesigned the key experiences on the watch to be even
+      more intuitive and provide users new ways to respond to messages. Some of
+      the highlights are below; for a complete list of changes, see <a href=
+      "{@docRoot}wear/preview/features/notifications.html">Notification Changes
+      in Wear 2.0</a>. <img src=
+      "{@docRoot}wear/preview/images/expanded_diagram.png" height="340" style=
+      "float:left;margin:10px 20px 0 0">
+    </p>
 
-<p>
-  When a user taps on a notification that is bridged from the phone to the
-  watch or that lacks a
-  <a href="{@docRoot}reference/android/support/v4/app/NotificationCompat.Builder.html#setContentIntent(android.app.PendingIntent)">
-  {@code contentIntent}</a>, the user will be taken to the expanded view of
-  that notification. When you <a href=
-  "{@docRoot}training/wearables/notifications/pages.html">specify additional
-  content pages</a> and actions for a notification, those are available to the
-  user within the expanded notification. Each expanded notification follows
-  <a href="https://google.com/design/spec-wear">Material Design for Android
-  Wear</a>, so the user gets an app-like experience.
-</p>
+    <h3 id="expanded">
+      Expanded Notifications
+    </h3>
 
+    <p>
+      When a user taps on a notification that is bridged from the phone to the
+      watch or that lacks a <a href=
+      "{@docRoot}reference/android/support/v4/app/NotificationCompat.Builder.html#setContentIntent(android.app.PendingIntent)">
+      {@code contentIntent}</a>, the user will be taken to the expanded view of
+      that notification. When you <a href=
+      "{@docRoot}training/wearables/notifications/pages.html">specify
+      additional content pages</a> and actions for a notification, those are
+      available to the user within the expanded notification. Each expanded
+      notification follows <a href=
+      "https://google.com/design/spec-wear">Material Design for Android
+      Wear</a>, so the user gets an app-like experience.
+    </p>
 
-<h3 id="messaging">Messaging Style notification</h3>
-<p> If you have a chat messaging app, your notifications should use
-{@code Notification.MessagingStyle}, which is new in Android 6.0. Wear 2.0 uses
-the chat messages included in a
-<a href="{@docRoot}preview/features/notification-updates.html#style">{@code MessagingStyle}</a>
- notification
-(see {@code addMessage()}) to provide a rich chat app-like experience in the
-expanded notification.
-</p>
+    <h3 id="messaging">
+      Messaging Style Notifications
+    </h3>
 
+    <p>
+      If you have a chat messaging app, your notifications should use {@code
+      Notification.MessagingStyle}, which is new in Android 6.0. Wear 2.0 uses
+      the chat messages included in a <a href=
+      "{@docRoot}preview/features/notification-updates.html#style">{@code
+      MessagingStyle}</a> notification (see {@code addMessage()}) to provide a
+      rich chat, app-like experience in the expanded notification.
+    </p>
 
-<h3 id="smart-replies">Smart Reply</h3>
+    <h3 id="inline-action">
+      Inline Action
+    </h3>
 
-<p>Android Wear 2.0 introduces support for Smart Reply in
-<a href="{@docRoot}wear/preview/features/notifications.html#messaging">{@code MessagingStyle}</a>
- notifications. Smart Reply provides the user with contextually relevant,
- touchable choices in the expanded notification and in
- <a href="{@docRoot}reference/android/app/RemoteInput.html">{@code RemoteInput}</a>.
-</p>
+    <p>
+      Wear 2.0 enables you to add an inline action within the notification
+      stream so that users can quickly take an action on a notification.
+      Examples of good use cases for an inline action within a notification stream
+      include replying to a text message, stopping a fitness activity, or
+      archiving an email message.
+    </p>
 
-<p>By enabling Smart Reply for your {@code MessagingStyle} notifications, you provide
-users a fast (single tap), discreet (no speaking aloud), and reliable way to respond
- to chat messages they receive.
- </p>
+    <p>
+      To learn how to add an inline action to your notification stream, see
+      <a href=
+      "https://developer.android.com/wear/preview/features/notifications.html#inline">
+      Inline Action</a>.
+    </p>
 
+    <h3 id="smart-replies">
+      Smart Reply
+    </h3>
 
-<img src="{@docRoot}wear/preview/images/remoteinput.png" height="350"
-  style="float:right;margin:10px 0 0 40px" />
+    <p>
+      Android Wear 2.0 introduces support for Smart Reply in <a href=
+      "{@docRoot}wear/preview/features/notifications.html#messaging">{@code
+      MessagingStyle}</a> notifications. Smart Reply provides the user with
+      contextually relevant, touchable choices in the expanded notification and
+      in <a href="{@docRoot}reference/android/app/RemoteInput.html">{@code
+      RemoteInput}</a>.
+    </p>
 
-<h3 id="remote-input">Remote Input</h3>
+    <p>
+      By enabling Smart Reply for your {@code MessagingStyle} notifications,
+      you provide users a fast (single tap), discreet (no speaking aloud), and
+      reliable way to respond to chat messages they receive.
+    </p>
 
-<p>Wear 2.0 users can choose between various input options from
-<a href="{@docRoot}reference/android/app/RemoteInput.html">Remote Input</a>.
- These options include:
-</p>
-<ul>
-<li>Dictation</li>
-<li>Emoji</li>
-<li>Canned responses</li>
-<li>Smart Reply</i>
-<li>Default IME </i>
-</ul>
+    <img src="{@docRoot}wear/preview/images/remoteinput.png" height="350"
+    style="float:right;margin:10px 0 0 40px">
 
-<p>
-For messaging notifications with Smart Reply, the system-generated Smart Reply
- appears within <a href="{@docRoot}reference/android/app/RemoteInput.html">{@code RemoteInput}</a>
-  above the developer-provided list of canned responses.
-  You can also use the
-  <a href="{@docRoot}reference/android/app/RemoteInput.Builder.html#setChoices(java.lang.CharSequence[])">setChoices()</a>
-   method in the {@code RemoteInput} API to enable users to select from a list
-   of canned responses.
-</p>
+    <h3 id="remote-input">
+      Remote Input
+    </h3>
 
-<h3 id="bridging"> Bridging Mode </h3>
-<p>By default, notifications are
-<a href="{@docRoot}training/wearables/notifications/index.html">
-bridged</a> (shared) from an app on a companion phone
-to the watch. Since a phone app and a standalone watch app may be sources of the
- same notifications, the Android Wear 2.0 Preview includes a Bridging mode feature.
-  Developers can begin planning to change the behavior of notifications with the
-  following:
-</p>
+    <p>
+      Wear 2.0 users can choose between various input options from <a href=
+      "{@docRoot}reference/android/app/RemoteInput.html">Remote Input</a>.
+      These options include:
+    </p>
 
-<ul>
-<li>Specifying in the standalone app's Android manifest file that notifications from
- the corresponding phone app should not be bridged to the watch. </li>
-<li>Setting a dismissal ID so notification dismissals (by users) are synced across
-devices.</li>
-</ul>
+    <ul>
+      <li>Dictation
+      </li>
 
-<p>For an example of how to use this feature, see <a href="{@docRoot}wear/preview/features/bridger.html">
-Bridging Mode for Notifications</a>.</p>
+      <li>Emoji
+      </li>
 
-<h3 id="imf">Input Method Framework</h3>
+      <li>Canned responses
+      </li>
 
-<p>Wear 2.0 extends the Android input method framework (IMF) to Android Wear.
-This allows users to enter text on Wear using the system default IME or third party
- IMEs.  The Wear IME lets the user enter text via gesture typing as well as tapping
-  individual keys. The IMF APIs used for Wear devices are the same as other form
-  factors, though usage is slightly different due to limited screen real estate.
-</p>
+      <li>Smart Reply
+      </li>
 
-<p>Wear provides user settings on the watch that let the user:</p>
-<ul>
-<li>Enable multiple IMEs from the list of installed IMEs.</li>
-<li>Set a single default IME from the list of enabled IMEs.</li>
-<li>Change languages for various IMEs.</li>
-</ul>
+      <li>Default IME
+      </li>
+    </ul>
 
-<p>To learn how to create an IME for Wear, see <a href="{@docRoot}wear/preview/features/ime.html">
-Input Method Framework</a>.
-</p>
+    <p>
+      For messaging notifications with Smart Reply, the system-generated Smart
+      Reply appears within <a href=
+      "{@docRoot}reference/android/app/RemoteInput.html">{@code
+      RemoteInput}</a> above the developer-provided list of canned responses.
+      You can also use the <a href=
+      "{@docRoot}reference/android/app/RemoteInput.Builder.html#setChoices(java.lang.CharSequence[])">
+      setChoices()</a> method in the {@code RemoteInput} API to enable users to
+      select from a list of canned responses.
+    </p>
 
-<h3 id="wrist-gestures">Wrist Gestures</h3>
+    <h3 id="bridging">
+      Bridging Mode
+    </h3>
 
-<p>
-  Wrist gestures can enable quick, one-handed interactions with your app
-  when use of a touch screen is inconvenient. The following
-  <a href="https://support.google.com/androidwear/answer/6312406">wrist gestures</a>
-  are available for use by apps:
-</p>
+    <p>
+      By default, notifications are <a href=
+      "{@docRoot}training/wearables/notifications/index.html">bridged</a>
+      (shared) from an app on a companion phone to the watch. Since a phone app
+      and a standalone watch app may be sources of the same notifications, the
+      Android Wear 2.0 Preview includes a Bridging mode feature.
+    </p>
 
-<ul>
-  <li>Flick wrist out</li>
-  <li>Flick wrist in</li>
-</ul>
+    <p>
+      For information about this feature, see <a href=
+      "{@docRoot}wear/preview/features/bridger.html">Bridging Mode for
+      Notifications</a>.
+    </p>
 
-<p>For more information, see
-<a href="{@docRoot}wear/preview/features/gestures.html">
- Wrist Gestures</a>.
-</p>
+    <h3 id="imf">
+      Input Method Framework
+    </h3>
 
-<h2 id="stand-alone">Standalone Devices</h2>
+    <p>
+      Wear 2.0 extends the Android input method framework (IMF) to Android
+      Wear. This allows users to enter text on Wear using the system default
+      IME or third party IMEs. The Wear IME lets the user enter text via
+      gesture typing as well as tapping individual keys. The IMF APIs used for
+      Wear devices are the same as other form factors, though usage is slightly
+      different due to limited screen real estate.
+    </p>
 
-<p>Standalone watches will enable Android Wear apps to work independently of phone
- apps. This means your app can continue to offer full functionality even if the
- paired phone is far away or turned off. </p>
+    <p>
+      Wear provides user settings on the watch that let the user:
+    </p>
 
-<h3 id="wear-apk">Wear-Specific APKs</h3>
+    <ul>
+      <li>Enable multiple IMEs from the list of installed IMEs.
+      </li>
 
-<p>For delivery to a watch, an Android Wear app is currently embedded in its corresponding
-phone app. This delivery method can result in an increased download size for users,
- regardless of whether they have an Android Wear device.
-</p>
+      <li>Set a single default IME from the list of enabled IMEs.
+      </li>
 
-<p>With standalone devices, the
-<a href ="{@docRoot}google/play/publishing/multiple-apks.html">Multi-APK</a>
- delivery method will be used. Developers will have the ability to release Android
-  Wear apps independently of the corresponding phone apps. Please stay tuned for
-   more information about this change.
-</p>
+      <li>Change languages for various IMEs.
+      </li>
+    </ul>
 
-<h3 id="network">Network Access</h3>
+    <p>
+      To learn how to create an IME for Wear, see <a href=
+      "{@docRoot}wear/preview/features/ime.html">Input Method Framework</a>.
+    </p>
 
-<p>Since Android Wear apps will work independently of phone apps, Android Wear's
- network access will no longer require the
- <a href="{@docRoot}training/wearables/data-layer/index.html">
- Wearable Data Layer API</a>. Android Wear apps will have the ability to make
- their own network requests. Additionally, they will be able to directly use
- Google Cloud Messaging.
-</p>
+    <h3 id="wrist-gestures">
+      Wrist Gestures
+    </h3>
 
-<p>No APIs for network access or GCM are specific to Android Wear; refer to the
-existing documentation about
-<a href="{@docRoot}training/basics/network-ops/connecting.html">
-Connecting to the Network</a> and
-<a href="https://developers.google.com/cloud-messaging/">Cloud Messaging</a>.
-</p>
+    <p>
+      Wrist gestures can enable quick, one-handed interactions with your app
+      when use of a touch screen is inconvenient. The following <a href=
+      "https://support.google.com/androidwear/answer/6312406">wrist
+      gestures</a> are available for use by apps:
+    </p>
 
-<p>We recommend using the following libraries:</p>
-<ul>
-<li><a href="{@docRoot}reference/android/app/job/JobScheduler.html">
-JobScheduler</a> for asynchronous jobs, including polling at regular intervals
-</li>
-<li>Multi-networking APIs if you need to connect to specific network types; see
-the <a href="{@docRoot}about/versions/android-5.0.html#Wireless">
-Multiple Network Connections</a>
-</li>
-</ul>
+    <ul>
+      <li>Flick wrist out
+      </li>
 
-<p>You will still be able to use the
-<a href="{@docRoot}training/wearables/data-layer/index.html">
- Wearable Data Layer API</a> to communicate with a phone app.
- However, use of this API to connect to a network will be discouraged.
- </p>
+      <li>Flick wrist in
+      </li>
+    </ul>
 
+    <p>
+      For more information, see <a href=
+      "{@docRoot}wear/preview/features/gestures.html">Wrist Gestures</a>.
+    </p>
 
-<h3 id="auth">Authentication</h3>
+    <h2 id="stand-alone">
+      Standalone Devices
+    </h2>
 
-<p>Since Android Wear apps will work independently of phone apps, Android Wear's
- authentication capabilities will be more powerful; apps will have new ways to
- authenticate.</p>
+    <p>
+      Standalone watches enable Android Wear apps to work independently of
+      phone apps. This means your app can continue to offer full functionality
+      even if the paired phone is far away or turned off.
+    </p>
 
-<h4>Users can enter a username and password on a watch</h4>
+    <h3 id="wear-apk">
+      Wear-Specific APKs
+    </h3>
 
-<p>Google Keyboard will be standard on Android Wear, allowing for direct text
-entry. This feature will work as expected with standard
-<a href="{@docRoot}reference/android/widget/EditText.html">EditText widgets</a>.
-For passwords, the {@code textPassword} attribute will be used.</p>
+    <p>
+      For delivery to a watch, an Android Wear app is currently embedded in its
+      corresponding phone app. This delivery method can result in an increased
+      download size for users, regardless of whether they have an Android Wear
+      device.
+    </p>
 
-<h4>Utilizing Account Manager</h4>
+    <p>
+      For information about planning and building your standalone app
+      for Wear 2.0, see <a href=
+      "https://developer.android.com/wear/preview/features/standalone-apps.html">
+      Standalone Apps</a>.
+    </p>
 
-<p>Android Wear will include the
-<a href="{@docRoot}reference/android/accounts/AccountManager.html">
-AccountManager</a>, which will be accessible for syncing and storing account
-data, as it is on an Android phone.</p>
+    <p>
+      For information about distributing your app, see <a href=
+      "https://developer.android.com/wear/preview/features/app-distribution.html">
+      App Distribution</a>.
+    </p>
 
-<h4>Authentication tokens can be passed over the Wearable Data Layer</h4>
+    <h3 id="network">
+      Network Access
+    </h3>
 
-<p>For Android-paired watches (only), a phone securely
-transfers authentication credentials to a watch app via the
-<a href="{@docRoot}training/wearables/data-layer/index.html">
-Wearable Data Layer API</a>. The credentials can be transferred as
-messages or data items.</p>
+    <p>
+      Since Android Wear apps will work independently of phone apps, Android
+      Wear's network access will no longer require the <a href=
+      "{@docRoot}training/wearables/data-layer/index.html">Wearable Data Layer
+      API</a>. Android Wear apps will have the ability to make their own
+      network requests. Additionally, they will be able to directly use Google
+      Cloud Messaging. For more information, see
+      <a href=
+      "https://developer.android.com/wear/preview/features/standalone-apps.html#network_access">
+      Network Access and Cloud Messaging</a>.
+    </p>
 
-<p>If your watch app needs to determine if your phone app is installed, you can
-advertise a capability on the phone app and retrieve the capability on the
-watch. For more information, see the following sections of
-<a href="{@docRoot}training/wearables/data-layer/messages.html">
-Sending and Receiving Messages</a>:</p>
+    <p>
+      No APIs for network access or GCM are specific to Android Wear; refer to
+      the existing documentation about <a href=
+      "{@docRoot}training/basics/network-ops/connecting.html">Connecting to the
+      Network</a> and <a href=
+      "https://developers.google.com/cloud-messaging/">Cloud Messaging</a>.
+    </p>
 
-<ul>
-  <li>Advertise Capabilities</li>
-  <li>Retrieve the Nodes with the Required Capabilities</li>
-</ul>
+    <p>
+      We recommend using the following libraries:
+    </p>
+
+    <ul>
+      <li>
+        <a href=
+        "{@docRoot}reference/android/app/job/JobScheduler.html">JobScheduler</a>
+        for asynchronous jobs, including polling at regular intervals
+      </li>
+
+      <li>Multi-networking APIs, to connect to specific network
+      types; see <a href=
+      "{@docRoot}about/versions/android-5.0.html#Wireless">Multiple Network
+      Connections</a>
+      </li>
+    </ul>
+
+    <p>
+      The <a href=
+      "{@docRoot}training/wearables/data-layer/index.html">Wearable Data Layer
+      API</a> is available to communicate with a phone app.
+      However, use of this API to connect to a network will be discouraged.
+    </p>
+
+    <h3 id="auth">
+      Authentication
+    </h3>
+
+    <p>
+      Since Android Wear apps will work independently of phone apps, Android
+      Wear's authentication capabilities will be more powerful; apps will have
+      new ways to authenticate.
+    </p>
+
+    <h4>
+      Users can enter a username and password on a watch
+    </h4>
+
+    <p>
+      Google Keyboard will be standard on Android Wear, allowing for direct
+      text entry. This feature will work as expected with standard <a href=
+      "{@docRoot}reference/android/widget/EditText.html">EditText widgets</a>.
+      For passwords, the {@code textPassword} attribute will be used.
+    </p>
+
+    <h4>
+      Utilizing Account Manager
+    </h4>
+
+    <p>
+      Android Wear will include the <a href=
+      "{@docRoot}reference/android/accounts/AccountManager.html">AccountManager</a>,
+      which will be accessible for syncing and storing account data, as it is
+      on an Android phone.
+    </p>
+
+    <h4>
+      Authentication tokens can be passed over the Wearable Data Layer
+    </h4>
+
+    <p>
+      For Android-paired watches (only), a phone securely transfers
+      authentication credentials to a watch app via the <a href=
+      "{@docRoot}training/wearables/data-layer/index.html">Wearable Data Layer
+      API</a>. The credentials can be transferred as messages or data items.
+    </p>
+
+    <p>
+      If your watch app needs to determine if your phone app is installed, you
+      can advertise a capability on the phone app and retrieve the capability
+      on the watch. For more information, see the following sections of
+      <a href="{@docRoot}training/wearables/data-layer/messages.html">Sending
+      and Receiving Messages</a>:
+    </p>
+
+    <ul>
+      <li>Advertise Capabilities
+      </li>
+
+      <li>Retrieve the Nodes with the Required Capabilities
+      </li>
+    </ul>
diff --git a/docs/html/wear/preview/behavior-changes.jd b/docs/html/wear/preview/behavior-changes.jd
index 0214622..c93d337 100644
--- a/docs/html/wear/preview/behavior-changes.jd
+++ b/docs/html/wear/preview/behavior-changes.jd
@@ -22,6 +22,8 @@
 
 <ul>
   <li><a href="#activity-dismissal">Activity Dismissal</a></li>
+  <li><a href="#invalid-fields">Invalid Fields for a Complication Type</a></li>
+  <li><a href="#empty">Complication Types for Empty Data</a></li>
 </ul>
 
 </div>
@@ -61,3 +63,44 @@
   <a href="{@docRoot}wear/preview/features/ui-nav-actions.html">navigation
   drawers</a>.
 </p>
+
+<h2 id="invalid-fields">Invalid Fields for a Complication Type</h2>
+
+<p>
+  When a watch face uses the <a href="{@docRoot}wear/preview/features/complications.html">
+  Complications API</a>, the watch face requests data from a chosen provider.
+  A <code>ComplicationData</code> object, which contains
+  complication types, is returned.
+</p>
+
+<p>
+  A complication type determines the
+  kinds of data that a watch face can render. This section describes
+  a behavior change related to the <code>ComplicationData</code> object.
+</p>
+
+<p>
+  Starting with
+  <a href="https://developer.android.com/wear/preview/support.html#dp3">
+  Developer Preview 3</a>, when a watch face requests a field that is invalid
+  for a complication type, a default value for the field is returned.
+  For example, if a watch face tries to access a <code>Long text</code>
+  field in a <code>SHORT_TEXT</code> type, the default value for the
+  <code>Long text</code> field is returned.
+  In previous releases, such a request for an invalid field
+  (for a type) resulted in an exception.
+</p>
+
+<h2 id="empty">Complication Types for Empty Data</h2>
+
+<p>
+  Starting with
+  <a href="https://developer.android.com/wear/preview/support.html#dp3">
+  Developer Preview 3</a>, the complication types used for "empty" data are
+  changed. Apps that use the Complications API
+  may need to be updated to use
+  <code>TYPE_NO_DATA</code>. See the information
+  about <code>TYPE_NO_DATA</code> in the
+  <a href="{@docRoot}wear/preview/features/complications.html#types_and_fields">
+  Types and fields</a> section.
+</p>
diff --git a/docs/html/wear/preview/downloads.jd b/docs/html/wear/preview/downloads.jd
index 4bc401b..83a3f98 100644
--- a/docs/html/wear/preview/downloads.jd
+++ b/docs/html/wear/preview/downloads.jd
@@ -171,7 +171,9 @@
           <li>
             <a href="#set_up_a_watch">Set Up a Watch</a>
           </li>
-
+          <li>
+            <a href="#set_up_a_phone">Set Up a Phone</a>
+          </li>
           <li>
             <a href="#set_up_an_emulator">Set Up an Emulator</a>
           </li>
@@ -180,7 +182,7 @@
     </div>
 
     <p>
-      You can run and test your app with the Android Wear 2.0 Developer Preview
+      You can run and test your app with the Android Wear 2.0 Preview
       in either of these ways:
     </p>
 
@@ -237,6 +239,13 @@
       following tables and flash it to the corresponding device.
     </p>
 
+    <p class="caution"><strong>Caution:</strong>
+      After you flash an image to a watch, follow the steps for
+      <a href="#set_up_a_phone">setting up a phone</a> with the beta version of
+      the Android Wear companion app. To use a Wear 2.0 image on a watch,
+      you must have the beta companion app on a paired phone.
+    </p>
+
     <p>
       To restore your device to its original state during the preview,
       you can flash the appropriate retail system image, below, to the device.
@@ -266,9 +275,9 @@
         <td>
           Preview image for testing
         </td>
-        <td><a href="#top" onclick="onDownload(this)">nemo-nvd83h-factory-48ac950c.tgz</a><br>
-          MD5: dd351884cce9fb5bf1bdec0a8e5f56e3<br>
-          SHA-1: 48ac950c48faef96a7770e3c1acb56d23a28d859
+        <td><a href="#top" onclick="onDownload(this)">nemo-nve68j-factory-302a33ea.tgz</a><br>
+          MD5: ddfccc3e050c7e2db8d657c82f7d6291<br>
+          SHA-1: 302a33eac348c401fcb165bad4b9aaa40c7beb2b
         </td>
       </tr>
 
@@ -276,9 +285,9 @@
         <td>
           Non-preview image (for after testing)
         </td>
-        <td><a href="#top" onclick="onDownload(this)">nemo-mnc40x-factory-fa528bec.tgz</a><br>
-          MD5: 0b8ba3653d5a93cb854f4d7409d7b6c9<br>
-          SHA-1: fa528bec8aba3bf6c7d901ba63cd6ea0a08dbeb0
+        <td><a href="#top" onclick="onDownload(this)">nemo-mfd18l-factory-3faf6f2d.tgz</a><br>
+          MD5: f3a0090c0e99da82ad095b5d2a9acc6d<br>
+          SHA-1: 3faf6f2d7f422a17a5f6c54cf5e1d2c5622689b0
         </td>
       </tr>
 
@@ -307,18 +316,18 @@
         <td>
           Preview image for testing
         </td>
-        <td><a href="#top" onclick="onDownload(this)">sturgeon-nvd83h-factory-cb5a11ab.tgz</a><br>
-          MD5: 38c1047992b1d28f6833d9f6c8470cdc<br>
-          SHA-1: cb5a11ab0260ea3ca7da5894e73e41f70357da6b
+        <td><a href="#top" onclick="onDownload(this)">sturgeon-nve68j-factory-6607cd31.tgz</a><br>
+          MD5: f78ac6ba8bb84038d163cc2d7ca85040<br>
+          SHA-1: 6607cd31858af1bfd50b905c68f7cf1f0b6e570e
         </td>
       </tr>
       <tr id="sturgeon-non-preview">
         <td>
           Non-preview image (for after testing)
         </td>
-        <td><a href="#top" onclick="onDownload(this)">sturgeon-mec23l-factory-48003078.tgz</a><br>
-          MD5: 417b5cbddb29a2262bce133e283d2732<br>
-          SHA-1: 4800307843580f818557dd7c43d8ba2161e289b2
+        <td><a href="#top" onclick="onDownload(this)">sturgeon-m6e69f-factory-e659286a.tgz</a><br>
+          MD5: 12ce6cb0b0e43b67ea46a886eae052ae<br>
+          SHA-1: e659286aa9004f4555a476ede4e8b690f56cfefd
         </td>
       </tr>
     </table>
@@ -437,13 +446,14 @@
 
 
     <h4 id="set_up_watch">
-      Set up the watch and begin testing
+      Set up the watch
     </h4>
 
       <p>
         After the <code>flash-all</code> script finishes, your watch reboots.
-        Pair the watch with a phone or tablet. The preview now is available
-        for testing on the watch. Before installing an app, perform the
+        Only pair the watch with a phone (so you can begin testing the preview)
+        by using the instructions in <a href="#set_up_a_phone">Set Up a Phone</a>.
+        Additionally, before installing an app, perform the
         following steps on the watch to re-secure the watch's bootloader:
     </p>
 
@@ -483,7 +493,9 @@
     </ol>
 
     <p>
-      Your watch is ready for you to <a href=
+      After you follow the instructions in
+      <a href="#set_up_a_phone">Set Up a Phone</a>,
+      your watch will be ready for you to <a href=
       "{@docRoot}training/wearables/apps/creating.html#Install">install and run
       your app</a>:
     </p>
@@ -539,13 +551,109 @@
       device reset and removes all user data on the device.
     </p>
 
+    <h2 id="set_up_a_phone">
+      Set Up a Phone
+    </h2>
+
+    <p>
+      On a phone, follow the instructions in this section to install the beta
+      version of the Android Wear companion app. The beta version cannot be run
+      on a phone at the same time as the non-beta version. Additionally, the
+      beta version is English-only.
+    </p>
+
+    <p>
+      <p class="caution"><strong>Caution:</strong> If you have an existing
+      pairing of the phone to a Wear 1.x
+      watch, installation of the beta companion app will cause a loss of that
+      pairing.
+    </p>
+
+    <h3 id="join-the-wear-2-0-preview-group">
+      Join the Wear 2.0 preview group
+    </h3>
+
+    <p>
+      To access the beta companion app, you must <a href=
+      "https://groups.google.com/forum/#!forum/android-wear-developer-preview">join
+      the preview group in Google Groups</a>.
+    </p>
+
+    <h3>
+      Opt in for beta testing
+    </h3>
+
+    <p>
+      On the <a href=
+      "https://play.google.com/apps/testing/com.google.android.wearable.app">Testing
+      Opt-in</a> page, select <strong>Become a Tester</strong>.
+    </p>
+
+    <h3 id="download-and-install-the-beta-version-of-the-companion-app">
+      Download and install the beta version of the companion app
+    </h3>
+
+    <p>
+      On the Play Store on your phone, go to the <a href=
+      "https://play.google.com/store/apps/details?id=com.google.android.wearable.app">
+      Android Wear app listing</a>. Tap <strong>Update</strong> to download and
+      install the beta version of the app. After installation, confirm that
+      <strong>Auto-update</strong> is selected for the app (see
+      the "Set up automatic updates for specific apps" section of <a href=
+      "https://support.google.com/googleplay/answer/113412">Update downloaded
+      apps</a>). Tap <strong>Open</strong> to start the app.
+    </p>
+
+    <h3 id="pairing">
+      Pair the phone to the watch
+    </h3>
+
+    <p>
+      After you install the beta version of the companion app on a phone,
+      you can pair the phone to the watch:
+    </p>
+
+    <ol>
+      <li>On the phone, select your device name from the list of devices.
+      A pairing code is displayed on the phone and on the watch.
+      Ensure that the codes match.
+      </li>
+
+      <li>Tap <strong>Pair</strong> to
+      continue the pairing process. When the watch is connected to
+      the phone, a confirmation message is displayed.
+      On the phone, a screen is displayed that lists
+      the accounts on the phone.
+      </li>
+
+      <li>Choose a Google Account to add and sync to your watch.
+      </li>
+
+      <li>Confirm the screen lock and enter the password to start the copying of
+      the account from the phone to the watch.
+      </li>
+
+      <li>Follow the instructions in the wizard to finish the
+      pairing process.
+      </li>
+    </ol>
+
+    <p>
+      You can begin testing your app with the preview.
+    </p>
+
     <h2 id="set_up_an_emulator">
       Set Up an Emulator
     </h2>
 
     <p>
-      To test with the Android Emulator, create a virtual device in Android
-      Studio as follows:
+      To test with the Android Emulator,
+      confirm that you have the latest version of the <strong>Android SDK
+      Platform-tools</strong> from the <a href=
+      "{@docRoot}studio/intro/update.html#sdk-manager">SDK Manager</a>.
+    </p>
+
+    <p>Create a new virtual device in Android Studio as follows:
     </p>
 
     <ol>
@@ -556,19 +664,19 @@
       <li>Click <strong>Create Virtual Device</strong>.
       </li>
 
-      <li>In the <strong>Category</strong> pane, select Wear and
-       choose a hardware profile.
+      <li>In the <strong>Category</strong> pane, select <strong>Wear</strong>
+       and choose a hardware profile.
        The Android Wear 2.0 Developer Preview
        is only optimized for round devices currently, so we recommend not
        using the square or chin profiles for now.
        Click <strong>Next</strong>.
       </li>
 
-      <li>Select an <strong>N</strong> image to download. The images may be on
+      <li>Select a <strong>Nougat</strong> image to download. The images may be on
       the <strong>x86</strong> tab instead of the <strong>Recommended</strong>
       tab, until installed. For example, select the image with the
-      <strong>Release Name</strong> of N, the <strong>API Level</strong> of N,
-      and the <strong>Target</strong> of "Android 6.X (with Android Wear)".
+      <strong>Release Name</strong> of Nougat, the <strong>API Level</strong> of 24,
+      and the <strong>Target</strong> of "Android 7.0 (with Android Wear)".
       When the download and installation are complete, click
       <strong>Finish</strong> and then click <strong>Next</strong>.
       </li>
@@ -576,16 +684,66 @@
       <li>Verify the configuration of the Android Virtual Device (AVD) and
       click <strong>Finish</strong>.
       </li>
+
+      <li>Start the emulator by selecting the new virtual device, clicking the
+      <strong>Play</strong> button, and waiting until
+      the emulator initializes and shows the Android Wear home screen.
+      </li>
     </ol>
 
     <p>
-      You can now test an application with a virtual preview device
+      Pair the phone with the emulator, and sync a Google Account, as follows:
+    </p>
+
+    <ol>
+      <li>On the phone, install the Android Wear app from Google Play.
+      </li>
+
+      <li>On the phone, enable Developer Options and USB Debugging.
+      </li>
+
+      <li>Connect the phone to your computer through USB.
+      </li>
+
+      <li>Forward the AVD's communication port to the connected handheld device
+      (each time the phone is connected):<br>
+      <code>adb -d forward tcp:5601 tcp:5601</code>
+      </li>
+
+      <li>On the phone, in the Android Wear app, begin the standard pairing
+      process. For example, on the Welcome screen, tap the
+      <strong>Set It Up</strong> button.
+      Alternatively, if an existing watch already is paired, in the upper-left
+      drop-down, tap <strong>Add a New Watch</strong>.
+      </li>
+
+      <li>On the phone, in the Android Wear app, tap the
+      Overflow button, and then tap
+      <strong>Pair with Emulator</strong>.
+      </li>
+
+      <li>Tap the Settings icon.
+      </li>
+
+      <li>Under Device Settings, tap <strong>Emulator</strong>.
+      </li>
+
+      <li>Tap <strong>Accounts</strong> and select a Google Account,
+      and follow the steps in the wizard to
+      sync the account with the emulator. If necessary, type the screen-lock
+      device password, and Google Account password, to start the account sync.
+      </li>
+    </ol>
+
+    <p>
+      You can now test an app with a virtual preview device
       in the <a href=
       "{@docRoot}tools/devices/emulator.html">Android Emulator</a>. For more
       information about using virtual devices, see <a href=
-      "{@docRoot}tools/devices/managing-avds.html">Managing AVDs with the AVD
-      Manager</a>.
+      "{@docRoot}tools/devices/managing-avds.html">
+      Create and Manage Virtual Devices</a>.
     </p>
+
  </div><!-- landing -->
 
 </div><!-- relative wrapper -->
diff --git a/docs/html/wear/preview/features/app-distribution.jd b/docs/html/wear/preview/features/app-distribution.jd
new file mode 100644
index 0000000..319efa6
--- /dev/null
+++ b/docs/html/wear/preview/features/app-distribution.jd
@@ -0,0 +1,325 @@
+page.title=App Distribution
+meta.keywords="wear-preview"
+page.tags="wear-preview"
+page.image=images/cards/card-n-sdk_2x.png
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+
+  <ul>
+    <li><a href="#publish">Publish Your APKs</a></li>
+    <li><a href="#targeting">Setting Up Targeting for a Watch</a></li>
+    <li><a href="#console">Using the Play Developer Console</a></li>
+  </ul>
+
+</div>
+</div>
+
+    <p>
+      With Android Wear 2.0, a user can visit the Play Store on a watch and
+      download a Wear app directly to the watch.
+    </p>
+
+    <p>
+      Generally, a Wear 2.0 app in the Play Store needs
+      a minimum and target API level of 24 or higher in
+      the Android manifest file. The minimum SDK level can be 23
+      only if you are using the same APK
+      for Wear 1.0 and 2.0 (and thus have an embedded Wear 1.0 APK).
+    </p>
+
+    <h2 id="publish">
+      Publish Your APKs
+    </h2>
+
+    <p>
+      To make your app appear in the on-watch Play Store, upload
+      the watch APK in the Play Developer Console just as you would any other
+      APK. If you only have a watch APK and no phone APK, no other steps
+      are required.
+    </p>
+
+    <p>
+      If you have a phone APK in addition to a watch APK, you must use the
+      <a href="https://developer.android.com/google/play/publishing/multiple-apks.html">Multi-APK delivery method</a>.
+    </p>
+
+    <p>
+      <a href=
+      "https://developer.android.com/training/permissions/requesting.html">Run-time
+      permissions</a> are required.
+    </p>
+
+    <p>
+      Also see
+      <a href="{@docRoot}wear/preview/features/standalone-apps.html">
+      Standalone Apps</a>.
+    </p>
+
+    <h3>
+      Distribution to Wear 2.0 watches
+    </h3>
+
+    <p>
+      If you only want your app to be distributed to Wear 2.0 watches,
+      it is unnecessary to embed the watch APK inside the the phone APK.
+    </p>
+
+    <p>
+      If you want your app to
+      be distributed to Wear 1.0 watches, you need to embed the
+      watch APK inside the phone APK, as described directly below.
+    </p>
+
+    <h3>
+      Distribution to Wear 1.0 and 2.0 watches
+    </h3>
+
+    <p>
+      If you are already distributing your app to Wear 1.0 watches,
+      follow these steps:
+    </p>
+
+    <ol>
+      <li>Provide a Wear 2.0 (standalone) version of your watch APK that can be made
+      available in the Play Store on Wear.
+      </li>
+
+      <li>Continue embedding a Wear 1.0 APK in your phone APK,
+      for use by watches that do not have Wear 2.0.
+      </li>
+    </ol>
+
+    <h3>
+      Specifying a version code
+    </h3>
+
+    <p>
+      To ensure that a standalone APK acts as an upgrade to an embedded Wear APK, the
+      standalone Wear APK's <a href=
+      "https://developer.android.com/google/play/publishing/multiple-apks.html#VersionCodes">
+      version code</a> generally should be higher than the embedded Wear APK's version code.
+      (A phone APK's version code scheme can be independent from that of a watch
+      APK, although they must be unique.) However, the version codes
+      of the standalone APK and the embedded Wear APK can be the same if
+      the APKs are equivalent. If the APKs are not equivalent,
+      but the version code is the same, then when a watch updates from Wear 1.0
+      to 2.0, the watch may get the new APK only after waiting for a
+      longer-than-expected period of time.
+    </p>
+
+    <p>
+      Note that it currently is not possible to create a single APK that works
+      on a phone and watch.
+    </p>
+
+    <h3>
+      Support in the Gradle file
+    </h3>
+
+    <p>
+      If you have a Wear app that is intended for both Wear 1.0 and Wear 2.0,
+      consider using <a href=
+      "https://developer.android.com/studio/build/build-variants.html#product-flavors">
+      product flavors</a>. For example,
+      if you want to target both SDK version 23 and version 24,
+      update your Wear module's <code>build.gradle</code> file to include
+      the following if an existing embedded app has a minimum SDK version of 23:
+    </p>
+
+<pre>
+android {
+    ...
+    defaultConfig
+    {
+       // This is the minSdkVersion of the Wear 1.0 embedded app
+       minSdkVersion 23
+       ...
+    }
+    buildTypes {...}
+    productFlavors {
+        wear1 {
+          // Use the defaultConfig value
+        }
+        wear2 {
+            minSdkVersion 24
+        }
+    }
+</pre>
+
+    <p>
+      Then update your phone module’s <code>build.gradle</code> file, replacing
+      <code>wearApp</code> as follows:
+    </p>
+
+<pre>
+dependencies {
+    ...
+    wearApp project(path: ':wearable', configuration: 'wear1Release')
+}
+</pre>
+
+    <p>
+      A <a href=
+      "https://developer.android.com/studio/build/build-variants.html#product-flavors">
+      build variant</a> is a combination of the product flavor and build type.
+      In Android Studio, select the appropriate build variant when
+      debugging or publishing your app. For example, if <code>wear2</code> is a
+      product flavor, select <strong>wear2Release</strong> as the
+      release build variant.
+    </p>
+
+    <p>
+      For purposes of code that is Wear 2.0-specific or Wear 1.0-specific,
+      consider <a href=
+      "https://developer.android.com/studio/build/build-variants.html#sourcesets">
+      source sets for build variants</a>.
+    </p>
+
+
+    <h2 id="targeting">
+      Setting Up Targeting for a Watch
+    </h2>
+
+    <p>
+      In your Android Manifest file, you must specify the following feature
+      restriction: the <code>uses-feature</code> element is set to
+      <code>android.hardware.type.watch</code>. Do not set
+      the <code>required</code> attribute to <code>false</code>.
+      A single APK for Wear and non-Wear devices presently is not supported.
+    </p>
+
+    <p>
+      Thus, if an APK has the following setting, Google Play provides the APK
+      to watches only:
+    </p>
+
+<pre>
+&lt;manifest package=&quot;com.example.standalone&quot;
+    xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
+    &lt;uses-feature
+        android:name=&quot;android.hardware.type.watch&quot;
+    ...
+&lt;/manifest&gt;
+</pre>
+
+    <p>
+      The <code>android.hardware.type.watch</code> setting above can be
+      combined with other criteria such as SDK version, screen resolution, and
+      CPU architecture. Thus, different Wear APKs can target different hardware
+      configurations.
+    </p>
+
+    <h2 id="console">
+      Using the Play Developer Console
+    </h2>
+
+    <p>
+      Below is an introduction to <a href=
+      "https://support.google.com/googleplay/android-developer/answer/113469">uploading</a>
+      a standalone Wear APK to an application listing using the Play Developer
+      Console.
+    </p>
+
+    <p>
+      If your app supports both Wear 1.0 and Wear 2.0, continue embedding the
+      Wear 1.0 APK (minimum SDK version of 20, 21, or 22, or 23) in the phone
+      APK and upload the phone APK. In addition, upload your standalone Wear
+      2.0 APK (which has a minimum SDK version of 24).
+    </p>
+
+    <p>
+      Also see <a href=
+      "https://developer.android.com/google/play/publishing/multiple-apks.html">
+      Multiple APK Support</a> and <a href=
+      "https://developer.android.com/distribute/googleplay/developer-console.html#manage">
+      Manage Your App</a>.
+      Before uploading an APK as described below, the APK
+      must be <a href=
+      "https://developer.android.com/studio/publish/app-signing.html#release-mode">
+      signed</a>.
+    </p>
+
+     <h3  id="uploading-apk">
+      Uploading your APK
+    </h3>
+
+    <p>
+      Go to the <a href="https://play.google.com/apps/publish">Play Developer
+      Console</a>, navigate to your application listing, and select
+      <strong>APK</strong> in the left-navigation panel. An APK screen similar to
+      the following is displayed:
+    </p>
+    <img src="../images/apk-tabs.png" width="" alt="alt_text">
+
+    <p>
+      You may need to use advanced mode for uploads, as follows:
+    </p>
+
+    <ul>
+      <li>Advanced mode is unnecessary if you only have a Wear 2.0 app and no
+      phone app. Instead of advanced mode, use simple mode.</li>
+
+      <li>Use advanced mode if you support Wear 1.0 or have a phone app.</li>
+    </ul>
+
+    <p>
+      Therefore, on the above APK screen, to determine whether to click
+      the <strong>Switch to advanced mode</strong>
+      button, consider the following:
+    </p>
+
+    <ul>
+      <li>If your app does not support Wear 1.0, and only has a watch APK,
+      upload it using simple mode.
+      </li>
+
+      <li>If your app does not support Wear 1.0 and has both a watch APK and a
+      phone APK, click <strong>Switch to advanced mode</strong>
+      to upload the watch and phone APKs.
+      </li>
+    </ul>
+
+    <p>
+      See <a href=
+      "https://developer.android.com/google/play/publishing/multiple-apks.html#SimpleAndAdvanced">
+      Simple mode and advanced mode</a> for more information about toggling
+      between modes.
+    </p>
+
+    <p>
+      Select the appropriate tab (<strong>Production</strong>, <strong>Beta
+      Testing</strong>, or <strong>Alpha Testing</strong>) for your upload.
+      Then click
+      the <strong>Upload New APK</strong> button and select your standalone
+      Wear APK for upload.
+    </p>
+
+    <h3>
+      Reviewing and publishing
+    </h3>
+
+    <p>
+      After you upload your standalone Wear APK and scroll down the resulting
+      page, the APK is shown in the <strong>Current APK</strong> table, with a
+      version number, in a similar way to the following:
+    </p>
+    <img src="../images/current-apk.png" width="" alt="alt_text">
+
+    <p>
+      Finally, in the <strong>Current APK</strong> table above, click the line
+      with the <strong>Version</strong> to review the APK. The <strong>APK
+      Details</strong> panel is displayed. You can verify, for example, that
+      the number in the <strong>Supported Android Devices</strong> line is far
+      fewer than the number would be for a typical phone APK:
+    </p>
+    <img src="../images/apk-details.png" width="" alt="alt_text">
+
+    <p>
+      When you are ready, <a href=
+      "https://support.google.com/googleplay/android-developer/answer/6334282">publish</a>
+      your app.
+    </p>
diff --git a/docs/html/wear/preview/features/bridger.jd b/docs/html/wear/preview/features/bridger.jd
index b7be093..2d879ca 100644
--- a/docs/html/wear/preview/features/bridger.jd
+++ b/docs/html/wear/preview/features/bridger.jd
@@ -6,19 +6,26 @@
 
     <div id="qv-wrapper">
       <div id="qv">
-        <ol>
+        <ul>
           <li>
             <a href=
-            "#preventing_bridging_with_the_bridging_mode_feature">Preventing
-            Bridging with the Bridging Mode Feature</a>
+            "#using-an-entry-in-the-manifest-file">Specifying a Bridging Configuration in the Manifest File</a>
           </li>
 
           <li>
             <a href=
-            "#using_a_dismissal_id_to_sync_notification_dismissals">Using a
-            Dismissal ID to Sync Notification Dismissals</a>
+            "#specifying-a-bridging-configuration-at-runtime">Specifying a Bridging Configuration at Runtime</a>
           </li>
-        </ol>
+          <li>
+            <a href=
+            "#existing-method-of-preventing-bridging">Existing Method of Preventing Bridging</a>
+          </li>
+
+          <li>
+            <a href=
+            "#using_a_dismissal_id_to_sync_notification_dismissals">Using a Dismissal ID to Sync Notification Dismissals</a>
+          </li>
+        </ul>
       </div>
     </div>
 
@@ -27,19 +34,20 @@
       "{@docRoot}training/wearables/notifications/index.html">are bridged
       (shared)</a> from an app on a companion phone to the watch. If you build
       a standalone watch app and have a companion phone app, they may duplicate
-      notifications. The Android Wear 2.0 Preview includes a Bridging mode
-      feature to handle this problem of repeated notifications.
+      notifications. The Android Wear 2.0 Preview includes
+      features to handle this problem of repeated notifications.
     </p>
 
     <p>
-      With the Android Wear 2.0 Preview, developers can change the
-      behavior of notifications with the following:
+      With the Android Wear 2.0 Preview, developers can change the behavior of
+      notifications with one or more of the following:
     </p>
 
     <ul>
-      <li>Specifying in the standalone app's Android manifest file that
-      notifications from the corresponding phone app should not be
-      bridged to the watch
+      <li>Specifying a bridging configuration in the manifest file
+      </li>
+
+      <li>Specifying a bridging configuration at runtime
       </li>
 
       <li>Setting a dismissal ID so notification dismissals are synced across
@@ -47,43 +55,201 @@
       </li>
     </ul>
 
-    <h2 id="preventing_bridging_with_the_bridging_mode_feature">
-      Preventing Bridging with the Bridging Mode Feature
+    <h2 id="using-an-entry-in-the-manifest-file">
+      Specifying a Bridging Configuration in the Manifest File
     </h2>
 
     <p>
-      To prevent bridging of notifications from a phone app, you can use an
+      An app's Android manifest file can indicate that notifications from the
+      corresponding phone app should not be bridged to the watch. Specifically,
+      to prevent bridging of notifications from a phone app, you can use a
+      <code>&lt;meta-data&gt;</code>
       entry in the manifest file of the watch app (e.g. the standalone watch
       app), as follows:
     </p>
 
-    <pre>
+<pre>
 com.google.android.wearable.notificationBridgeMode
-    </pre>
+</pre>
 
     <p>
       Setting that entry to <code>NO_BRIDGING</code> will prevent bridging:
     </p>
 
-    <pre>
-&lt;meta-data android:name="com.google.android.wearable.notificationBridgeMode"
-                   android:value="NO_BRIDGING" /&gt;
+<pre>
+&lt;meta-data android:name=&quot;com.google.android.wearable.notificationBridgeMode&quot;
+                   android:value=&quot;NO_BRIDGING&quot; /&gt;
 </pre>
+
     <p>
-      The default bridging behavior occurs if you do not include the entry or
+      The default bridging behavior occurs if you do not
+      include the <code>&lt;meta-data&gt;</code> entry or
       if you specify a value of <code>BRIDGING</code> instead of
       <code>NO_BRIDGING</code>.
     </p>
 
-    <h3 id="existing_method_of_preventing_bridging">
-      Existing method of preventing bridging
+    <p>
+      For an existing app, if you are using
+      Google Cloud Messaging (GCM) or Firebase Cloud
+      Messaging (FCM) to send notification alerts to devices,
+      you may already have disabled bridging in case a phone is not
+      connected at the time of receiving an alert.
+      In this case, you may still want to dismiss the notification
+      across other devices when it is dismissed in a watch app.
+    </p>
+
+    <p>
+      The bridging configuration that is set in the manifest takes effect as
+      soon as a watch app is installed.
+    </p>
+
+    <h2 id="specifying-a-bridging-configuration-at-runtime">
+      Specifying a Bridging Configuration at Runtime
+    </h2>
+
+    <p>
+      This section describes how to specify a bridging configuration at runtime
+      using the <code>BridgingManager</code> class
+      <code>(android.support.wearable.notifications.BridgingManager)</code>.
+    </p>
+
+    <p>
+      You can set a bridging mode, and optionally set tags for notifications
+      that are exempt from the bridging mode, using a
+      <code>BridgingManager</code> object. Specifically, create a
+      <code>BridgingConfig</code> object and set it as shown in this section,
+      optionally using the <code>setBridgingEnabled</code> method. If you
+      specify a bridging configuration at runtime, then if the
+      <code>setBridgingEnabled</code> method is not set, bridging is enabled by
+      default.
+    </p>
+
+    <p>
+      Specifying a bridging configuration at runtime overrides a
+      bridging-related setting in the Android manifest file.
+    </p>
+
+    <h3 id="disable-bridging-for-all-notifications">
+      Disable bridging for all notifications
     </h3>
 
     <p>
+      You can use the <code>setBridgingEnabled</code> method, as follows:
+    </p>
+
+<pre>
+BridgingManager.setConfig(context,
+  new BridgingConfig.Builder(context)
+    .setBridgingEnabled(false)
+    .build());
+</pre>
+    <p>
+      If the above setter is not called, the bridging mode defaults to true.
+      Here is an example of setting tags without using the
+      <code>setBridgingEnabled</code> method, excluding notifications with a
+      tag of <code>foo</code> or <code>bar</code>:
+    </p>
+
+<pre>
+BridgingManager.setConfig(context,
+  new BridgingConfig.Builder(context)
+    .addExcludedTag("foo")
+    .addExcludedTag("bar")
+    .build());
+</pre>
+    <h3 id="exempt-notifications-that-are-tagged">
+      Exempt notifications that are tagged
+    </h3>
+
+    <p>
+      You can disable bridging for all notifications except those with certain
+      tags.
+    </p>
+
+    <p>
+      For example, you can disable bridging, except for notifications tagged as
+      <code>foo</code> or <code>bar,</code> with the following:
+    </p>
+
+<pre>
+BridgingManager.setConfig(context,
+  new BridgingConfig.Builder(context)
+    .setBridgingEnabled(false)
+    .addExcludedTag("foo")
+    .addExcludedTag("bar")
+    .build());
+</pre>
+
+    <p>
+      As another example, you can disable bridging for all notifications except
+      for notifications tagged as <code>foo</code>, <code>bar</code> or
+      <code>baz</code>.
+    </p>
+
+    <pre>
+BridgingManager.setConfig(context,
+  new BridgingConfig.Builder(context)
+    .setBridgingEnabled(false)
+    .addExcludedTags(Arrays.asList("foo", "bar", "baz"))
+    .build());
+</pre>
+    <h3 id="enable-bridging-except-for-notifications-with-certain-tags">
+      Enable bridging except for notifications with certain tags
+    </h3>
+
+    <p>
+      You can enable bridging for all notifications except those with certain
+      tags.
+    </p>
+
+    <p>
+      For example, you can enable bridging for all notifications, except for
+      notifications tagged as <code>foo</code> or <code>bar</code>, with the
+      following:
+    </p>
+
+<pre>
+BridgingManager.setConfig(context,
+  new BridgingConfig.Builder(context)
+    .setBridgingEnabled(true)
+    .addExcludedTag("foo")
+    .addExcludedTag("bar")
+    .build());
+</pre>
+
+    <h3 id="setting-a-bridge-tag">
+      Setting a bridge tag
+    </h3>
+
+    <p>
+      A bridge tag can be set on a notification by calling the
+      <code>setNotificationBridgeTag</code> method as follows:
+    </p>
+
+<pre>
+BridgingManager.setNotificationBridgeTag(&lt;NotificationCompat.Builder&gt;, &lt;String&gt;);
+</pre>
+
+    <p>
+      For example:
+    </p>
+
+<pre>
+NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
+&lt;set other fields&gt;;
+BridgingManager.setNotificationBridgeTag(builder, &quot;foo&quot;);
+Notification notification =  builder.build();
+</pre>
+
+    <h2 id="existing-method-of-preventing-bridging">
+      Existing Method of Preventing Bridging
+    </h2>
+
+    <p>
       An existing way to prevent bridging is with the
       <code>Notification.Builder</code> class; specify <code>true</code> in the
       <a href=
-      "{@docRoot}reference/android/app/Notification.Builder.html#setLocalOnly(boolean)">
+      "http://developer.android.com/reference/android/app/Notification.Builder.html#setLocalOnly(boolean)">
       setLocalOnly</a> method.
     </p>
 
@@ -95,12 +261,6 @@
       the watch app may not be installed on all of them.
     </p>
 
-    <p>
-      Thus, if bridging should be prevented when the watch app
-      is installed, use the <a href=
-      "#preventing_bridging_with_the_bridging_mode_feature">Bridging mode
-      feature</a>.
-    </p>
 
     <h2 id="using_a_dismissal_id_to_sync_notification_dismissals">
       Using a Dismissal ID to Sync Notification Dismissals
@@ -110,7 +270,7 @@
       If you prevent bridging with the Bridging mode feature, dismissals
       (cancellations) of notifications are not synced across a user's devices.
       However, the following methods of the <a href=
-      "{@docRoot}reference/android/support/v4/app/NotificationCompat.WearableExtender.html">
+      "http://developer.android.com/reference/android/support/v4/app/NotificationCompat.WearableExtender.html">
       NotificationCompat.WearableExtender</a> class enable you to use dismissal
       IDs:
     </p>
@@ -118,7 +278,7 @@
     <pre>
 public WearableExtender setDismissalId(String dismissalId)
 public String getDismissalId()
-    </pre>
+</pre>
     <p>
       To enable a dismissal to be synced, use the <code>setDismissalId()</code>
       method. For each notification, pass a globally unique ID, as a string,
@@ -135,12 +295,12 @@
 
     <pre>
 NotificationCompat.WearableExtender wearableExtender =
-new NotificationCompat.WearableExtender().setDismissalId(“abc123”);
+new NotificationCompat.WearableExtender().setDismissalId("abc123");
 Notification notification = new NotificationCompat.Builder(context)
 &lt;set other fields&gt;
 .extend(wearableExtender)
 .build();
-    </pre>
+</pre>
     <p>
       Dismissal IDs work if a watch is paired to an Android phone, but not if a
       watch is paired to an iPhone.
diff --git a/docs/html/wear/preview/features/complications.jd b/docs/html/wear/preview/features/complications.jd
index 3334cb7..c866118 100644
--- a/docs/html/wear/preview/features/complications.jd
+++ b/docs/html/wear/preview/features/complications.jd
@@ -13,6 +13,13 @@
             Complications to a Watch Face</a>
           </li>
           <li>
+            <a href="#permissions-for-complication-data">Permissions
+            for Complication Data</a>
+          </li>
+          <li>
+            <a href="#default-providers">Default Providers for Watch Faces</a>
+          </li>
+          <li>
             <a href="#exposing_data_to_complications">Exposing Data to
             Complications</a>
           </li>
@@ -27,12 +34,14 @@
             <a href="#api_additions">API Additions</a>
           </li>
       </ol>
+
     <h2>See Also</h2>
       <ol>
         <li><a class="external-link"
           href="https://github.com/googlesamples/android-WatchFace">Watch
           Face sample app with complications</a></li>
       </ol>
+
       </div>
     </div>
 
@@ -56,9 +65,12 @@
     </p>
 
     <p>
-      Along with reviewing this page, download the Android Wear 2.0 Preview
-      Reference (see the Complications API <a href=
-      "#api_additions">additions</a>) and review the Javadoc for complications.
+      You can review the Javadoc for complications by downloading
+      the Android Wear 2.0 Preview
+      Reference. Also see the <a href="#api_additions">API additions for
+      complications</a> and the
+      <a href="https://developer.android.com/wear/preview/behavior-changes.html">
+      behavior changes</a> for Wear 2.0.
     </p>
 
     <p>
@@ -117,8 +129,8 @@
       <code>WatchFaceService.Engine</code> class, with a list of watch face
       complication IDs. A watch face creates these IDs to uniquely identify
       slots on the watch face where complications can appear, and passes them
-      to the <code>createProviderChooserIntent</code> method (of the
-      <code>ProviderChooserIntent</code> class) to allow the user to decide
+      to the <code>createProviderChooserIntent</code> method
+      to allow the user to decide
       which complication should go in which slot.
     </p>
 
@@ -186,6 +198,406 @@
       where possible.
     </p>
 
+    <h2 id="permissions-for-complication-data">
+      Permissions for Complication Data
+    </h2>
+
+    <p>
+      A watch face must have the following <a href=
+      "https://developer.android.com/training/permissions/requesting.html">permission</a>
+      to receive complication data and open the provider chooser:
+    </p>
+
+<pre>
+com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA
+</pre>
+
+    <h3 id="opening-the-provider-chooser">
+      Opening the provider chooser
+    </h3>
+
+    <p>
+      A watch face that was not granted the above permission will be unable to
+      start the provider chooser.
+    </p>
+
+    <p>
+      To make it easier to request the permission and start the chooser, the
+      <code>ComplicationHelperActivity</code> class is available in the
+      wearable support library. This class should be used instead of
+      <code>ProviderChooserIntent</code> to start the chooser in almost all
+      cases.
+    </p>
+
+    <h4 id="requesting-the-necessary-permission">
+      Requesting the necessary permission
+    </h4>
+
+    <p>
+      To use <code>ComplicationHelperActivity</code>, add it to the watch face
+      in the <a href=
+      "https://developer.android.com/guide/topics/manifest/manifest-intro.html">
+      manifest file</a>:
+    </p>
+
+<pre>
+&lt;activity android:name=&quot;android.support.wearable.complications.ComplicationHelperActivity&quot;/&gt;
+</pre>
+
+    <p>
+      To start the provider chooser, call the
+      <code>ComplicationHelperActivity.createProviderChooserHelperIntent</code>
+      method, to obtain an intent.
+    </p>
+
+    <p>
+      The new intent can be used with either <code>startActivity</code> or
+      <code>startActivityForResult</code> to launch the chooser.
+    </p>
+
+    <p>
+      Here is an example of using the new intent with
+      <code>startActivityForResult</code>:
+    </p>
+
+    <pre>
+startActivityForResult(
+  ComplicationHelperActivity.createProviderChooserHelperIntent(
+     getActivity(),
+     watchFace,
+     complicationId,
+     ComplicationData.TYPE_LARGE_IMAGE),
+  PROVIDER_CHOOSER_REQUEST_CODE);
+</pre>
+    <p>
+      When the helper activity is started, the helper activity checks if the
+      permission was granted. If the permission was not granted, the helper
+      activity makes a runtime permission request. If the permission request is
+      accepted (or is unneeded), the provider chooser is shown.
+    </p>
+
+    <p>
+      If <code>startActivityForResult</code> was used with the intent, the
+      result delivered back to the calling Activity will have a result code of
+      <code>RESULT_OK</code> if a provider was successfully set, or a result
+      code of <code>RESULT_CANCELLED</code> if no provider was set.
+    </p>
+
+    <p>
+      In the case where a provider was set,
+      <code>ComplicationProviderInfo</code> for the chosen provider will be
+      included in the data intent of the result, as an extra with the key
+      <code>ProviderChooserIntent#EXTRA_PROVIDER_INFO</code>.
+    </p>
+
+    <h3 id="receiving-complication-data">
+      Receiving complication data
+    </h3>
+
+    <p>
+      In general, watch faces need the above permission in order to receive
+      complication data, but there are some exceptions. Specifically, a watch
+      face can only receive data from a provider if one of the following is
+      true:
+    </p>
+
+    <ul>
+      <li>The provider is a "safe" system provider,
+      </li>
+
+      <li>The provider and watch face are from the same app,
+      </li>
+
+      <li>The provider whitelists the watch face as a "safe" watch face, or
+      </li>
+
+      <li>The watch face has the permission
+      </li>
+    </ul>
+
+    <h4 id="lack-of-appropriate-permission">
+      Lack of appropriate permission
+    </h4>
+
+    <p>
+      If none of the above is true, then when <code>ComplicationData</code>
+      normally would be sent by a provider to a watch face, the system instead
+      sends data of the type <code>TYPE_NO_PERMISSION</code>. This type
+      includes an icon (an exclamation mark) and short text ("--") to allow it
+      to be rendered as if it were of the short text type or icon type, for
+      convenience.
+    </p>
+
+    <p>
+      When a watch face receives data of <code>TYPE_NO_PERMISSION</code>, the
+      watch face should render this appropriately, so the user can see that
+      action is needed for the complication to work. If possible, a tap on a
+      complication in this state should launch a permission request. This can
+      be done using
+      <code>ComplicationHelperActivity.createPermissionRequestHelperIntent</code>,
+      if the helper activity was added to the watch face app.
+    </p>
+
+    <p>
+      If a user accepts the permission request created by the helper activity,
+      updates are requested for all the active complications on the watch face
+      automatically, allowing the <code>TYPE_NO_PERMISSION</code> data to be
+      replaced by real data.
+    </p>
+
+    <h4 id="safe-providers">
+      Safe providers
+    </h4>
+
+    <p>
+      Some system providers are considered "safe", because they only supply
+      information that the watch face already could obtain itself.
+    </p>
+
+    <p>
+      These providers are listed in the new <code>SystemProviders</code> class
+      in the wearable support library. Whether a system provider is safe is
+      stated in the Javadoc (in the Android Wear 2.0 Preview Reference). Also
+      see <a href="#system-providers">System providers</a> for a list.
+    </p>
+
+    <h4 id="provider-specified-safe-watch-faces">
+      Provider-specified safe watch faces
+    </h4>
+
+    <p>
+      Providers can specify certain watch faces as "safe" to receive their
+      data. This is intended to be used only when the watch face will attempt
+      to use the provider as a default (see below),
+      and the provider trusts the watch face app.
+    </p>
+
+    <p>
+      To declare watch faces as safe, the provider adds metadata with a key of
+      <code>android.support.wearable.complications.SAFE_WATCH_FACES</code>. The
+      metadata value should be a comma-separated list (whitespace is ignored).
+      Entries in the list can be component names (of
+      <code>WatchFaceServices</code>, given as if
+      <code>ComponentName.flattenToString()</code> had been called), or they
+      can be package names (of apps, in which case every watch face within a
+      specified app is considered safe).
+    </p>
+
+    <p>
+      For example:
+    </p>
+
+<pre>
+&lt;meta-data
+       android:name=&quot;android.support.wearable.complications.SAFE_WATCH_FACES&quot;
+        android:value=&quot;
+          com.app.watchface/com.app.watchface.MyWatchFaceService,
+          com.anotherapp.anotherwatchface/com.something.WatchFaceService,
+          com.something.text
+        &quot;/&gt;
+</pre>
+
+  <h2 id="default-providers">
+      Default Providers for Watch Faces
+  </h2>
+
+    <p>
+      Watch faces can specify default providers that are used until a user
+      selects a provider.
+    </p>
+
+    <h3 id="setting-default-providers">
+      Setting default providers
+    </h3>
+
+    <p>
+      Set default providers using the
+      <code>setDefaultComplicationProvider</code> method in
+      <code>WatchFaceService.Engine</code>. This method may be called at any
+      time, but it does nothing if the user already chose a provider for the
+      given complication.
+    </p>
+
+    <h3 id="safe-providers2">
+      Safe providers
+    </h3>
+
+    <p>
+      For most providers, the <code>RECEIVE_COMPLICATION_DATA</code> permission
+      must be granted to a watch face before data can flow to it. However, some
+      system providers are considered "safe", and do not require the watch face
+      to have the permission for data to be sent (see <a href=
+      "#safe-providers">Safe Providers</a> and <a href=
+      "#system-providers">System providers</a>). These providers may be
+      preferable to use as defaults, as they can supply data immediately.
+    </p>
+
+    <p>
+      Alternatively, if a watch face has a partnership with a certain provider
+      and wishes to use it as a default, it can request that the provider list
+      it as a safe watch face (see <a href=
+      "#provider-specified-safe-watch-faces">Provider-specified safe watch
+      faces</a>).
+    </p>
+
+    <h3 id="system-providers">
+      System providers
+    </h3>
+
+    <p>
+      The system includes providers that can be used as defaults. These are
+      listed in the <code>SystemProviders</code> class in the wearable support
+      library.
+    </p>
+
+    <p>
+      The following table has details about providers that are considered safe:
+    </p>
+
+    <table>
+      <tr>
+        <th>
+          Method name in the SystemProviders class
+        </th>
+        <th>
+          Safety
+        </th>
+        <th>
+          Can be the default
+        </th>
+        <th>
+          Notes
+        </th>
+      </tr>
+
+      <tr>
+        <td>
+          <code>dateProvider()</code>
+        </td>
+        <td>
+          Yes
+        </td>
+        <td>
+          Yes
+        </td>
+        <td>
+          The standard system date provider. Tapping opens the standard Agenda
+          app.
+        </td>
+      </tr>
+
+      <tr>
+        <td>
+          <code>currentTimeProvider()</code>
+        </td>
+        <td>
+          Yes
+        </td>
+        <td>
+          Yes
+        </td>
+        <td>
+          The standard system "time and date" provider. No tap action.
+        </td>
+      </tr>
+
+      <tr>
+        <td>
+          <code>batteryProvider()</code>
+        </td>
+        <td>
+          Yes
+        </td>
+        <td>
+          Yes
+        </td>
+        <td>
+          The standard system battery provider. No tap action.
+        </td>
+      </tr>
+
+      <tr>
+        <td>
+          <code>stepCountProvider()</code>
+        </td>
+        <td>
+          Yes
+        </td>
+        <td>
+          Yes
+        </td>
+        <td>
+          Shows a daily total of steps, as reported by
+          <code>readDailyTotal</code>.
+        </td>
+      </tr>
+
+      <tr>
+        <td>
+          <code>unreadCountProvider()</code>
+        </td>
+        <td>
+          Yes
+        </td>
+        <td>
+          Yes
+        </td>
+        <td>
+          Shows the number of unread notifications in the stream.
+        </td>
+      </tr>
+
+      <tr>
+        <td>
+          <code>worldClockProvider()</code>
+        </td>
+        <td>
+          Yes
+        </td>
+        <td>
+          Yes
+        </td>
+        <td>
+          Will default to London or New York. Can be tapped to change the time
+          zone.
+        </td>
+      </tr>
+
+      <tr>
+        <td>
+          <code>appsProvider()</code>
+        </td>
+        <td>
+          Yes
+        </td>
+        <td>
+          Yes
+        </td>
+        <td>
+          Will show an "apps" icon at first, which can be tapped to choose an
+          app.
+        </td>
+      </tr>
+
+      <tr>
+        <td>
+          <code>nextEventProvider()</code>
+        </td>
+        <td>
+          No
+        </td>
+        <td>
+          Yes (but not a safe provider)
+        </td>
+        <td>
+          The standard system "next event" provider. Tapping opens
+            the standard Agenda app.
+          </p>
+        </td>
+      </tr>
+    </table>
+
+
     <h2 id="exposing_data_to_complications">
       Exposing Data to Complications
     </h2>
@@ -203,6 +615,11 @@
       be used to send data back to the system.
     </p>
 
+    <p class="note"><strong>Note:</strong> When you provide data as a
+    complication data provider, the watch face receives the raw values
+    you send so it can draw them on the watch face.
+    </p>
+
     <p>
       In your app's manifest, declare the service and add an intent filter for
       the following:
@@ -210,7 +627,8 @@
 
     <pre>
 android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST
-</pre>
+    </pre>
+
     <p>
       The service's manifest entry should also include an
       <code>android:icon</code> attribute. The provided icon should be a
@@ -227,6 +645,21 @@
       <a href="#api_additions">API Additions</a>).
     </p>
 
+    <p>
+      Additionally, a permission for provider services ensures that only the Android Wear system
+      can bind to provider services. Only the Android Wear system can have this
+      permission.
+    </p>
+
+    <p>
+      Provider services should add the following to their service declarations
+      in the manifest:
+    </p>
+
+<pre>
+android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER"
+</pre>
+
     <h3 id="update_period">
       Update period
     </h3>
@@ -371,6 +804,11 @@
     <p>
       The following table describes the types and fields of the
       <code>ComplicationData</code> object.
+      If a watch face requests a field that is invalid for a complication type,
+      a default value for the field is returned.
+      For example, if a watch face tries to access a <code>Long text</code>
+      field in a <code>SHORT_TEXT</code> type, the default value for the
+      <code>Long text</code> field is returned.
     </p>
 
     <table>
@@ -489,56 +927,80 @@
     </table>
 
     <p>
-      In addition, the following two types have no fields. These two types may
-      be sent for any complication slot and do not need to be included in a
-      list of supported types:
+      In addition, the types in the table below are for empty data and
+      may be sent for any complication slot. These types have no fields
+      and do not need to be included in a
+      list of supported types. These types enable watch
+      faces to differentiate among the following three cases:
+    </p>
+
+    <ul>
+      <li>No provider was chosen
+      </li>
+
+      <li>The user has selected "empty" for a slot
+      </li>
+
+      <li>A provider has no data to send
+      </li>
+    </ul>
+
+    <p>
+      Providers should not send <code>TYPE_EMPTY</code> in response to
+      update requests. Providers should send <code>TYPE_NO_DATA</code> instead.
+    </p>
+
+    <p>
+      Details on the complication types for "empty" data are in the
+      following table:
     </p>
 
     <table>
       <tr>
-        <th style="width:175px">
-          Type
+        <th>Complication type
         </th>
-        <th style="width:175px">
-          Required fields
-        </th>
-        <th style="width:175px">
-          Optional fields
-        </th>
-        <th>
-          Notes
+        <th>Description
         </th>
       </tr>
 
       <tr>
         <td>
-          NOT_CONFIGURED
+          <code>TYPE_NOT_CONFIGURED</code>
         </td>
         <td>
-          None
-        </td>
-        <td>
-          None
-        </td>
-        <td>
-          Sent when a provider has not yet been chosen for a complication.
+          Sent by the system when a complication is activated but the user has
+          not selected a provider, and no default was set.
+          <p>
+            Cannot be sent by providers.
+          </p>
         </td>
       </tr>
 
       <tr>
         <td>
-          EMPTY
+          <code>TYPE_EMPTY</code>
         </td>
         <td>
-          None
+          Sent by the system when a complication is activated and the user has
+          chosen "empty" instead of a provider, or when the watch face has
+          chosen no provider, and this type, as the default.
+          <p>
+            Cannot be sent by providers.
+          </p>
+        </td>
+      </tr>
+
+      <tr>
+        <td>
+          <code>TYPE_NO_DATA</code>
         </td>
         <td>
-          None
-        </td>
-        <td>
-          Sent by a provider when there is no data to display in a
-          complication, or sent by the system when nothing should be shown in a
-          complication.
+          Sent by the system when a complication (that has a provider) is
+          activated, to clear the complication before actual data is received
+          from the provider.
+          <p>
+            Should be sent by providers if they have no actual data to send.
+          </p>
         </td>
       </tr>
     </table>
@@ -700,8 +1162,8 @@
     </h2>
 
     <p>
-      The Complications API includes new classes in the Wearable Support
-      Library. For more information, download the <a href=
+      The Complications API includes new classes in the wearable support
+      library. For more information, download the <a href=
       "{@docRoot}wear/preview/start.html#get_the_preview_reference_documentation">
       Android Wear 2.0 Preview Reference</a>.
     </p>
@@ -722,26 +1184,14 @@
       </li>
 
       <li>
-        <code>ComplicationText</code>
+        <code>ComplicationHelperActivity</code>
         <ul>
-          <li>Used to supply text-based values in a
-          <code>ComplicationData</code> object
+          <li>Used to request the following permission: <br>
+<code>com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA</code>
           </li>
 
-          <li>Includes options for time-dependent values, whose text value
-          depends on the current time
-          </li>
-        </ul>
-      </li>
-
-      <li>
-        <code>ComplicationProviderService</code>
-        <ul>
-          <li>Extends <code>Service</code> and includes callback methods to
-          respond to the complication system
-          </li>
-
-          <li>Callback methods are all called on the main thread
+          <li>Used instead of <code>ProviderChooserIntent</code>
+          to start the chooser in almost all cases
           </li>
         </ul>
       </li>
@@ -759,13 +1209,35 @@
       </li>
 
       <li>
-        <code>ProviderChooserIntent</code>
+        <code>ComplicationProviderService</code>
         <ul>
-          <li>Non-instantiable utility class
+          <li>Extends <code>Service</code> and includes callback methods to
+          respond to the complication system
           </li>
 
-          <li>Includes a method that a watch face can call for starting a
-          provider chooser (to allow a user to configure complications)
+          <li>Callback methods are all called on the main thread
+          </li>
+        </ul>
+      </li>
+
+      <li>
+        <code>ComplicationText</code>
+        <ul>
+          <li>Used to supply text-based values in a
+          <code>ComplicationData</code> object
+          </li>
+
+          <li>Includes options for time-dependent values, whose text value
+          depends on the current time
+          </li>
+        </ul>
+      </li>
+
+      <li>
+        <code>ProviderChooserIntent</code>
+        <ul>
+          <li>Non-instantiable utility class that is not commonly used; use
+          <code>ComplicationHelperActivity</code> instead
           </li>
         </ul>
       </li>
@@ -789,6 +1261,16 @@
           </li>
         </ul>
       </li>
+
+      <li>
+        <code>SystemProviders</code>
+        <ul>
+          <li>Lists system providers that are considered "safe",
+          because they only supply information that the watch face
+          already could obtain itself
+          </li>
+        </ul>
+      </li>
     </ul>
 
     <p>
diff --git a/docs/html/wear/preview/features/notifications.jd b/docs/html/wear/preview/features/notifications.jd
index dcc0970..b546978 100644
--- a/docs/html/wear/preview/features/notifications.jd
+++ b/docs/html/wear/preview/features/notifications.jd
@@ -1,6 +1,5 @@
 page.title=Notification Changes in Android Wear 2.0
-meta.tags="wear", "wear-preview", "notifications"
-page.tags="wear"
+meta.tags="wear", "wear-preview", "notifications" page.tags="wear"
 page.image=/wear/preview/images/expanded_diagram.png
 
 
@@ -12,6 +11,7 @@
     <h2>This document includes</h2>
     <ol>
       <li><a href="#visual">Visual Updates</a></li>
+      <li><a href="#inline">Inline Action</a></li>
       <li><a href="#expanded">Expanded Notifications</a></li>
       <li><a href="#messaging">MessagingStyle</a></li>
     </ol>
@@ -67,7 +67,8 @@
   We recommended that you don't set color for bridged notifications.
 
   When Wear apps post local notifications, you can work around this by checking
-  <a href="{@docRoot}training/basics/supporting-devices/platforms.html#version-codes">the API level of the device</a> they're running on and using an appropriate color
+  <a href="{@docRoot}training/basics/supporting-devices/platforms.html#version-codes">the API level of the device</a>
+   they're running on and using an appropriate color
   for Wear 1.x and a different color for Wear 2.0.
 </li>
 
@@ -77,6 +78,85 @@
   you must update the text of your notification.
 </li>
 </ul>
+
+<h2 id="inline">Inline Action</h3>
+
+<img src="{@docRoot}wear/preview/images/inline_action.png" style="float:right;margin:10px 20px 0 0">
+<p>
+  Wear 2.0 now supports inline action, which allows users to take actions on a
+  notification from within the notification stream card.  On Wear, the inline
+  action appears as an additional button displayed at the bottom of the notification.
+</p>
+<p>
+  Inline actions are optional but recommended for cases in which users are likely
+  to take an action on a notification after viewing the contents in the
+  notification stream card (without going to the
+  <a href= "{@docRoot}wear/preview/features/notifications.html#expanded">expanded notification</a>).
+  Examples of good use cases for inline action on a notification include: replying to a
+  text message, stopping a fitness activity, and archiving an email message.
+</p>
+
+<p>
+  A notification can provide only one inline action.
+  To display the inline action as an additional button in the notification, set
+  the <a href="https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Action.WearableExtender.html#setHintDisplayActionInline(boolean)">{@code setHintDisplayActionInline()}</a>
+  method to true. When a user taps the inline action, the system invokes
+  the intent that you specified in the notification action.
+</p>
+
+<h3>Adding an inline action</h3>
+<p>
+  The following code example shows how to create a notification with an inline
+  reply action:
+</p>
+
+<ol>
+  <li>Create an instance of
+    <a href="https://developer.android.com/reference/android/support/v4/app/RemoteInput.Builder.html">{@code RemoteInput.Builder}</a></code>
+    that you can add to your notification action. This class's constructor accepts a
+    string that the system uses as the key for the text input. Later, your app
+    uses that key to retrieve the text of the input.
+
+<pre>
+String[] choices = context.getResources().getStringArray(R.array.notification_reply_choices);
+    choices = WearUtil.addEmojisToCannedResponse(choices);
+  RemoteInput remoteInput = new RemoteInput.Builder(Intent.EXTRA_TEXT)
+        .setLabel(context.getString(R.string.notification_prompt_reply))
+        .setChoices(choices)
+        .build();
+</pre>
+
+  </li>
+
+  <li>
+    Use the <a href="https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Action.Builder.html#addRemoteInput(android.support.v4.app.RemoteInput)">{@code addRemoteInput()}</a>
+    method to attach the <ahref="https://developer.android.com/reference/android/support/v4/app/RemoteInput.html">{@code RemoteInput}</a>
+    object to an action.
+
+<pre>
+NotificationCompat.Action.Builder actionBuilder = new NotificationCompat.Action.Builder(
+        R.drawable.ic_full_reply, R.string.notification_reply, replyPendingIntent);
+    actionBuilder.addRemoteInput(remoteInput);
+    actionBuilder.setAllowGeneratedReplies(true);
+</pre>
+  </li>
+
+  <li>
+    Add a hint to display the reply action inline, and use the
+    <a href="https://developer.android.com/reference/android/support/v4/app/NotificationCompat.WearableExtender.html#addAction(android.support.v4.app.NotificationCompat.Action)">{@code addAction}</a>
+    method to add this action to the notification.
+
+<pre>
+// Android Wear 2.0 requires a hint to display the reply action inline.
+    Action.WearableExtender actionExtender =
+        new Action.WearableExtender()
+            .setHintLaunchesActivity(true)
+            .setHintDisplayActionInline(true);
+    wearableExtender.addAction(actionBuilder.extend(actionExtender).build());
+</pre>
+  </li>
+</ol>
+
 <h2 id="expanded">Expanded Notifications</h2>
 <p>Android Wear 2.0 introduces <i>expanded notifications</i>, which provide
   substantial additional content and actions for each notification.
@@ -152,51 +232,52 @@
 </p>
 <h2 id="messaging">MessagingStyle</h2>
 
-<p>If you have a chat messaging app, your notifications should use
-<a href="{@docRoot}preview/features/notification-updates.html#style">{@code Notification.MessagingStyle}</a>,
- which is new in Android N. Wear 2.0 uses the chat messages included
-  in a <a href="{@docRoot}preview/features/notification-updates.html#style">{@code MessagingStyle}</a> notification
-
-  (see <a href="{@docRoot}preview/features/notification-updates.html#style">{@code addMessage()}</a>) to provide
-  a rich chat app-like experience in the expanded notification.
+<p>
+  If you have a chat messaging app, your notifications should use
+  <a href="https://developer.android.com/reference/android/support/v4/app/NotificationCompat.MessagingStyle.html">{@code NotificationCompat.MessagingStyle}</a>,
+  which is new in Android 7.0. Wear 2.0 uses the chat messages included in a
+  {@code MessagingStyle} notification
+  (see <a href="https://developer.android.com/reference/android/support/v4/app/NotificationCompat.MessagingStyle.html#addMessage(android.support.v4.app.NotificationCompat.MessagingStyle.Message)">{@code addMessage()}</a>)
+  to provide a rich chat app-like experience in the expanded notification.
 </p>
 
-<p class="note">Note: <a href="{@docRoot}preview/features/notification-updates.html#style">{@code MessagingStyle}</a>
+<p class="note">Note: <a href="https://developer.android.com/reference/android/support/v4/app/NotificationCompat.MessagingStyle.html">{@code MessagingStyle}</a>
 expanded notifications require that you have at least version 1.5.0.2861804 of the
   <a href="https://play.google.com/store/apps/details?id=com.google.android.wearable.app">Android Wear app</a>
-  on your paired Android phone. That version will be available within the next
-  few weeks in the Play Store.
+  on your paired Android phone.
 </p>
 
 <h3 id="smart-reply">Smart Reply</h3>
 <img src="{@docRoot}wear/preview/images/messaging_style.png" height="420"
   style="float:right;margin:10px 20px 0 0" />
-<p>Wear 2.0 also introduces <i>Smart Reply</i>
-for <a href="{@docRoot}preview/features/notification-updates.html#style">{@code MessagingStyle}</a> notifications.
+<p>Wear 2.0 also introduces <i>Smart Reply</i> for
+  <a href="https://developer.android.com/reference/android/support/v4/app/NotificationCompat.MessagingStyle.html">{@code MessagingStyle}</a> notifications.
   Smart Reply provides the user with contextually relevant, touchable choices in
   the expanded notification and in {@code RemoteInput}. These augment the fixed
   list of choices that the developer provides in
-   <a href="http://developer.android.com/reference/android/support/v4/app/RemoteInput.html">{@code RemoteInput}</a>
-    using the
-    <a href="{@docRoot}reference/android/support/v4/app/RemoteInput.Builder.html#setChoices(java.lang.CharSequence[])">{@code setChoices()}</a> method.
-</p>
-<p>By enabling Smart Reply for your MessagingStyle notifications,
-  you provide users with a fast (single tap), discreet (no speaking aloud), and
-  reliable way to respond to chat messages.
-</p>
-
-<p>Responses generated by Smart Reply are shown in addition to those set using the
+  <a href="http://developer.android.com/reference/android/support/v4/app/RemoteInput.html">{@code RemoteInput}</a>
+  using the
   <a href="{@docRoot}reference/android/support/v4/app/RemoteInput.Builder.html#setChoices(java.lang.CharSequence[])">{@code setChoices()}</a> method.
 </p>
+<p> Smart Reply provides users with a fast (single tap), discreet (no speaking aloud),
+  private (messages received by a user never leave the watch), and reliable (no
+  internet connection needed) way to respond to chat messages.
+</p>
+
+<p>
+  Smart Reply responses are generated by an entirely on-watch machine learning
+  model using the context provided by the MessagingStyle notification. No user
+  notification data is sent to Google servers to generate Smart Reply responses.
+</p>
+
 <p>To enable Smart Reply for your notification action, you need to do the
 following:
 </p>
 <ol>
-  <li>Use <a href="{@docRoot}preview/features/notification-updates.html#style">{@code Notification.MessagingStyle}</a>.
+  <li>Use <a href="https://developer.android.com/reference/android/support/v4/app/NotificationCompat.MessagingStyle.html">{@code NotificationCompat.MessagingStyle}</a>.
   </li>
-  <li>Call the method {@code setAllowGeneratedReplies()} for the notification action.
-  For more information, see the downloadable
-  <a href="{@docRoot}preview/setup-sdk.html#docs-dl">API reference</a>.
+  <li>Call the method <a href="https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Action.Builder.html#setAllowGeneratedReplies(boolean)">{@code setAllowGeneratedReplies(true)}</a>
+   for the notification action.
   </li>
   <li>Ensure that the notification action has a
     <a href="{@docRoot}reference/android/app/RemoteInput.html">{@code RemoteInput}</a>
@@ -236,3 +317,29 @@
 // 3) add an action with RemoteInput
 .extend(new WearableExtender().addAction(action)).build();
 </pre>
+
+<h3 id="images">Adding images to a MessagingStyle notification</h3>
+<p>
+  You can add images to a notification message  by setting the appropriate MIME
+  type and placing the URI to the image in {@code NotificationCompat.MessagingStyle.Message.}
+  <a href="https://developer.android.com/reference/android/support/v4/app/NotificationCompat.MessagingStyle.Message.html#setData(java.lang.String, android.net.Uri)">{@code setData()}</a> method.
+</p>
+<p>
+  Here is the code snippet to set data of type image in a notification:
+</p>
+<pre>
+NotificationCompat.MessagingStyle.Message message = new Message("sticker", 1, "Jeff")
+                      .setData("image/png", stickerUri);
+
+  NotificationCompat notification = new NotificationCompat.Builder()
+             .setStyle(new NotificationComapt.MessagingStyle("Me")
+             .addMessage(message)
+             .build());
+
+</pre>
+<p>
+  In the above code snippet the variable <code>stickerUri </code>is a Uri that
+  points to a publicly-accessible location, as described <a
+  href="https://developer.android.com/reference/android/support/v4/app/NotificationCompat.MessagingStyle.Message.html">here
+  </a>.
+</p>
\ No newline at end of file
diff --git a/docs/html/wear/preview/features/standalone-apps.jd b/docs/html/wear/preview/features/standalone-apps.jd
new file mode 100644
index 0000000..5c1930d
--- /dev/null
+++ b/docs/html/wear/preview/features/standalone-apps.jd
@@ -0,0 +1,499 @@
+page.title=Standalone Apps
+meta.keywords="wear-preview"
+page.tags="wear-preview"
+page.image=images/cards/card-n-sdk_2x.png
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+
+  <ul>
+    <li><a href="#planning_apps">Planning Your Phone and Watch Apps</a></li>
+    <li><a href="#network_access">Network Access and Cloud Messaging</a></li>
+    <li><a href="#background_services">Using Background Services</a></li>
+    <li><a href="#fcm">Cloud Notifications Using FCM</a></li>
+    <li><a href="#fcm-phone">Notifications from a Companion Phone</a></li>
+  </ul>
+
+</div>
+</div>
+
+    <p>
+      In Android Wear 2.0, apps can work independently of a phone. Users can
+      complete more tasks on a watch, without access to an Android or iOS
+      phone.
+    </p>
+
+    <h2 id="planning_apps">
+      Planning Your Phone and Watch Apps
+    </h2>
+
+    <p>
+      A watch APK targeting Wear 2.0 should not be embedded in a phone APK.
+      For more information, see
+      <a href="{@docRoot}wear/preview/features/app-distribution.html">
+      App Distribution</a>.
+    </p>
+
+    <p>
+      Generally, the minimum and target API level for a standalone app, and
+      for Wear 2.0, is level 24. The minimum SDK level can be 23
+      only if you are using the same APK
+      for Wear 1.0 and 2.0 (and thus have an embedded Wear 1.0 APK).
+    </p>
+
+    <p>
+      If you build a standalone Wear 2.0 APK and will continue to have a
+      Wear 1.0 APK, please do both of the following:
+    </p>
+
+    <ul>
+      <li>Provide a standalone version of the Wear APK, and
+      </li>
+
+      <li>Continue embedding a version of the Wear APK in your phone APK
+      </li>
+    </ul>
+
+    <p>
+      <strong>Caution</strong>: For the Wear 2.0 Developer Preview, if you
+      publish an update to your production phone APK that has removed an embedded
+      Wear APK, production users who update the phone APK before installing
+      your standalone Wear APK will lose their existing Wear app and its data.
+      Therefore, it's important that you continue to embed
+      your watch APK into your phone APK.
+    </p>
+
+    <p>
+      <a href=
+      "https://developer.android.com/training/articles/wear-permissions.html">
+      Run-time permissions</a> are required for standalone apps.
+    </p>
+
+    <h3>
+      Shared code and data storage
+    </h3>
+
+    <p>
+      Code can be shared between a Wear app and a phone app. Optionally, code
+      that is specific to a form factor can be in a separate module.
+    </p>
+
+    <p>
+      For example, common code for networking can be in a shared library.
+    </p>
+
+    <p>
+      You can use standard Android storage APIs to store data locally.
+      For example, you can use
+      the <a href=
+      "https://developer.android.com/reference/android/content/SharedPreferences.html">
+      SharedPreferences APIs</a>, SQLite, or internal storage (as you would in
+      the case of a phone).
+    </p>
+
+    <h3>
+      Detecting your phone app or watch app
+    </h3>
+
+    <p>
+      If a user of your watch app needs your phone app, your watch app can
+      detect if the phone app is available. Using the <a href=
+      "https://developers.google.com/android/reference/com/google/android/gms/wearable/CapabilityApi">
+      CapabilityApi</a>, your phone app or watch app can advertise its presence
+      to a paired device. It can do so statically and dynamically. When an app
+      is on a node in a user's Wear network (i.e., on a phone, paired watch, or
+      in the cloud), the <code>CapabilityApi</code> enables another
+      app to detect if it is installed. For more information, see <a href=
+      "https://developer.android.com/training/wearables/data-layer/messages.html#AdvertiseCapabilities">
+      Advertise capabilities</a>.
+    </p>
+
+    <p>
+      If your phone app is unavailable, your can check if the Play Store is
+      available on the phone, as described below, before directing the user to
+      go to the Play Store (to install your phone app).
+    </p>
+
+    <h4>
+      Checking for Play Store availability on a phone
+    </h4>
+
+    <p>
+      iPhones and some Android phones lack the Play Store. A standalone Wear
+      app can check if the paired phone has the Play Store, before directing a
+      user to go there to install your phone app. The
+      <code>PlayStoreAvailability</code> class contains a
+      <code>getPlayStoreAvailabilityOnPhone()</code> method that enables your
+      Wear app to check if a companion phone has the Play Store.
+    </p>
+
+    <p>
+      More information about the <code>PlayStoreAvailability</code> class is
+      available when you <a href=
+      "https://developer.android.com/wear/preview/start.html#get_the_preview_reference_documentation">
+      download the Android Wear 2.0 Preview Reference</a>. Here is a snippet
+      that uses the <code>getPlayStoreAvailabilityOnPhone()</code> method to
+      determine if the paired phone has the Play Store:
+    </p>
+
+<pre>
+int playStoreAvailabilityOnPhone =
+PlayStoreAvailability.getPlayStoreAvailabilityOnPhone(context);
+</pre>
+
+    <p>
+      The value returned by the <code>getPlayStoreAvailabilityOnPhone()</code>
+      method is one of the following:
+    </p>
+
+    <table>
+      <tr>
+        <th>
+          <strong>Return value</strong>
+        </th>
+        <th>
+          <strong>Description</strong>
+        </th>
+      </tr>
+
+      <tr>
+        <td>
+          <code>PLAY_STORE_ON_PHONE_AVAILABLE</code>
+        </td>
+        <td>
+          The Play Store is available on the companion phone.
+        </td>
+      </tr>
+
+      <tr>
+        <td>
+          <code>PLAY_STORE_ON_PHONE_UNAVAILABLE</code>
+        </td>
+        <td>
+          The Play Store is not available on the companion phone.
+        </td>
+      </tr>
+
+      <tr>
+        <td>
+          <code>PLAY_STORE_ON_PHONE_ERROR_UNKNOWN</code>
+        </td>
+        <td>
+          An error occurred in the check for the Play Store; another check
+          should be made later.
+        </td>
+      </tr>
+    </table>
+
+    <h2 id="network_access">
+      Network Access and Cloud Messaging
+    </h2>
+
+    <p>
+      Android Wear apps can make their own network requests. When a watch has a
+      Bluetooth connection to a phone, the watch's network traffic is proxied
+      through the phone. When a phone is unavailable, Wi-Fi and cellular
+      networks are used, depending on the hardware. The Wear platform handles
+      transitions between networks. A watch's network access thus does not
+      require the <a href=
+      "https://developer.android.com/training/wearables/data-layer/index.html">
+      Wearable Data Layer API</a>.
+    </p>
+
+    <p>
+      For sending notifications, apps can directly use Firebase Cloud Messaging
+      (FCM), which replaces Google Cloud Messaging, or continue to use GCM.
+    </p>
+
+    <p>
+      No APIs for network access or FCM are specific to Android Wear.
+      Refer to the existing documentation about <a href=
+      "https://developer.android.com/training/basics/network-ops/connecting.html">
+      connecting to a network</a> and <a href=
+      "https://developers.google.com/cloud-messaging/">cloud messaging</a>.
+    </p>
+
+    <p>
+      You can use protocols such as HTTP, TCP, and UDP. However,
+      the <a href="https://developer.android.com/reference/android/webkit/package-summary.html">
+      android.webkit</a> APIs are not available. Therefore,
+      use of cookies is available by reading and writing headers on
+      requests and responses, but the <a href=
+      "https://developer.androidcom/reference/android/webkit/CookieManager.html">
+      CookieManager</a> class is not available.
+    </p>
+
+    <p>
+      FCM works well with
+      <a href="https://developer.android.com/training/monitoring-device-state/doze-standby.html">
+      Doze</a>.
+    </p>
+
+    <p>
+      Additionally, we recommend using the following:
+    </p>
+
+    <ul>
+      <li>The <a href=
+      "https://developer.android.com/reference/android/app/job/JobScheduler.html">
+        JobScheduler</a> API for asynchronous jobs, including polling at
+        regular intervals (described below)
+      </li>
+
+      <li>Multi-networking APIs if you need to connect to specific network
+      types; see <a href=
+      "https://developer.android.com/about/versions/android-5.0.html#Wireless">
+        Multiple Network Connections</a>
+      </li>
+    </ul>
+
+    <p>
+      For foreground use cases, we currently recommend that you make a
+      request for an unmetered network. Here is an example of using
+      the multi-networking APIs to request an unmetered network:
+    </p>
+
+<pre>
+ConnectivityManager.NetworkCallback networkCallback =
+  new ConnectivityManager.NetworkCallback() {
+    &#64;Override
+    public void onAvailable(Network network) {
+      // access network
+      }
+    };
+ConnectivityManager connectivityManager =
+  (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+
+connectivityManager.requestNetwork(new NetworkRequest.Builder()
+  .addCapability(NET_CAPABILITY_NOT_METERED)
+  .build(), networkCallback);
+</pre>
+
+    <p>
+      We also recommend setting a timer for frontend scenarios
+      to prevent a user from potentially waiting for a long time.
+      When the network is no longer needed, or if the timer fires,
+      the network callback needs to be unregistered:
+    </p>
+
+<pre>
+connectivityManager.unregisterNetworkCallback(networkCallback):
+</pre>
+
+    <p>
+      A Wear app can communicate with a phone app using the <a href=
+      "https://developer.android.com/training/wearables/data-layer/index.html">Wearable
+      Data Layer API</a>, but connecting to a network using that API is
+      discouraged.
+    </p>
+
+    <h3 id="necessary_data">
+      Obtaining only the necessary data
+    </h3>
+
+    <p>
+      When obtaining data from the cloud, get only the necessary data.
+      Otherwise, you may introduce unnecessary latency, memory use, and battery
+      use.
+    </p>
+
+    <p>
+      When a watch is connected over a Bluetooth LE connection, your app may
+      have access to a bandwidth of only 10 kilobytes per second. Therefore,
+      the following steps are recommended:
+    </p>
+
+    <ul>
+      <li>Audit your network requests and responses for extra data that only is
+      for a phone app
+      </li>
+
+      <li>Shrink large images before sending them over a network to a watch
+      </li>
+    </ul>
+
+    <h2 id="background_services">
+      Using Background Services
+    </h2>
+
+    <p>
+      To ensure that background tasks are correctly executed, they must account
+      for <a href=
+      "https://developer.android.com/training/monitoring-device-state/doze-standby.html">
+      Doze</a>. In Android 6.0, Doze and App Standby resulted in significant
+      improvements to battery life by allowing devices to enter deep sleep when
+      idle and stationary.
+    </p>
+
+    <p>
+      Doze is <a href=
+      "https://developer.android.com/preview/behavior-changes.html#doze">enhanced</a>
+      in Android Nougat and Android Wear 2.0. When a screen turns off or enters
+      ambient mode for a long enough time, a subset of Doze can occur and
+      background tasks may be deferred for certain periods. Later, when a
+      device is stationary for an extended time, regular Doze occurs.
+    </p>
+
+    <p>
+      You should schedule jobs with the <a href=
+      "https://developer.android.com/reference/android/app/job/JobScheduler.html">
+      JobScheduler</a> API, which enables your app to register for Doze-safe
+      code execution. When scheduling jobs, you can select constraints such as
+      periodic execution and the need for connectivity or device charging.
+      It is important to configure jobs in a way that does not adversely
+      impact battery life. Jobs should use a
+      <a href="https://developer.android.com/reference/android/app/job/JobInfo.Builder.html">
+      JobInfo.Builder</a> object to provide constraints and metadata, e.g. with
+      one or more of the following methods for a task:
+    </p>
+
+    <ul>
+      <li>To schedule a task that requires networking, use
+      <code>setRequiredNetworkType(int networkType)</code>, specifying
+      <code>NETWORK_TYPE_ANY</code> or <code>NETWORK_TYPE_UNMETERED</code>;
+      note that <code>NETWORK_TYPE_UNMETERED</code> is for large data transfers
+      while <code>NETWORK_TYPE_ANY</code> is for small transfers
+      </li>
+
+      <li>To schedule a task while charging, use
+      <code>setRequiresCharging(boolean requiresCharging)</code>
+      </li>
+
+      <li>For specifying that a device is idle for a task, use
+      <code>setRequiresDeviceIdle(boolean requiresDeviceIdle)</code>; this
+      method can be useful for lower-priority background work or
+      synchronization, especially when used with
+      <code>setRequiresCharging</code>
+      </li>
+    </ul>
+
+    <p>
+      Note that some low-bandwidth networks, such as Bluetooth LE, are
+      considered metered.
+    </p>
+
+    <h3>
+      Scheduling with constraints
+    </h3>
+
+    <p>
+      You can schedule a task that requires constraints. In the example below,
+      a <code>JobScheduler</code> object activates <code>MyJobService</code>
+      when the following constraints are met:
+    </p>
+
+    <ul>
+      <li>Unmetered networking
+      </li>
+
+      <li>Device charging
+      </li>
+    </ul>
+
+    <p>
+      You can use the builder method <code>setExtras</code> to attach a bundle
+      of app-specific metadata to the job request. When your job executes, this
+      bundle is provided to your job service. Note the <code>MY_JOB_ID</code>
+      value passed to the <code>JobInfo.Builder</code> constructor. This
+      <code>MY_JOB_ID</code> value is an app-provided identifier. Subsequent
+      calls to cancel, and subsequent jobs created with that same value, will
+      update the existing job:
+    </p>
+
+<pre>
+JobInfo jobInfo = new JobInfo.Builder(MY_JOB_ID,
+        new ComponentName(this, MyJobService.class))
+        .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
+        .setRequiresCharging(true)
+        .setExtras(extras)
+        .build();
+((JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE))
+        .schedule(jobInfo);
+</pre>
+
+    <p>
+      Below is an implementation of <a href=
+      "https://developer.android.com/reference/android/app/job/JobService.html">
+      JobService</a> to handle the job above. When the job executes, a
+      <code>JobParameters</code> object is passed into the
+      <code>onStartJob</code> method. The <code>JobParameters</code> object
+      enables you to get the job ID value along with any extras bundle provided
+      when scheduling the job. The <code>onStartJob</code> method is called on
+      the main application thread, and therefore any expensive logic should be
+      run from a separate thread. In the example, an <code>AsyncTask</code> is
+      used to run code in the background. When work is complete, you would call
+      the <code>jobFinished</code> method to notify <code>JobScheduler</code>
+      that the task is done:
+    </p>
+
+<pre>
+public class MyJobService extends JobService {
+    &#64;Override public boolean onStartJob(JobParameters params) {
+        new JobAsyncTask().execute(params);
+        return true;
+    }
+
+    private class JobAsyncTask extends AsyncTask
+</pre>
+
+    <h2 id="fcm">
+      Cloud Notifications Using FCM
+    </h2>
+
+    <p>
+      FCM is the recommended way to send notifications to a watch.
+    </p>
+
+    <p>
+      Provide for messages from FCM by collecting a registration token for a
+      device when your Wear app runs. Then include the token as part of the
+      destination when your server sends messages to the FCM REST endpoint. FCM
+      sends messages to the device identified by the token.
+    </p>
+
+    <p>
+      An FCM message is in JSON format and can include one or both of the
+      following payloads:
+    </p>
+
+    <ul>
+      <li>
+        <strong>Notification payload.</strong> When a notification payload is
+        received by a watch, the data is displayed to a user directly in the
+        notification stream. When the user taps the notification, your app is
+        launched.
+      </li>
+
+      <li>
+        <strong>Data payload</strong>. The payload has a set of custom
+        key/value pairs. The payload and is delivered as data to your Wear app.
+      </li>
+    </ul>
+
+    <p>
+      For more information and examples of payloads, see <a href=
+      "https://firebase.google.com/docs/cloud-messaging/concept-options">About
+      FCM Messages</a>.
+    </p>
+
+    <h2 id="fcm-phone">
+      Notifications from a Companion Phone
+    </h2>
+
+    <p>
+      By default, notifications are bridged (shared) from a phone app to a
+      watch. If you have a standalone Wear app and a corresponding phone app,
+      duplicate notifications can occur. For example, the same notification
+      from FCM, received by both a phone and a watch, could be
+      displayed by both devices independently.
+    </p>
+
+    <p>
+      For information about preventing duplicate notifications, see <a href=
+      "https://developer.android.com/wear/preview/features/bridger.html">Bridging
+      Mode for Notifications</a>.
+    </p>
diff --git a/docs/html/wear/preview/features/wearable-recycler-view.jd b/docs/html/wear/preview/features/wearable-recycler-view.jd
new file mode 100644
index 0000000..f28a472
--- /dev/null
+++ b/docs/html/wear/preview/features/wearable-recycler-view.jd
@@ -0,0 +1,223 @@
+
+page.title=Curved Layout
+meta.tags="wear", "wear-preview", "RecyclerView"
+page.tags="wear"
+
+@jd:body
+
+
+<div id="qv-wrapper">
+<div id="qv">
+
+    <h2>In this document</h2>
+    <ol>
+      <li><a href="#creating">Creating a Curved Layout</a></li>
+      <li><a href="#adding">Adding a Circular Scrolling Gesture</a></li>
+      <li><a href="#aligning">Anchoring Children to the Curve</a></li>
+    </ol>
+
+</div>
+</div>
+
+
+<p>
+  Wear 2.0 introduces the {@code WearableRecyclerView} class for displaying
+  and manipulating a vertical list of items optimized for round displays.
+  {@code WearableRecyclerView} extends the existing
+  <a href="{@docRoot}reference/android/support/v7/widget/RecyclerView.html">{@code RecyclerView}</a>
+  class to provide a curved layout and a circular scrolling gesture in wearable apps.
+</p>
+<img src="https://android-dot-devsite.googleplex.com/wear/preview/images/wrv_new.png"
+      style="float:right;margin:10px 20px 0 0">
+
+<p>
+  You can adapt to this interface in your wearable app by creating a new
+  {@code WearableRecyclerView} container.
+</p>
+
+<p>
+  You should decide whether to use a {@code WearableRecyclerView}, based on
+  the kind of user experience you want to provide. We recommend using the
+  {@code WearableRecyclerView} for a simple, long list of items, such as an
+  application launcher, or a list contacts. Each item might have a short string
+  and an associated icon. Alternatively, each item might have only a string or
+  an icon. We do not recommend using a {@code WearableRecyclerView} for short
+  or complex lists.
+</p>
+
+<p>
+  This document describes how to create a curved layout for your scrollable items
+  and properly align them along the curve.
+</p>
+
+
+<h2 id="creating">Creating a Curved Layout</h2>
+<p>To create a curved layout for scrollable items in your wearable app:
+</p>
+<ul>
+  <li>Use {@code WearableRecyclerView} as your main container in the relevant
+      xml layout.
+  </li>
+
+  <li>By default, {@code WearableRecyclerView} uses the {@code
+    DefaultOffsettingHelper} class to offset items in a curved layout on round
+    devices. If you wish to implement your own offsetting logic, you can extend the
+    abstract {@code WearableRecyclerView.OffsettingHelper} class and attach it to
+    the {@code WearableRecyclerView} using {@code
+    WearableRecyclerView.setOffsettingHelper} method.
+
+    <pre>
+      CircularOffsettingHelper circularHelper = new CircularOffsettingHelper();
+      mRecyclerView.setOffsettingHelper(circularHelper);
+    </pre>
+
+    <pre>
+      public class CircularOffsettingHelper extends OffsettingHelper {
+
+        &#64;Override
+        public void updateChild(View child, WearableRecyclerView parent) {
+          int progress = child.getTop() / parent.getHeight();
+          child.setTranslationX(-child.getHeight() * progress);
+         }
+      }
+    </pre>
+
+  </li>
+
+</ul>
+
+<p class="note">
+  <strong>Note:</strong> {@code DefaultOffsettingHelper} class
+  offsets the child items
+  along a predefined UX curve, but the operation can cut off part of the child
+  view if it is not scaled down accordingly. This is because the default curve
+  attempts to fit 5 items on the screen, regardless of their size.
+  If you do not wish to scale your items, you should consider additional padding.
+</p>
+
+<h3>Examples</h3>
+<p>
+  The following code example demonstrates how to add {@code WearableRecyclerView}
+   to a layout:
+</p>
+<pre>
+&lt;android.support.wearable.view.WearableRecyclerView
+   xmlns:android="http://schemas.android.com/apk/res/android"
+   xmlns:tools="http://schemas.android.com/tools"
+   android:id="&#64;+id/recycler_launcher_view"
+   android:layout_width="match_parent"
+   android:layout_height="match_parent"
+   android:scrollbars="vertical" /&gt;
+ </pre>
+
+
+<p>
+  To customize the appearance of the children while scrolling (for example,
+  scale the icons and text while the items scroll away from the center),  extend
+  the  {@code DefaultOffsettingHelper} and override the {@code updateChild }
+  method. It is important to call the {@code super.updateChild(child, parent)} to
+  offset the children along the curve. However, if for any particular child you do
+  not wish them to follow a curve, you can chose not to call the super method for
+  that particular child.
+</p>
+
+<pre>
+
+public class MyOffsettingHelper extends DefaultOffsettingHelper {
+
+   /** How much should we scale the icon at most. */
+   private static final float MAX_ICON_PROGRESS = 0.65f;
+
+   private float mProgressToCenter;
+
+   public OffsettingHelper() {}
+
+   &#64;Override
+
+   public void updateChild(View child,  WearableRecyclerView parent) {
+       super.updateChild(child, parent);
+
+
+       // Figure out % progress from top to bottom
+       float centerOffset = ((float) child.getHeight() / 2.0f) /  (float) mParentView.getHeight();
+       float yRelativeToCenterOffset = (child.getY() / mParentView.getHeight()) + centerOffset;
+
+       // Normalize for center
+       mProgressToCenter = Math.abs(0.5f - yRelativeToCenterOffset);
+       // Adjust to the maximum scale
+       mProgressToCenter = Math.min(mProgressToCenter, MAX_ICON_PROGRESS);
+
+       child.setScaleX(1 - mProgressToCenter);
+       child.setScaleY(1 - mProgressToCenter);
+   }
+}
+
+
+</pre>
+
+
+<h2 id="adding">Adding a Circular Scrolling Gesture</h2>
+
+<p>
+  By default, circular scrolling is disabled in the {@code
+  WearableRecyclerView}. If you want to enable circular scrolling gesture
+  in your child view, use the  {@code WearavleRecyclerView}’s {@code
+  setCircularScrollingGestureEnabled()} method.  You can also customize the
+  circular scrolling gesture by defining one or both of the following:
+</p>
+
+<ul>
+  <li>How many degrees the user has to rotate by to scroll through one screen height.
+    This effectively influences the speed of the scolling -
+    {@code setScrollDegreesPerScreen} - the default value is set at 180 degrees.
+  </li>
+
+  <li>
+    The width of a virtual ‘bezel’ near the the edge of the screen in which the
+    gesture will be recognized - {@code setBezelWidth} - the default value is set
+    at 1. This is expressed as a fraction of the radius of the view.
+</ul>
+
+
+<p>The following code snippet shows how to set these methods:</p>
+
+<pre>
+  setCircularScrollingGestureEnabled(true);
+  setBezelWidth(0.5f);
+  setScrollDegreesPerScreen(90);
+</pre>
+
+<h2 id="aligning"> Anchoring Children to the Curve </h2>
+
+<p>
+  To ensure that the layout for WearableRecyclerView is adaptable to different
+  types of child views, the WearableRecyclerView class, by default, chooses the
+  middle left edge (X=0, Y=Half the child height) as the anchor coordinates for
+  the child item. Using the default anchor coordinates can result in offsetting
+  the child items from the left edge of the watch face. To customize the anchor
+  coordinates of your child view along the curve, you can overwrite the
+  {@code adjustAnchorOffsetXY()} method. You can calculate the X (horizontal)
+  and Y (vertical) offset of the child item, and set it using the
+  {@code adjustAnchorOffsetXY()} method to properly align items
+  along the curve. The coordinates should be with relation to the child view.
+</p>
+
+<p><img src="{@docRoot}wear/preview/images/alignment.png"/></p>
+<p><b>Figure 1</b>. Imaginary UX curve and anchor points on the curve.</p>
+
+<p>
+  The code snippet below, calculates the X offset for a child item in which the
+  width of the icon is same as the height of the child item. In this case, the
+  anchor coordinates for the child item are at the center of the icon.
+
+</p>
+<img src="{@docRoot}wear/preview/images/center_align.png" style="float:left;margin:10px 20px 0 0"/>
+
+<pre>
+ &#64;Override
+  protected void adjustAnchorOffsetXY(View child, float[] anchorOffsetXY) {
+    anchorOffsetXY[0] = child.getHeight() / 2.0f;
+  }
+</pre>
+
+
diff --git a/docs/html/wear/preview/images/alignment.png b/docs/html/wear/preview/images/alignment.png
new file mode 100644
index 0000000..525b334
--- /dev/null
+++ b/docs/html/wear/preview/images/alignment.png
Binary files differ
diff --git a/docs/html/wear/preview/images/apk-details.png b/docs/html/wear/preview/images/apk-details.png
new file mode 100644
index 0000000..eb3b859
--- /dev/null
+++ b/docs/html/wear/preview/images/apk-details.png
Binary files differ
diff --git a/docs/html/wear/preview/images/apk-tabs.png b/docs/html/wear/preview/images/apk-tabs.png
new file mode 100644
index 0000000..949b98f
--- /dev/null
+++ b/docs/html/wear/preview/images/apk-tabs.png
Binary files differ
diff --git a/docs/html/wear/preview/images/center_align.png b/docs/html/wear/preview/images/center_align.png
new file mode 100644
index 0000000..ca88ad7
--- /dev/null
+++ b/docs/html/wear/preview/images/center_align.png
Binary files differ
diff --git a/docs/html/wear/preview/images/current-apk.png b/docs/html/wear/preview/images/current-apk.png
new file mode 100644
index 0000000..2545f92
--- /dev/null
+++ b/docs/html/wear/preview/images/current-apk.png
Binary files differ
diff --git a/docs/html/wear/preview/images/inline_action.png b/docs/html/wear/preview/images/inline_action.png
new file mode 100644
index 0000000..7ecaafe
--- /dev/null
+++ b/docs/html/wear/preview/images/inline_action.png
Binary files differ
diff --git a/docs/html/wear/preview/images/wrv_new.png b/docs/html/wear/preview/images/wrv_new.png
new file mode 100644
index 0000000..c413c59
--- /dev/null
+++ b/docs/html/wear/preview/images/wrv_new.png
Binary files differ
diff --git a/docs/html/wear/preview/program.jd b/docs/html/wear/preview/program.jd
index e2bf92f..4f2fb5c 100644
--- a/docs/html/wear/preview/program.jd
+++ b/docs/html/wear/preview/program.jd
@@ -143,8 +143,9 @@
     <p>
       At milestone 4, you'll have access to the final Android Wear 2.0
       APIs and SDK to develop with, as well as near-final system images to test
-      system behaviors and features. Android Wear 2.0 will use the Android N
-      API level at this time. You can begin final compatibility testing of your
+      system behaviors and features. Android Wear 2.0 will use the
+      Android 7.0 API level at this time.
+      You can begin final compatibility testing of your
       legacy apps and refine any new code that is using the Android Wear 2.0
       APIs or features.
     </p>
diff --git a/docs/html/wear/preview/start.jd b/docs/html/wear/preview/start.jd
index 8fccdc8..c9720dc 100644
--- a/docs/html/wear/preview/start.jd
+++ b/docs/html/wear/preview/start.jd
@@ -29,7 +29,7 @@
 
     <p>
       If you want an environment for basic compatibility
-      testing of your app, you can use your current APK and a
+      testing, you can use your current APK and a
       supported watch or an emulator. You don't necessarily need to update your
       full development environment to do basic testing. To simply test your
       app's compatibility with a preview system image, see <a href=
@@ -48,10 +48,8 @@
     </h2>
 
     <p>
-      1. For compatibility with the <a href="{@docRoot}preview/overview.html">N
-      Developer Preview</a>, follow the <a href=
-      "{@docRoot}preview/setup-sdk.html">setup instructions</a> for installing
-      the latest version of Android Studio.
+      1. For compatibility with Android 7.0, install the latest version of
+      <a href="https://developer.android.com/studio/index.html">Android Studio</a>.
     </p>
 
     <p>
@@ -63,7 +61,7 @@
     <ul>
       <li>Under the <strong>SDK Platforms tab</strong>:
         <ul>
-          <li>Android N Preview
+          <li>Android 7.0 (Nougat)
           </li>
         </ul>
       </li>
@@ -107,10 +105,10 @@
 
       <tr>
         <td>
-          <a href="http://storage.googleapis.com/androiddevelopers/shareables/wear-preview/wearable-support-preview-2-docs.zip">wearable-support-preview-2-docs.zip</a>
+          <a href="http://storage.googleapis.com/androiddevelopers/shareables/wear-preview/wearable-support-preview-3-docs.zip">wearable-support-preview-3-docs.zip</a>
         </td>
-        <td>MD5: afb770c9c5c0431bbcbdde186f1eae06<br>
-            SHA-1: 81d681e61cee01f222ea82e83297d23c4e55b8f3
+        <td>MD5: 22bae00e473e39e320aae8ea09a001a5<br>
+            SHA-1: 474502cc7092bcf0bd671441b8654aa8d6c155ed
         </td>
       </tr>
     </table>
@@ -163,7 +161,7 @@
       following, which requires that your the Google Repository <a href=
       "#install_android_studio_and_the_latest_packages">is the latest
       version</a>:
-      <code>compile 'com.google.android.support:wearable:2.0.0-alpha2'</code>
+      <code>compile 'com.google.android.support:wearable:2.0.0-alpha3'</code>
         </li>
       </ul>
       </li>
@@ -190,12 +188,12 @@
       </li>
 
       <li>Optionally, select the <strong>Phone and Tablet</strong> option. If
-      you plan to use N Preview APIs in a phone app, then the Minimum SDK
-      option list, select <strong>API N: Android 6.x (N Preview)</strong>.
+      you plan to use Android 7.0 APIs in a phone app, then the Minimum SDK
+      option list, select <strong>API 24: Android 7.0 (Nougat)</strong>.
       </li>
 
       <li>Select the <strong>Wear</strong> option, and in the Minimum SDK
-      option list, select the latest available (<strong>N Preview</strong>)
+      option list, select the latest available (<strong>API Nougat</strong>)
       option. Click <strong>Next</strong> until you exit the Create New Project
       wizard.
       </li>
@@ -215,7 +213,7 @@
       following, which requires that your the Google Repository <a href=
       "#install_android_studio_and_the_latest_packages">is the latest
       version</a>:
-      <code>compile 'com.google.android.support:wearable:2.0.0-alpha2'</code>
+      <code>compile 'com.google.android.support:wearable:2.0.0-alpha3'</code>
         </li>
       </ul>
       </li>
diff --git a/docs/html/wear/preview/support.jd b/docs/html/wear/preview/support.jd
index 78b4e4b..6006627 100644
--- a/docs/html/wear/preview/support.jd
+++ b/docs/html/wear/preview/support.jd
@@ -23,7 +23,9 @@
 
 <ul>
   <li><a href="#general">General Advisories</a></li>
+  <li><a href="#platform-version">Platform API Version</a></li>
   <li><a href="#deprecations">Deprecations</a></li>
+  <li><a href="#dp3">Developer Preview 3</a></li>
   <li><a href="#dp2">Developer Preview 2</a></li>
   <li><a href="#dp1">Developer Preview 1</a></li>
 </ul>
@@ -46,10 +48,25 @@
     panics and crashes.
   </li>
   <li>Some apps <strong>may not function as expected</strong> on the new
-  platform version. This includes Google’s apps and other apps.
+  platform version. This includes Google's apps and other apps.
   </li>
 </ul>
 
+<h2 id="platform-version">
+  Platform API Version
+</h2>
+
+<p>
+  The Android Platform API version is incremented to 24 to match Android 7.0.
+  You can update the following in your Android Wear 2.0 Preview project
+  to <strong>24</strong>:
+</p>
+
+<ul>
+  <li><code>compileSdkVersion</code></li>
+  <li><code>targetSdkVersion</code></li>
+</ul>
+
 <h2 id="deprecations">Deprecations</h2>
 
 <p>The following fields are deprecated in the preview:</p>
@@ -64,6 +81,291 @@
   </li>
 </ul>
 
+<h2 id="dp3">Developer Preview 3</h2>
+
+<div class="wrap">
+  <div class="cols">
+    <div class="col-6of12">
+      <p><em>Date: September 2016<br />
+      Builds: Wearable Support 2.0.0-alpha3, NVE68J<br/>
+      Emulator support: x86 & ARM (32-bit)<br/>
+      </em></p>
+    </div>
+  </div>
+</div>
+
+<h3 id="new-in-fdp3">
+  New in Preview 3
+</h3>
+
+    <p>
+      For access to system images and the companion app for Preview 3, see
+      <a href="https://developer.android.com/wear/preview/downloads.html">
+      Download and Test with a Device</a>.
+    </p>
+
+    <h4>
+      Additions for standalone apps and the Play Store on Wear
+    </h4>
+
+    <p>
+      For information about planning your Wear 2.0 app, see <a href=
+      "https://developer.android.com/wear/preview/features/standalone-apps.html">
+      Standalone Apps</a>.
+    </p>
+
+    <p>
+      Generally, the minimum and target SDK level for Wear 2.0, and for a
+      standalone APK, is level 24. The minimum SDK level can be 23
+      only if you are using the same APK
+      for Wear 1.0 and 2.0 (and thus have an embedded Wear 1.0 APK).
+    </p>
+
+    <p>
+      Run-time permissions are required.
+    </p>
+
+    <p>
+      For information about distributing your Wear 2.0 app, see <a href=
+      "https://developer.android.com/wear/preview/features/app-distribution.html">
+      App Distribution</a>.
+    </p>
+
+    <h4 id="additions-to-the-complications-api">
+      Complications API additions
+    </h4>
+
+    <p>
+      For Preview 3, additions and changes have been made to the Complications
+      API. The <a href=
+      "https://developer.android.com/wear/preview/features/complications.html">documentation</a>
+      includes information about the following additions and changes:
+    </p>
+
+    <ul>
+      <li>To receive complication data and open the provider chooser, a watch
+      face must have the <code>RECEIVE_COMPLICATION_DATA</code> permission.
+      </li>
+
+      <li>To ease a request for the new permission and the starting of the
+      chooser, the <code>ComplicationHelperActivity</code> class is available
+      in the wearable support library. This class should be used instead of
+      <code>ProviderChooserIntent</code> to start the chooser in almost all
+      cases.
+      </li>
+
+      <li>Watch faces can specify default providers that are used until a user
+      selects a provider.
+      </li>
+
+      <li>The complication types used for "empty" data are changed.
+      </li>
+
+      <li>A new permission was added to ensure that only the Android Wear
+      system can bind to provider services.
+      </li>
+    </ul>
+
+    <p>
+      For changes related to the <code>ComplicationData</code> object, see
+      <a href=
+      "https://developer.android.com/wear/preview/behavior-changes.html">Behavior
+      Changes</a>.
+    </p>
+
+    <h4 id="wearable-recycler-view-api">
+      Curved Layout
+    </h4>
+
+    <p>
+      For information about creating a curved layout using
+      the <code>WearableRecyclerView</code> API in your Wear 2.0 app, see
+      <a href="https://developer.android.com/wear/preview/features/wearable-recycler-view.html">
+      Curved Layout</a>.
+    </p>
+
+    <h4 id="notifications-features-fdp3">
+      Notifications features
+    </h4>
+
+    <p>
+      To learn about adding an inline action to a notification,
+      see <a href="https://developer.android.com/wear/preview/notifications.html#inline">Inline
+      Action</a>.
+    </p>
+
+    <p>
+      To learn about adding images to a notification, see
+      <a href=
+      "https://developer.android.com/wear/preview/notifications.html#images">Adding
+      images to a notification</a>.
+    </p>
+
+    <p>
+      For additions related to the bridging of notifications from a companion
+      app to a watch, see <a href=
+      "https://developer.android.com/wear/preview/features/bridger.html">Bridging
+      Mode for Notifications</a>.
+    </p>
+
+    <h4 id="additions-for-smart-reply">
+      Smart Reply additions
+    </h4>
+
+    <p>
+      Smart Reply responses are generated by an entirely on-watch,
+      machine-learning model using the context provided by <a href=
+      "https://developer.android.com/wear/preview/features/notifications.html#messaging">
+      MessagingStyle</a> notifications. Use the <a href=
+      "https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Action.Builder.html#setAllowGeneratedReplies(boolean)">
+      setAllowGeneratedReplies(boolean)</a> method to enable Smart Reply for
+      your <code>MessagingStyle</code> notification.
+    </p>
+
+    <h3 id="known-issues-3">
+      Known Issues
+    </h3>
+
+    <h4 id="notifications">
+      Notifications
+    </h4>
+
+    <ul>
+      <li>The <code>MessagingStyle</code> <a href=
+      "https://developer.android.com/wear/preview/features/notifications.html#images">
+        notifications with images</a> posted by standalone apps don't show
+        images in the notification (i.e., bridged notifications show images,
+        but standalone notifications don't).
+      </li>
+
+      <li>This preview release does not include support for notification
+      groups.
+      </li>
+
+      <li>With Wear 2.0, a watch can receive notifications directly from
+      Firebase Cloud Messaging (FCM), which replaces Google Cloud Messaging
+      (GCM). However, in Preview 3 of Wear 2.0, FCM does not function with
+      iOS-paired watches.
+      </li>
+
+      <li>Smart Reply responses are only shown in <code>RemoteInput</code> when
+      <code>RemoteInput</code> is called from a <code>MessagingStyle</code>
+      expanded notification. Smart Reply responses are not shown in
+      <code>RemoteInput</code> when <code>RemoteInput</code> is called from an
+      <a href=
+      "https://developer.android.com/wear/preview/features/notifications.html#inline">
+        inline action</a> within the stream&#8212;an action set with the <a href=
+        "https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Action.WearableExtender.html#setHintDisplayActionInline(boolean)">
+        setHintDisplayActionInline(true)</a> method.
+      </li>
+    </ul>
+
+    <h4 id="companion-app">
+      Companion app
+    </h4>
+
+    <ul>
+      <li>The preview companion app is not compatible with Android 4.3
+      (Jelly Bean MR2), which has an SDK build version code of:
+      <code>JELLY_BEAN_MR2</code></li>
+    </ul>
+
+    <ul>
+      <li>In permission screens in the preview companion app:
+      If you deny a permission, you cannot
+      proceed. Instead of denying a permission, tap <strong>Skip</strong>.
+      </li>
+    </ul>
+
+
+    <h4 id="developer-console">
+      Developer Console
+    </h4>
+
+    <ul>
+      <li>If you set a minimum SDK version of 24, the Play Developer Console
+      states that there are few supported devices.
+      </li>
+    </ul>
+
+    <h4 id="system-user-interface">
+      System user interface and apps
+    </h4>
+
+    <ul>
+      <li>Dismissing multiple notifications can cause an app to forcibly close.
+      </li>
+
+      <li>The "Ok Google" detection and voice transcription may not work
+      reliably.
+      </li>
+
+      <li>Google Fit is not available with Preview 3.
+      </li>
+
+      <li>Syncing for embedded apps is not enabled for the preview. Therefore,
+      to test an app on a device, add it to the Play Store or side-load it
+      onto a watch. Some existing Wear apps, e.g. Google Maps, are only
+      using the embedded apps mechanism currently, and are therefore not
+      installable on the preview (and therefore do not appear on the watch).
+      </li>
+
+      <li>In Play Store search results on the watch,
+      results other than apps sometimes appear.
+      </li>
+
+      <li>Media controls/notifications are not bridged
+      to the watch from an Android KitKat phone.
+      </li>
+    </ul>
+
+    <h4 id="account">
+      Account sync
+    </h4>
+
+    <ul>
+      <li>Account sync initiated from watch settings may not work reliably.
+      Instead, add accounts from the setup flow of the Android Wear app, or using
+      the Accounts settings for a device from the Android Wear app.
+      </li>
+
+      <li>The list of accounts that can be synced is the same as the list of accounts
+      on the phone. So to add a new account, use the Android settings on the phone,
+      and then proceed to Android Wear app to sync that account.
+      </li>
+    </ul>
+
+    <h4 id="devices">
+      Devices
+    </h4>
+
+    <ul>
+      <li>In Android Wear emulators, the Play Store app requires that an
+      account is synced to the device before the app can be opened.
+      </li>
+
+      <li>On the Huawei Watch, selecting the language, followed by multiple
+      acknowledgement dialogues, results in a black screen.
+      </li>
+
+      <li>On the LG Watch Urbane 2nd Edition, when answering a call from the
+      watch, the watch does not provide audio from the caller.
+      </li>
+    </ul>
+
+    <h4 id="smart-reply">
+      Smart Reply
+    </h4>
+
+    <ul>
+      <li>Smart Reply is only available if your watch's system language is
+      English.
+      </li>
+
+      <li>Smart Reply responses are not generated for all messages.
+      </li>
+    </ul>
+
 <h2 id="dp2">Developer Preview 2</h2>
 
 <div class="wrap">
@@ -78,24 +380,9 @@
 </div>
 
 <h3 id="new-in-fdp2">
-  <strong>New in Preview 2</strong>
+  New in Preview 2
 </h3>
 
-<h4 id="platform-version-24">
-  Platform API Version
-</h4>
-
-<p>
-  The Android Platform API version is incremented to 24 to match Android Nougat.
-  You can update the following in your Android Wear 2.0 Preview project
-  to <strong>24</strong>:
-</p>
-
-<ul>
-  <li><code>compileSdkVersion</code></li>
-  <li><code>targetSdkVersion</code></li>
-</ul>
-
 <h4 id="wearable-drawers">
   Wearable drawers
 </h4>
@@ -174,7 +461,7 @@
 </p>
 
 <h3 id="known-issues-2">
-  <strong>Known Issues</strong>
+  Known Issues
 </h3>
 
 <h4 id="notifications-2">
@@ -239,6 +526,10 @@
 
   <li>Unable to turn off the Wi-Fi on a wearable.
   </li>
+
+  <li>After music is played on a companion phone,
+  music card notifications are not mirrored to the watch.
+  </li>
 </ul>
 
 <h4 id="companion-app-2">
diff --git a/docs/image_sources/brand/android_logo_no.graffle/data.plist b/docs/image_sources/brand/android_logo_no.graffle/data.plist
new file mode 100644
index 0000000..1132a59
--- /dev/null
+++ b/docs/image_sources/brand/android_logo_no.graffle/data.plist
Binary files differ
diff --git a/docs/image_sources/brand/android_logo_no.graffle/image1.jpg b/docs/image_sources/brand/android_logo_no.graffle/image1.jpg
new file mode 100644
index 0000000..ff29599
--- /dev/null
+++ b/docs/image_sources/brand/android_logo_no.graffle/image1.jpg
Binary files differ
diff --git a/docs/source.properties b/docs/source.properties
new file mode 100644
index 0000000..77a760b
--- /dev/null
+++ b/docs/source.properties
@@ -0,0 +1,3 @@
+Pkg.Revision=24.0
+Pkg.Desc=Android offline API reference
+Pkg.Path=docs
\ No newline at end of file
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index c386108..efb46b90 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -156,7 +156,6 @@
      * @param singleBufferMode whether the SurfaceTexture will be in single buffered mode.
      *
      * @throws Surface.OutOfResourcesException If the SurfaceTexture cannot be created.
-     * @hide
      */
     public SurfaceTexture(boolean singleBufferMode) {
         mCreatorLooper = Looper.myLooper();
diff --git a/include/androidfw/AssetManager.h b/include/androidfw/AssetManager.h
index 914ac3d..0b22802 100644
--- a/include/androidfw/AssetManager.h
+++ b/include/androidfw/AssetManager.h
@@ -72,6 +72,13 @@
     static const char* RESOURCES_FILENAME;
     static const char* IDMAP_BIN;
     static const char* OVERLAY_DIR;
+    /*
+     * If OVERLAY_SUBDIR_PROPERTY is set, search for runtime resource overlay
+     * APKs in OVERLAY_SUBDIR/<value of OVERLAY_SUBDIR_PROPERTY>/ rather than in
+     * OVERLAY_DIR.
+     */
+    static const char* OVERLAY_SUBDIR;
+    static const char* OVERLAY_SUBDIR_PROPERTY;
     static const char* TARGET_PACKAGE_NAME;
     static const char* TARGET_APK_PATH;
     static const char* IDMAP_DIR;
diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java
index d849317..d023866 100644
--- a/keystore/java/android/security/KeyPairGeneratorSpec.java
+++ b/keystore/java/android/security/KeyPairGeneratorSpec.java
@@ -251,8 +251,9 @@
     /**
      * Builder class for {@link KeyPairGeneratorSpec} objects.
      * <p>
-     * This will build a parameter spec for use with the <a href="{@docRoot}
-     * training/articles/keystore.html">Android KeyStore facility</a>.
+     * This will build a parameter spec for use with the
+     * <a href="{@docRoot}training/articles/keystore.html">Android KeyStore
+     * facility</a>.
      * <p>
      * The required fields must be filled in with the builder.
      * <p>
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 641a7ff..fe78cef 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -78,6 +78,8 @@
 const char* AssetManager::OVERLAY_DIR = "/vendor/overlay";
 const char* AssetManager::TARGET_PACKAGE_NAME = "android";
 const char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk";
+const char* AssetManager::OVERLAY_SUBDIR = "/system/vendor/overlay-subdir";
+const char* AssetManager::OVERLAY_SUBDIR_PROPERTY = "ro.boot.vendor.overlay.subdir";
 const char* AssetManager::IDMAP_DIR = "/data/resource-cache";
 
 namespace {
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 44d7010..eedc9e7 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -148,7 +148,7 @@
  * This will disable the use of EGL_EXT_buffer_age and BUFFER_PRESERVED.
  * Default is "true"
  */
-#define PROPERTY_ENABLE_PARTIAL_UPDATES "debug.hwui.enable_partial_updates"
+#define PROPERTY_ENABLE_PARTIAL_UPDATES "debug.hwui.use_partial_updates"
 
 #define PROPERTY_FILTER_TEST_OVERHEAD "debug.hwui.filter_test_overhead"
 
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index ac6a28f..86731c9 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -134,7 +134,12 @@
 void EglManager::initExtensions() {
     auto extensions = StringUtils::split(
             eglQueryString(mEglDisplay, EGL_EXTENSIONS));
-    EglExtensions.bufferAge = extensions.has("EGL_EXT_buffer_age");
+    // For our purposes we don't care if EGL_BUFFER_AGE is a result of
+    // EGL_EXT_buffer_age or EGL_KHR_partial_update as our usage is covered
+    // under EGL_KHR_partial_update and we don't need the expanded scope
+    // that EGL_EXT_buffer_age provides.
+    EglExtensions.bufferAge = extensions.has("EGL_EXT_buffer_age")
+            || extensions.has("EGL_KHR_partial_update");
     EglExtensions.setDamage = extensions.has("EGL_KHR_partial_update");
     LOG_ALWAYS_FATAL_IF(!extensions.has("EGL_KHR_swap_buffers_with_damage"),
             "Missing required extension EGL_KHR_swap_buffers_with_damage");
diff --git a/location/java/android/location/Address.java b/location/java/android/location/Address.java
index b152f48..335ad5e 100644
--- a/location/java/android/location/Address.java
+++ b/location/java/android/location/Address.java
@@ -28,7 +28,7 @@
 /**
  * A class representing an Address, i.e, a set of Strings describing a location.
  *
- * The addres format is a simplified version of xAL (eXtensible Address Language)
+ * The address format is a simplified version of xAL (eXtensible Address Language)
  * http://www.oasis-open.org/committees/ciq/ciq.html#6
  */
 public class Address implements Parcelable {
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 0c7fa8e..69710d6 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -1761,6 +1761,11 @@
      * copying all the data from one file to another and deleting the old file and renaming the
      * other. It's best to use {@link #setAttribute(String,String)} to set all attributes to write
      * and make a single call rather than multiple calls for each attribute.
+     * <p>
+     * This method is only supported for JPEG files.
+     * </p>
+     *
+     * @throws UnsupportedOperationException If this method is called with unsupported files.
      */
     public void saveAttributes() throws IOException {
         if (!mIsSupportedFile || mMimeType != IMAGE_TYPE_JPEG) {
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index bf1559d..82cf965 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityThread;
+import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
@@ -982,13 +983,16 @@
     public void setDataSource(@NonNull Context context, @NonNull Uri uri,
             @Nullable Map<String, String> headers) throws IOException, IllegalArgumentException,
                     SecurityException, IllegalStateException {
+        // The context and URI usually belong to the calling user. Get a resolver for that user
+        // and strip out the userId from the URI if present.
         final ContentResolver resolver = context.getContentResolver();
         final String scheme = uri.getScheme();
+        final String authority = ContentProvider.getAuthorityWithoutUserId(uri.getAuthority());
         if (ContentResolver.SCHEME_FILE.equals(scheme)) {
             setDataSource(uri.getPath());
             return;
         } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
-                && Settings.AUTHORITY.equals(uri.getAuthority())) {
+                && Settings.AUTHORITY.equals(authority)) {
             // Try cached ringtone first since the actual provider may not be
             // encryption aware, or it may be stored on CE media storage
             final int type = RingtoneManager.getDefaultType(uri);
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 96ea834..06dd3db 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -219,12 +219,25 @@
             }
 
             if (mBluetoothA2dpRoute != null) {
-                if (mSelectedRoute == mDefaultAudioVideo || mSelectedRoute == null) {
+                final boolean a2dpEnabled = isBluetoothA2dpOn();
+                if (mSelectedRoute == mBluetoothA2dpRoute && !a2dpEnabled) {
+                    selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo, false);
+                } else if ((mSelectedRoute == mDefaultAudioVideo || mSelectedRoute == null) &&
+                        a2dpEnabled) {
                     selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mBluetoothA2dpRoute, false);
                 }
             }
         }
 
+        boolean isBluetoothA2dpOn() {
+            try {
+                return mAudioService.isBluetoothA2dpOn();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error querying Bluetooth A2DP state", e);
+                return false;
+            }
+        }
+
         void updateDiscoveryRequest() {
             // What are we looking for today?
             int routeTypes = 0;
@@ -893,11 +906,6 @@
     static void selectRouteStatic(int types, @NonNull RouteInfo route, boolean explicit) {
         Log.v(TAG, "Selecting route: " + route);
         assert(route != null);
-        if (route == sStatic.mDefaultAudioVideo && sStatic.mBluetoothA2dpRoute != null) {
-            Log.i(TAG, "Change the route to a BT route: " + sStatic.mBluetoothA2dpRoute
-                    + "\nDo not select the default route when a BT route is available.");
-            route = sStatic.mBluetoothA2dpRoute;
-        }
         final RouteInfo oldRoute = sStatic.mSelectedRoute;
         if (oldRoute == route) return;
         if (!route.matchesTypes(types)) {
@@ -907,6 +915,16 @@
             return;
         }
 
+        final RouteInfo btRoute = sStatic.mBluetoothA2dpRoute;
+        if (btRoute != null && (types & ROUTE_TYPE_LIVE_AUDIO) != 0 &&
+                (route == btRoute || route == sStatic.mDefaultAudioVideo)) {
+            try {
+                sStatic.mAudioService.setBluetoothA2dpOn(route == btRoute);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error changing Bluetooth A2DP state", e);
+            }
+        }
+
         final WifiDisplay activeDisplay =
                 sStatic.mDisplayService.getWifiDisplayStatus().getActiveDisplay();
         final boolean oldRouteHasAddress = oldRoute != null && oldRoute.mDeviceAddress != null;
@@ -946,7 +964,7 @@
     static void selectDefaultRouteStatic() {
         // TODO: Be smarter about the route types here; this selects for all valid.
         if (sStatic.mSelectedRoute != sStatic.mBluetoothA2dpRoute
-                && sStatic.mBluetoothA2dpRoute != null) {
+                && sStatic.mBluetoothA2dpRoute != null && sStatic.isBluetoothA2dpOn()) {
             selectRouteStatic(ROUTE_TYPE_ANY, sStatic.mBluetoothA2dpRoute, false);
         } else {
             selectRouteStatic(ROUTE_TYPE_ANY, sStatic.mDefaultAudioVideo, false);
@@ -1278,7 +1296,12 @@
                 selectedRoute == sStatic.mDefaultAudioVideo) {
             dispatchRouteVolumeChanged(selectedRoute);
         } else if (sStatic.mBluetoothA2dpRoute != null) {
-            dispatchRouteVolumeChanged(sStatic.mBluetoothA2dpRoute);
+            try {
+                dispatchRouteVolumeChanged(sStatic.mAudioService.isBluetoothA2dpOn() ?
+                        sStatic.mBluetoothA2dpRoute : sStatic.mDefaultAudioVideo);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error checking Bluetooth A2DP state to report volume change", e);
+            }
         } else {
             dispatchRouteVolumeChanged(sStatic.mDefaultAudioVideo);
         }
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 664765a..3cb01de 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -727,7 +727,9 @@
 
         String setting = getSettingForType(type);
         if (setting == null) return;
-        ringtoneUri = ContentProvider.maybeAddUserId(ringtoneUri, context.getUserId());
+        if(!isInternalRingtoneUri(ringtoneUri)) {
+            ringtoneUri = ContentProvider.maybeAddUserId(ringtoneUri, context.getUserId());
+        }
         Settings.System.putStringForUser(resolver, setting,
                 ringtoneUri != null ? ringtoneUri.toString() : null, context.getUserId());
 
@@ -744,6 +746,12 @@
         }
     }
 
+    private static boolean isInternalRingtoneUri(Uri uri) {
+        Uri uriWithoutUserId = ContentProvider.getUriWithoutUserId(uri);
+        return uriWithoutUserId == null ? false : uriWithoutUserId.toString()
+                        .startsWith(MediaStore.Audio.Media.INTERNAL_CONTENT_URI.toString());
+    }
+
     /**
      * Try opening the given ringtone locally first, but failover to
      * {@link IRingtonePlayer} if we can't access it directly. Typically happens
@@ -816,6 +824,7 @@
      * @return The type of the defaultRingtoneUri, or -1.
      */
     public static int getDefaultType(Uri defaultRingtoneUri) {
+        defaultRingtoneUri = ContentProvider.getUriWithoutUserId(defaultRingtoneUri);
         if (defaultRingtoneUri == null) {
             return -1;
         } else if (defaultRingtoneUri.equals(Settings.System.DEFAULT_RINGTONE_URI)) {
diff --git a/media/java/android/media/midi/MidiDeviceInfo.aidl b/media/java/android/media/midi/MidiDeviceInfo.aidl
index f2f37a2..5b2ac9b 100644
--- a/media/java/android/media/midi/MidiDeviceInfo.aidl
+++ b/media/java/android/media/midi/MidiDeviceInfo.aidl
@@ -16,4 +16,4 @@
 
 package android.media.midi;
 
-parcelable MidiDeviceInfo;
+parcelable MidiDeviceInfo cpp_header "media/MidiDeviceInfo.h";
diff --git a/media/java/android/media/midi/MidiDeviceInfo.java b/media/java/android/media/midi/MidiDeviceInfo.java
index a59be54..66d1ed7 100644
--- a/media/java/android/media/midi/MidiDeviceInfo.java
+++ b/media/java/android/media/midi/MidiDeviceInfo.java
@@ -32,6 +32,11 @@
 
     private static final String TAG = "MidiDeviceInfo";
 
+    /*
+     * Please note that constants and (un)marshalling code need to be kept in sync
+     * with the native implementation (MidiDeviceInfo.h|cpp)
+     */
+
     /**
      * Constant representing USB MIDI devices for {@link #getType}
      */
@@ -321,15 +326,17 @@
     public static final Parcelable.Creator<MidiDeviceInfo> CREATOR =
         new Parcelable.Creator<MidiDeviceInfo>() {
         public MidiDeviceInfo createFromParcel(Parcel in) {
+            // Needs to be kept in sync with code in MidiDeviceInfo.cpp
             int type = in.readInt();
             int id = in.readInt();
-            int inputPorts = in.readInt();
-            int outputPorts = in.readInt();
+            int inputPortCount = in.readInt();
+            int outputPortCount = in.readInt();
             String[] inputPortNames = in.createStringArray();
             String[] outputPortNames = in.createStringArray();
-            Bundle properties = in.readBundle();
             boolean isPrivate = (in.readInt() == 1);
-            return new MidiDeviceInfo(type, id, inputPorts, outputPorts,
+            Bundle basicPropertiesIgnored = in.readBundle();
+            Bundle properties = in.readBundle();
+            return new MidiDeviceInfo(type, id, inputPortCount, outputPortCount,
                     inputPortNames, outputPortNames, properties, isPrivate);
         }
 
@@ -342,14 +349,34 @@
         return 0;
     }
 
+    private Bundle getBasicProperties(String[] keys) {
+        Bundle basicProperties = new Bundle();
+        for (String key : keys) {
+            String val = mProperties.getString(key);
+            if (val != null) {
+                basicProperties.putString(key, val);
+            }
+        }
+        return basicProperties;
+    }
+
     public void writeToParcel(Parcel parcel, int flags) {
+        // Needs to be kept in sync with code in MidiDeviceInfo.cpp
         parcel.writeInt(mType);
         parcel.writeInt(mId);
         parcel.writeInt(mInputPortCount);
         parcel.writeInt(mOutputPortCount);
         parcel.writeStringArray(mInputPortNames);
         parcel.writeStringArray(mOutputPortNames);
-        parcel.writeBundle(mProperties);
         parcel.writeInt(mIsPrivate ? 1 : 0);
+        // "Basic" properties only contain properties of primitive types
+        // and thus can be read back by native code. "Extra" properties is
+        // a superset that contains all properties.
+        parcel.writeBundle(getBasicProperties(new String[] {
+            PROPERTY_NAME, PROPERTY_MANUFACTURER, PROPERTY_PRODUCT, PROPERTY_VERSION,
+            PROPERTY_SERIAL_NUMBER, PROPERTY_ALSA_CARD, PROPERTY_ALSA_DEVICE
+        }));
+        // Must be serialized last so native code can safely ignore it.
+        parcel.writeBundle(mProperties);
    }
 }
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 810996e..c2c66fd 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -32,6 +32,7 @@
 #include <gui/Surface.h>
 
 #include <media/ICrypto.h>
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/MediaCodec.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -407,7 +408,7 @@
 
 status_t JMediaCodec::getBuffers(
         JNIEnv *env, bool input, jobjectArray *bufArray) const {
-    Vector<sp<ABuffer> > buffers;
+    Vector<sp<MediaCodecBuffer> > buffers;
 
     status_t err =
         input
@@ -425,7 +426,7 @@
     }
 
     for (size_t i = 0; i < buffers.size(); ++i) {
-        const sp<ABuffer> &buffer = buffers.itemAt(i);
+        const sp<MediaCodecBuffer> &buffer = buffers.itemAt(i);
 
         jobject byteBuffer = NULL;
         err = createByteBufferFromABuffer(
@@ -446,8 +447,9 @@
 }
 
 // static
+template <typename T>
 status_t JMediaCodec::createByteBufferFromABuffer(
-        JNIEnv *env, bool readOnly, bool clearBuffer, const sp<ABuffer> &buffer,
+        JNIEnv *env, bool readOnly, bool clearBuffer, const sp<T> &buffer,
         jobject *buf) const {
     // if this is an ABuffer that doesn't actually hold any accessible memory,
     // use a null ByteBuffer
@@ -492,7 +494,7 @@
 
 status_t JMediaCodec::getBuffer(
         JNIEnv *env, bool input, size_t index, jobject *buf) const {
-    sp<ABuffer> buffer;
+    sp<MediaCodecBuffer> buffer;
 
     status_t err =
         input
@@ -509,7 +511,7 @@
 
 status_t JMediaCodec::getImage(
         JNIEnv *env, bool input, size_t index, jobject *buf) const {
-    sp<ABuffer> buffer;
+    sp<MediaCodecBuffer> buffer;
 
     status_t err =
         input
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index c0c47ef..88b566a 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -146,8 +146,9 @@
 
     status_t mInitStatus;
 
+    template <typename T>
     status_t createByteBufferFromABuffer(
-            JNIEnv *env, bool readOnly, bool clearBuffer, const sp<ABuffer> &buffer,
+            JNIEnv *env, bool readOnly, bool clearBuffer, const sp<T> &buffer,
             jobject *buf) const;
 
     void cacheJavaObjects(JNIEnv *env);
diff --git a/native/android/Android.bp b/native/android/Android.bp
new file mode 100644
index 0000000..33c9655
--- /dev/null
+++ b/native/android/Android.bp
@@ -0,0 +1,20 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// The headers module is in frameworks/native/Android.bp.
+ndk_library {
+    name: "libandroid.ndk",
+    symbol_file: "libandroid.map.txt",
+    first_version: "9",
+}
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
new file mode 100644
index 0000000..5758a3c
--- /dev/null
+++ b/native/android/libandroid.map.txt
@@ -0,0 +1,194 @@
+LIBANDROID {
+  global:
+    AAssetDir_close;
+    AAssetDir_getNextFileName;
+    AAssetDir_rewind;
+    AAssetManager_fromJava;
+    AAssetManager_open;
+    AAssetManager_openDir;
+    AAsset_close;
+    AAsset_getBuffer;
+    AAsset_getLength;
+    AAsset_getLength64; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
+    AAsset_getRemainingLength;
+    AAsset_getRemainingLength64; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
+    AAsset_isAllocated;
+    AAsset_openFileDescriptor;
+    AAsset_openFileDescriptor64; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
+    AAsset_read;
+    AAsset_seek;
+    AAsset_seek64; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
+    AChoreographer_getInstance; # introduced=24
+    AChoreographer_postFrameCallback; # introduced=24
+    AChoreographer_postFrameCallbackDelayed; # introduced=24
+    AConfiguration_copy;
+    AConfiguration_delete;
+    AConfiguration_diff;
+    AConfiguration_fromAssetManager;
+    AConfiguration_getCountry;
+    AConfiguration_getDensity;
+    AConfiguration_getKeyboard;
+    AConfiguration_getKeysHidden;
+    AConfiguration_getLanguage;
+    AConfiguration_getLayoutDirection; # introduced-arm=17 introduced-arm64=21 introduced-mips=17 introduced-mips64=21 introduced-x86=17 introduced-x86_64=21
+    AConfiguration_getMcc;
+    AConfiguration_getMnc;
+    AConfiguration_getNavHidden;
+    AConfiguration_getNavigation;
+    AConfiguration_getOrientation;
+    AConfiguration_getScreenHeightDp; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
+    AConfiguration_getScreenLong;
+    AConfiguration_getScreenSize;
+    AConfiguration_getScreenWidthDp; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
+    AConfiguration_getSdkVersion;
+    AConfiguration_getSmallestScreenWidthDp; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
+    AConfiguration_getTouchscreen;
+    AConfiguration_getUiModeNight;
+    AConfiguration_getUiModeType;
+    AConfiguration_isBetterThan;
+    AConfiguration_match;
+    AConfiguration_new;
+    AConfiguration_setCountry;
+    AConfiguration_setDensity;
+    AConfiguration_setKeyboard;
+    AConfiguration_setKeysHidden;
+    AConfiguration_setLanguage;
+    AConfiguration_setLayoutDirection; # introduced-arm=17 introduced-arm64=21 introduced-mips=17 introduced-mips64=21 introduced-x86=17 introduced-x86_64=21
+    AConfiguration_setMcc;
+    AConfiguration_setMnc;
+    AConfiguration_setNavHidden;
+    AConfiguration_setNavigation;
+    AConfiguration_setOrientation;
+    AConfiguration_setScreenHeightDp; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
+    AConfiguration_setScreenLong;
+    AConfiguration_setScreenSize;
+    AConfiguration_setScreenWidthDp; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
+    AConfiguration_setSdkVersion;
+    AConfiguration_setSmallestScreenWidthDp; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
+    AConfiguration_setTouchscreen;
+    AConfiguration_setUiModeNight;
+    AConfiguration_setUiModeType;
+    AInputEvent_getDeviceId;
+    AInputEvent_getSource;
+    AInputEvent_getType;
+    AInputQueue_attachLooper;
+    AInputQueue_detachLooper;
+    AInputQueue_finishEvent;
+    AInputQueue_getEvent;
+    AInputQueue_hasEvents;
+    AInputQueue_preDispatchEvent;
+    AKeyEvent_getAction;
+    AKeyEvent_getDownTime;
+    AKeyEvent_getEventTime;
+    AKeyEvent_getFlags;
+    AKeyEvent_getKeyCode;
+    AKeyEvent_getMetaState;
+    AKeyEvent_getRepeatCount;
+    AKeyEvent_getScanCode;
+    ALooper_acquire;
+    ALooper_addFd;
+    ALooper_forThread;
+    ALooper_pollAll;
+    ALooper_pollOnce;
+    ALooper_prepare;
+    ALooper_release;
+    ALooper_removeFd;
+    ALooper_wake;
+    AMotionEvent_getAction;
+    AMotionEvent_getAxisValue; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
+    AMotionEvent_getButtonState; # introduced-arm=14 introduced-arm64=21 introduced-mips=14 introduced-mips64=21 introduced-x86=14 introduced-x86_64=21
+    AMotionEvent_getDownTime;
+    AMotionEvent_getEdgeFlags;
+    AMotionEvent_getEventTime;
+    AMotionEvent_getFlags;
+    AMotionEvent_getHistoricalAxisValue; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
+    AMotionEvent_getHistoricalEventTime;
+    AMotionEvent_getHistoricalOrientation;
+    AMotionEvent_getHistoricalPressure;
+    AMotionEvent_getHistoricalRawX;
+    AMotionEvent_getHistoricalRawY;
+    AMotionEvent_getHistoricalSize;
+    AMotionEvent_getHistoricalToolMajor;
+    AMotionEvent_getHistoricalToolMinor;
+    AMotionEvent_getHistoricalTouchMajor;
+    AMotionEvent_getHistoricalTouchMinor;
+    AMotionEvent_getHistoricalX;
+    AMotionEvent_getHistoricalY;
+    AMotionEvent_getHistorySize;
+    AMotionEvent_getMetaState;
+    AMotionEvent_getOrientation;
+    AMotionEvent_getPointerCount;
+    AMotionEvent_getPointerId;
+    AMotionEvent_getPressure;
+    AMotionEvent_getRawX;
+    AMotionEvent_getRawY;
+    AMotionEvent_getSize;
+    AMotionEvent_getToolMajor;
+    AMotionEvent_getToolMinor;
+    AMotionEvent_getToolType; # introduced-arm=14 introduced-arm64=21 introduced-mips=14 introduced-mips64=21 introduced-x86=14 introduced-x86_64=21
+    AMotionEvent_getTouchMajor;
+    AMotionEvent_getTouchMinor;
+    AMotionEvent_getX;
+    AMotionEvent_getXOffset;
+    AMotionEvent_getXPrecision;
+    AMotionEvent_getY;
+    AMotionEvent_getYOffset;
+    AMotionEvent_getYPrecision;
+    ANativeActivity_finish;
+    ANativeActivity_hideSoftInput;
+    ANativeActivity_setWindowFlags;
+    ANativeActivity_setWindowFormat;
+    ANativeActivity_showSoftInput;
+    ANativeWindow_acquire;
+    ANativeWindow_fromSurface;
+    ANativeWindow_fromSurfaceTexture; # introduced-arm=13 introduced-mips=13 introduced-x86=13
+    ANativeWindow_getFormat;
+    ANativeWindow_getHeight;
+    ANativeWindow_getWidth;
+    ANativeWindow_lock;
+    ANativeWindow_release;
+    ANativeWindow_setBuffersGeometry;
+    ANativeWindow_unlockAndPost;
+    AObbInfo_delete;
+    AObbInfo_getFlags;
+    AObbInfo_getPackageName;
+    AObbInfo_getVersion;
+    AObbScanner_getObbInfo;
+    ASensorEventQueue_disableSensor;
+    ASensorEventQueue_enableSensor;
+    ASensorEventQueue_getEvents;
+    ASensorEventQueue_hasEvents;
+    ASensorEventQueue_setEventRate;
+    ASensorManager_createEventQueue;
+    ASensorManager_destroyEventQueue;
+    ASensorManager_getDefaultSensor;
+    ASensorManager_getDefaultSensorEx; # introduced=21
+    ASensorManager_getInstance;
+    ASensorManager_getSensorList;
+    ASensor_getFifoMaxEventCount; # introduced=21
+    ASensor_getFifoReservedEventCount; # introduced=21
+    ASensor_getMinDelay;
+    ASensor_getName;
+    ASensor_getReportingMode; # introduced=21
+    ASensor_getResolution;
+    ASensor_getStringType; # introduced=21
+    ASensor_getType;
+    ASensor_getVendor;
+    ASensor_isWakeUpSensor; # introduced=21
+    AStorageManager_delete;
+    AStorageManager_getMountedObbPath;
+    AStorageManager_isObbMounted;
+    AStorageManager_mountObb;
+    AStorageManager_new;
+    AStorageManager_unmountObb;
+    ATrace_beginSection; # introduced=23
+    ATrace_endSection; # introduced=23
+    ATrace_isEnabled; # introduced=23
+    android_getTtsEngine; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
+    android_getaddrinfofornetwork; # introduced=23
+    android_setprocnetwork; # introduced=23
+    android_setsocknetwork; # introduced=23
+    getTtsEngine; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
+  local:
+    *;
+};
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
new file mode 100644
index 0000000..e09b0b4
--- /dev/null
+++ b/native/graphics/jni/Android.bp
@@ -0,0 +1,20 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// The headers module is in frameworks/native/Android.bp.
+ndk_library {
+    name: "libjnigraphics.ndk",
+    symbol_file: "libjnigraphics.map.txt",
+    first_version: "9",
+}
diff --git a/native/graphics/jni/libjnigraphics.map.txt b/native/graphics/jni/libjnigraphics.map.txt
new file mode 100644
index 0000000..a601d8a
--- /dev/null
+++ b/native/graphics/jni/libjnigraphics.map.txt
@@ -0,0 +1,8 @@
+LIBJNIGRAPHICS {
+  global:
+    AndroidBitmap_getInfo;
+    AndroidBitmap_lockPixels;
+    AndroidBitmap_unlockPixels;
+  local:
+    *;
+};
diff --git a/packages/ExternalStorageProvider/Android.mk b/packages/ExternalStorageProvider/Android.mk
index ec6af2f..db825ff4 100644
--- a/packages/ExternalStorageProvider/Android.mk
+++ b/packages/ExternalStorageProvider/Android.mk
@@ -5,7 +5,6 @@
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-documents-archive
 LOCAL_PACKAGE_NAME := ExternalStorageProvider
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 1fe88f0..33d6b9a 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -44,7 +44,6 @@
 import android.provider.DocumentsProvider;
 import android.provider.MediaStore;
 import android.provider.Settings;
-import android.support.provider.DocumentArchiveHelper;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.DebugUtils;
@@ -101,7 +100,6 @@
 
     private StorageManager mStorageManager;
     private Handler mHandler;
-    private DocumentArchiveHelper mArchiveHelper;
 
     private final Object mRootsLock = new Object();
 
@@ -115,7 +113,6 @@
     public boolean onCreate() {
         mStorageManager = (StorageManager) getContext().getSystemService(Context.STORAGE_SERVICE);
         mHandler = new Handler();
-        mArchiveHelper = new DocumentArchiveHelper(this, (char) 0);
 
         updateVolumes();
         return true;
@@ -377,10 +374,6 @@
         }
 
         final String mimeType = getTypeForFile(file);
-        if (mArchiveHelper.isSupportedArchiveType(mimeType)) {
-            flags |= Document.FLAG_ARCHIVE;
-        }
-
         final String displayName = file.getName();
         if (mimeType.startsWith("image/")) {
             flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
@@ -392,7 +385,6 @@
         row.add(Document.COLUMN_SIZE, file.length());
         row.add(Document.COLUMN_MIME_TYPE, mimeType);
         row.add(Document.COLUMN_FLAGS, flags);
-        row.add(DocumentArchiveHelper.COLUMN_LOCAL_FILE_PATH, file.getPath());
 
         // Only publish dates reasonably after epoch
         long lastModified = file.lastModified();
@@ -421,14 +413,6 @@
     @Override
     public boolean isChildDocument(String parentDocId, String docId) {
         try {
-            if (mArchiveHelper.isArchivedDocument(docId)) {
-                return mArchiveHelper.isChildDocument(parentDocId, docId);
-            }
-            // Archives do not contain regular files.
-            if (mArchiveHelper.isArchivedDocument(parentDocId)) {
-                return false;
-            }
-
             final File parent = getFileForDocId(parentDocId).getCanonicalFile();
             final File doc = getFileForDocId(docId).getCanonicalFile();
             return FileUtils.contains(parent, doc);
@@ -538,10 +522,6 @@
     @Override
     public Cursor queryDocument(String documentId, String[] projection)
             throws FileNotFoundException {
-        if (mArchiveHelper.isArchivedDocument(documentId)) {
-            return mArchiveHelper.queryDocument(documentId, projection);
-        }
-
         final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
         includeFile(result, documentId, null);
         return result;
@@ -551,11 +531,6 @@
     public Cursor queryChildDocuments(
             String parentDocumentId, String[] projection, String sortOrder)
             throws FileNotFoundException {
-        if (mArchiveHelper.isArchivedDocument(parentDocumentId) ||
-                mArchiveHelper.isSupportedArchiveType(getDocumentType(parentDocumentId))) {
-            return mArchiveHelper.queryChildDocuments(parentDocumentId, projection, sortOrder);
-        }
-
         final File parent = getFileForDocId(parentDocumentId);
         final MatrixCursor result = new DirectoryCursor(
                 resolveDocumentProjection(projection), parentDocumentId, parent);
@@ -612,10 +587,6 @@
 
     @Override
     public String getDocumentType(String documentId) throws FileNotFoundException {
-        if (mArchiveHelper.isArchivedDocument(documentId)) {
-            return mArchiveHelper.getDocumentType(documentId);
-        }
-
         final File file = getFileForDocId(documentId);
         return getTypeForFile(file);
     }
@@ -624,10 +595,6 @@
     public ParcelFileDescriptor openDocument(
             String documentId, String mode, CancellationSignal signal)
             throws FileNotFoundException {
-        if (mArchiveHelper.isArchivedDocument(documentId)) {
-            return mArchiveHelper.openDocument(documentId, mode, signal);
-        }
-
         final File file = getFileForDocId(documentId);
         final File visibleFile = getFileForDocId(documentId, true);
 
@@ -656,10 +623,6 @@
     public AssetFileDescriptor openDocumentThumbnail(
             String documentId, Point sizeHint, CancellationSignal signal)
             throws FileNotFoundException {
-        if (mArchiveHelper.isArchivedDocument(documentId)) {
-            return mArchiveHelper.openDocumentThumbnail(documentId, sizeHint, signal);
-        }
-
         final File file = getFileForDocId(documentId);
         return DocumentsContract.openImageThumbnail(file);
     }
diff --git a/packages/Keyguard/res/values-sv/strings.xml b/packages/Keyguard/res/values-sv/strings.xml
index 527c8e6..4a1d67b 100644
--- a/packages/Keyguard/res/values-sv/strings.xml
+++ b/packages/Keyguard/res/values-sv/strings.xml
@@ -34,7 +34,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="6671162730167305479">"Laddas snabbt"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="1964714661071163229">"Laddas långsamt"</string>
     <string name="keyguard_low_battery" msgid="8143808018719173859">"Anslut din laddare."</string>
-    <string name="keyguard_instructions_when_pattern_disabled" msgid="1332288268600329841">"Tryck på Meny om du vill låsa upp."</string>
+    <string name="keyguard_instructions_when_pattern_disabled" msgid="1332288268600329841">"Tryck på Meny för att låsa upp."</string>
     <string name="keyguard_network_locked_message" msgid="9169717779058037168">"Nätverk låst"</string>
     <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"Inget SIM-kort"</string>
     <string name="keyguard_missing_sim_message" product="tablet" msgid="1445849005909260039">"Inget SIM-kort i surfplattan."</string>
diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
index 8d41145..0474df7 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -28,13 +28,16 @@
 import android.telecom.TelecomManager;
 import android.util.AttributeSet;
 import android.util.Slog;
+import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.widget.Button;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.internal.telephony.IccCardConstants.State;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.policy.EmergencyAffordanceManager;
 
 /**
  * This class implements a smart emergency button that updates itself based
@@ -51,7 +54,10 @@
                     | Intent.FLAG_ACTIVITY_CLEAR_TOP);
 
     private static final String LOG_TAG = "EmergencyButton";
+    private final EmergencyAffordanceManager mEmergencyAffordanceManager;
 
+    private int mDownX;
+    private int mDownY;
     KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
 
         @Override
@@ -64,6 +70,7 @@
             updateEmergencyCallButton();
         }
     };
+    private boolean mLongPressWasDragged;
 
     public interface EmergencyButtonCallback {
         public void onEmergencyButtonClickedWhenInCall();
@@ -86,6 +93,7 @@
                 com.android.internal.R.bool.config_voice_capable);
         mEnableEmergencyCallWhileSimLocked = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked);
+        mEmergencyAffordanceManager = new EmergencyAffordanceManager(context);
     }
 
     @Override
@@ -110,10 +118,45 @@
                 takeEmergencyCallAction();
             }
         });
+        setOnLongClickListener(new OnLongClickListener() {
+            @Override
+            public boolean onLongClick(View v) {
+                if (!mLongPressWasDragged
+                        && mEmergencyAffordanceManager.needsEmergencyAffordance()) {
+                    mEmergencyAffordanceManager.performEmergencyCall();
+                    return true;
+                }
+                return false;
+            }
+        });
         updateEmergencyCallButton();
     }
 
     @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        final int x = (int) event.getX();
+        final int y = (int) event.getY();
+        if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+            mDownX = x;
+            mDownY = y;
+            mLongPressWasDragged = false;
+        } else {
+            final int xDiff = Math.abs(x - mDownX);
+            final int yDiff = Math.abs(y - mDownY);
+            int touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+            if (Math.abs(yDiff) > touchSlop || Math.abs(xDiff) > touchSlop) {
+                mLongPressWasDragged = true;
+            }
+        }
+        return super.onTouchEvent(event);
+    }
+
+    @Override
+    public boolean performLongClick() {
+        return super.performLongClick();
+    }
+
+    @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
         updateEmergencyCallButton();
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 66e1b27..288b954 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -29,8 +29,8 @@
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.AlarmManager;
-import android.app.IUserSwitchObserver;
 import android.app.PendingIntent;
+import android.app.UserSwitchObserver;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
 import android.content.BroadcastReceiver;
@@ -384,7 +384,7 @@
     }
 
     /** @return List of SubscriptionInfo records, maybe empty but never null */
-    List<SubscriptionInfo> getSubscriptionInfo(boolean forceReload) {
+    public List<SubscriptionInfo> getSubscriptionInfo(boolean forceReload) {
         List<SubscriptionInfo> sil = mSubscriptionInfo;
         if (sil == null || forceReload) {
             sil = mSubscriptionManager.getActiveSubscriptionInfoList();
@@ -1071,7 +1071,7 @@
         mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
         try {
             ActivityManagerNative.getDefault().registerUserSwitchObserver(
-                    new IUserSwitchObserver.Stub() {
+                    new UserSwitchObserver() {
                         @Override
                         public void onUserSwitching(int newUserId, IRemoteCallback reply) {
                             mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
@@ -1082,10 +1082,6 @@
                             mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
                                     newUserId, 0));
                         }
-                        @Override
-                        public void onForegroundProfileSwitch(int newProfileId) {
-                            // Ignore.
-                        }
                     }, TAG);
         } catch (RemoteException e) {
             e.rethrowAsRuntimeException();
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index f688a8e..b3cfea5 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -760,6 +760,10 @@
                 mPrintJob.setPrinterId(printerInfo.getId());
                 mPrintJob.setPrinterName(printerInfo.getName());
 
+                if (printerInfo.getCapabilities() != null) {
+                    updatePrintAttributesFromCapabilities(printerInfo.getCapabilities());
+                }
+
                 mDestinationSpinnerAdapter.ensurePrinterInVisibleAdapterPosition(printerInfo);
 
                 MetricsLogger.action(this, MetricsEvent.ACTION_PRINTER_SELECT_ALL,
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 11235ef..81af941 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi-verbinding het misluk"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Stawingsprobleem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Nie binne ontvangs nie"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Geen internettoegang bespeur nie, sal nie outomaties herkoppel nie."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Gestoor deur <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Gekoppel via Wi-Fi-assistent"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Gekoppel via %1$s"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index dbfd5d8..792c434 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"የWiFi ግንኙነት መሰናከል"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"የማረጋገጫ ችግር"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"በክልል ውስጥ የለም"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"ምንም የበይነ መረብ መዳረሻ ተፈልጎ አልተገኘም፣ በራስ-ሰር እንደገና እንዲገናኝ አይደረግም።"</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"የተቀመጠው በ<xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"በWi‑Fi ረዳት አማካኝነት ተገናኝቷል"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"በ%1$s በኩል መገናኘት"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index fc45a6e..db9afee 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"‏أخفق اتصال WiFi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"حدثت مشكلة في المصادقة"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"ليست في النطاق"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"لم يتم اكتشاف اتصال بالإنترنت."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"تم الحفظ بواسطة <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"‏تم التوصيل عبر مساعد Wi-Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"‏تم الاتصال عبر %1$s"</string>
diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml
index 2e58ae9..130cd75 100644
--- a/packages/SettingsLib/res/values-az-rAZ/strings.xml
+++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi Bağlantı Uğursuzluğu"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Autentifikasiya problemi"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Diapazonda deyil"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"İnternet bağlantısı tapılmadı, avtomatik olaraq yenidən qoşulmayacaq."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> tərəfindən saxlandı"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Wi‑Fi köməkçisi vasitəsilə qoşulub"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s vasitəsilə qoşuludur"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 1f0ed53..5d7e852 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi veza je otkazala"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem sa potvrdom autentičnosti"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Nije u opsegu"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Pristup internetu nije otkriven, automatsko povezivanje nije moguće."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Sačuvao/la je <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Povezano preko Wi‑Fi pomoćnika"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Veza je uspostavljena preko pristupne tačke %1$s"</string>
diff --git a/packages/SettingsLib/res/values-be-rBY/strings.xml b/packages/SettingsLib/res/values-be-rBY/strings.xml
index b8de297..a8428f2 100644
--- a/packages/SettingsLib/res/values-be-rBY/strings.xml
+++ b/packages/SettingsLib/res/values-be-rBY/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Збой падлучэння Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Праблема аўтэнтыфікацыі"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Не ў зоне дасягальнасці"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Доступ да інтэрнэту не выяўлены, аўтаматычнае перападлучэнне не адбудзецца."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Хто захаваў: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Падлучана праз памочніка Wi‑Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Падлучана праз %1$s"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 683a4d9..b356766 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Неуспешна връзка с Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Проблем при удостоверяването"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Извън обхват"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Не е открит достъп до интернет. Няма да се свърже отново автоматично."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Запазено от <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Установена е връзка чрез помощника за Wi-Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Установена е връзка през „%1$s“"</string>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index 9ba656f..4089562 100644
--- a/packages/SettingsLib/res/values-bn-rBD/strings.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi সংযোগের ব্যর্থতা"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"প্রমাণীকরণ সমস্যা"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"পরিসরের মধ্যে নয়"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"কোনো ইন্টারনেট অ্যাক্সেস শনাক্ত হয়নি, স্বয়ংক্রিয়ভাবে পুনরায় সংযোগ স্থাপন করবে না৷"</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> দ্বারা সংরক্ষিত"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"ওয়াই-ফাই সহায়ক-এর মাধ্যমে সংযুক্ত হয়েছে"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s মাধ্যমে সংযুক্ত হয়েছে"</string>
diff --git a/packages/SettingsLib/res/values-bs-rBA/strings.xml b/packages/SettingsLib/res/values-bs-rBA/strings.xml
index f2c7323..5115bbd 100644
--- a/packages/SettingsLib/res/values-bs-rBA/strings.xml
+++ b/packages/SettingsLib/res/values-bs-rBA/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Greška pri povezivanju na Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem pri provjeri vjerodostojnosti."</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Nije u dometu"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Pristup internetu nije pronađen. Neće se ponovo povezivati automatski."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Sačuvao <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Povezani preko Wi-Fi pomoćnika"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Povezani preko %1$s"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 332daf3..abc9390 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Error de connexió Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problema d\'autenticació"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Fora de l\'abast"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"No s\'ha detectat accés a Internet, no s\'hi tornarà a connectar automàticament."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Desat per <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Connectat mitjançant l\'assistent de Wi‑Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Connectada mitjançant %1$s"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index d0dbe74..edc53ed 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Selhání připojení Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problém s ověřením"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Mimo dosah"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Nebyl zjištěn žádný přístup k internetu, připojení nebude automaticky obnoveno."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Uloženo uživatelem <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Připojeno pomocí asistenta připojení Wi-Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Připojeno prostřednictvím %1$s"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 3c4b955..5714901 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi-forbindelsesfejl"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem med godkendelse"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Ikke inden for rækkevidde"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Der blev ikke fundet nogen internetadgang. Forbindelsen bliver ikke automatisk genoprettet."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Gemt af <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Forbindelse via Wi-Fi-assistent"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Tilsluttet via %1$s"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 0fca8b9..406523e 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WLAN-Verbindungsfehler"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Authentifizierungsproblem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Nicht in Reichweite"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Keine Internetverbindung erkannt, es kann nicht automatisch eine Verbindung hergestellt werden."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Gespeichert von <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Über WLAN-Assistenten verbunden"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Über %1$s verbunden"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index da1b03c..117b9fe 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Αποτυχία σύνδεσης Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Πρόβλημα ελέγχου ταυτότητας"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Εκτός εμβέλειας"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Δεν εντοπίστηκε καμία πρόσβαση στο διαδίκτυο, δεν θα γίνει αυτόματη επανασύνδεση."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Αποθηκεύτηκε από <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Σύνδεση μέσω βοηθού Wi‑Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Συνδέθηκε μέσω %1$s"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 70fa5017..35ec15b 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi Connection Failure"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Authentication problem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Not in range"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"No Internet Access Detected, won\'t automatically reconnect."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Saved by <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Connected via Wi‑Fi assistant"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Connected via %1$s"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 70fa5017..35ec15b 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi Connection Failure"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Authentication problem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Not in range"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"No Internet Access Detected, won\'t automatically reconnect."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Saved by <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Connected via Wi‑Fi assistant"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Connected via %1$s"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 70fa5017..35ec15b 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi Connection Failure"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Authentication problem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Not in range"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"No Internet Access Detected, won\'t automatically reconnect."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Saved by <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Connected via Wi‑Fi assistant"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Connected via %1$s"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 63a5d87..2874e61 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Error de conexión Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problema de autenticación"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Fuera de alcance"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"No se detectó el acceso a Internet. No se volverá a conectar de forma automática."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Guardadas por <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Conexión por asistente de Wi-Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Conexión a través de %1$s"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index a0dc336b..7d0097a 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Error de conexión Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Error de autenticación"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Fuera de rango"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"No se ha detectado acceso a Internet, no se volverá a conectar automáticamente."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Guardadas por <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Conectado a través de asistente Wi‑Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Conectado a través de %1$s"</string>
diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml
index de9255a..97fe73f 100644
--- a/packages/SettingsLib/res/values-et-rEE/strings.xml
+++ b/packages/SettingsLib/res/values-et-rEE/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi-ühenduse viga"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Autentimise probleem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Pole vahemikus"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Interneti-ühendust ei tuvastatud, seadet ei ühendata automaatselt."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Salvestas: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Ühendatud WiFi-abi kaudu"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Ühendatud üksuse %1$s kaudu"</string>
diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml
index bd8c11d..9234f24 100644
--- a/packages/SettingsLib/res/values-eu-rES/strings.xml
+++ b/packages/SettingsLib/res/values-eu-rES/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Ezin izan da konektatu Wi-Fi sarera"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Autentifikazio-arazoa"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Urrunegi"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Ez da hauteman Interneterako sarbiderik. Ez da automatikoki berriro konektatuko."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> aplikazioak gorde du"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Wi‑Fi laguntzailearen bidez konektatuta"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s bidez konektatuta"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 9c7e046..bb2e166 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"‏اتصال Wi-Fi برقرار نشد"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"مشکل احراز هویت"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"در محدوده نیست"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"دسترسی به اینترنت شناسایی نشد، به صورت خودکار وصل نمی‌شود."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"ذخیره‌شده توسط <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"‏متصل شده از طریق دستیار Wi-Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"‏متصل از طریق %1$s"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index a988ccf..c04c970 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi-yhteysvirhe"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Todennusvirhe"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Ei kantoalueella"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Internetyhteyttä ei havaittu, yhteyttä ei muodosteta automaattisesti uudelleen."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Tallentaja: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Yhteys muodostettu Wi‑Fi-apurin kautta"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Yhdistetty seuraavan kautta: %1$s"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index e22e938..1b34904 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Échec de connexion Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problème d\'authentification"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Hors de portée"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Aucun accès à Internet détecté, reconnexion automatique impossible"</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Enregistrés par <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Connecté à l\'aide de l\'assistant Wi-Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Connecté par %1$s"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index e4a34d6..07398f3 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Échec de la connexion Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problème d\'authentification."</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Hors de portée"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Aucun accès à Internet détecté, reconnexion automatique impossible"</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Enregistré par <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Connecté via l\'assistant Wi‑Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Connecté via %1$s"</string>
diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index 10a3957..5207a73 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Erro na conexión wifi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problema de autenticación"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Non está dentro da zona de cobertura"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Non se detectou acceso a Internet e non se volverá conectar automaticamente."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Redes gardadas por <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Conectado ao asistente de wifi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Conectado a través de %1$s"</string>
diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml
index 0f3079d..3d0a02b 100644
--- a/packages/SettingsLib/res/values-gu-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi કનેક્શન નિષ્ફળ"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"પ્રમાણીકરણ સમસ્યા"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"રેન્જમાં નથી"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"કોઈ ઇન્ટરનેટ અ‍ૅક્સેસ શોધાયું નથી, આપમેળે ફરીથી કનેક્ટ કરશે નહીં."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા સચવાયું"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Wi-Fi સહાયક દ્વારા કનેક્ટ થયું"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s દ્વારા કનેક્ટ થયેલ"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 5407c21..329a670 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"वाईफ़ाई कनेक्‍शन विफलता"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"प्रमाणीकरण समस्या"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"रेंज में नहीं"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"किसी इंटरनेट कनेक्‍शन का पता नहीं चला, अपने आप पुन: कनेक्‍ट नहीं हो सकता."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> के द्वारा सहेजा गया"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"वाई-फ़ाई सहायक के द्वारा कनेक्‍ट है"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s के द्वारा उपलब्ध"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index e52f441..89b0653 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Povezivanje s Wi-Fi-jem nije uspjelo"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem u autentifikaciji"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Nije u rasponu"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Pristup internetu nije otkriven. Nema automatskog ponovnog povezivanja."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Spremljeno: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Povezani putem pomoćnika za Wi-Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Povezano putem %1$s"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index ac4a43c..c33943a 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi-kapcsolati hiba"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Azonosítási probléma"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Hatókörön kívül"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Nincs érzékelhető internet-hozzáférés, ezért nem kapcsolódik újra automatikusan."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Mentette: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Csatlakozva Wi‑Fi-segéddel"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Csatlakozva a következőn keresztül: %1$s"</string>
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index e26d4cb..32b0dd6 100644
--- a/packages/SettingsLib/res/values-hy-rAM/strings.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi կապի ձախողում"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Նույնականացման խնդիր"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Ընդգրկույթից դուրս է"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Ինտերնետի հասանելիություն չկա. ավտոմատ կերպով կրկին չի միանա:"</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Պահել է հետևյալ օգտվողը՝ <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Կապակցված է Wi‑Fi Օգնականի միջոցով"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Կապակցված է %1$s-ի միջոցով"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 5711ea7..33df1fe 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Kegagalan Sambungan Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Masalah autentikasi"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Tidak dalam jangkauan"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Akses Internet Tidak Terdeteksi, tidak akan menyambung ulang secara otomatis."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Disimpan oleh <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Terhubung melalui Asisten Wi-Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Terhubung melalui %1$s"</string>
diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml
index 44226ee..8cc408f 100644
--- a/packages/SettingsLib/res/values-is-rIS/strings.xml
+++ b/packages/SettingsLib/res/values-is-rIS/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi-tengingarvilla"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Vandamál við auðkenningu"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Ekkert samband"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Enginn netaðgangur fannst; endurtengist ekki sjálfkrafa."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> vistaði"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Tengt í gegnum Wi-Fi aðstoð"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Tengt í gegnum %1$s"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index cbf89c9..0bb26e1 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Errore connessione Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problema di autenticazione"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Fuori portata"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Nessun accesso a Internet rilevato, non verrà eseguita la riconnessione automatica."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Salvata da <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Connesso tramite assistente Wi‑Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Collegato tramite %1$s"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 6f7460a..7510911 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"‏כשל בחיבור Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"בעיית אימות"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"מחוץ לטווח"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"אין גישה לאינטרנט. לא יתבצע חיבור מחדש באופן אוטומטי."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"נשמר על ידי <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"‏מחובר באמצעות אסיסטנט ה-Wi-Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"‏מחובר דרך %1$s"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 025b7fd..f657c1e 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -28,7 +28,8 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi接続エラー"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"認証に問題"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"圏外"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"インターネットアクセスを検出できないため、自動的に再接続されません。"</string>
+    <string name="wifi_no_internet_no_reconnect" msgid="2211781637653149657">"インターネット アクセスを検出できないため、自動的に再接続されません。"</string>
+    <string name="wifi_no_internet" msgid="5011955173375805204">"インターネットに接続していません。"</string>
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g>で保存"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Wi‑Fiアシスタント経由で接続"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s経由で接続"</string>
diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml
index 0eda6a9..f349c4f 100644
--- a/packages/SettingsLib/res/values-ka-rGE/strings.xml
+++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi კავშირის შეფერხება"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"ავთენტიკაციის პრობლემა"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"არ არის დიაპაზონში"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"ინტერნეტთან წვდომის ამოცნობა ვერ მოხერხდა. ავტომატურად ხელახლა დაკავშირება არ განხორციელდება."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"შენახული <xliff:g id="NAME">%1$s</xliff:g>-ის მიერ"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"დაკავშირებულია Wi-Fi თანაშემწით"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s-ით დაკავშირებული"</string>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
index 369a10f..1141fca 100644
--- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml
+++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi байланысының қатесі"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Растау мәселесі"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Аумақта жоқ"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Интернетке қатынас анықталмады, автоматты түрде қайта қосылу орындалмайды."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> сақтаған"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Wi‑Fi көмекшісі арқылы қосылу орындалды"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s арқылы қосылған"</string>
diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml
index 3e934ba..7d1c797 100644
--- a/packages/SettingsLib/res/values-km-rKH/strings.xml
+++ b/packages/SettingsLib/res/values-km-rKH/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"ការ​ភ្ជាប់​ WiFi បរាជ័យ"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"បញ្ហា​ក្នុង​ការ​ផ្ទៀងផ្ទាត់"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"នៅ​ក្រៅ​តំបន់"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"រក​មិន​ឃើញ​ការ​ចូល​ដំណើរការ​អ៊ីនធឺណិត, នឹង​មិន​ភ្ជាប់​ឡើង​វិញ​ដោយ​ស្វ័យ​ប្រវត្តិ​ទេ។"</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"បានរក្សាទុកដោយ <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"បានភ្ជាប់តាមរយៈជំនួយការ Wi‑Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"បានភ្ជាប់តាមរយៈ %1$s"</string>
diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml
index ad549c2..9039e25 100644
--- a/packages/SettingsLib/res/values-kn-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi ಸಂಪರ್ಕ ವಿಫಲತೆ"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"ಪ್ರಮಾಣೀಕರಣ ಸಮಸ್ಯೆ"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"ವ್ಯಾಪ್ತಿಯಲ್ಲಿಲ್ಲ"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"ಯಾವುದೇ ಇಂಟರ್ನೆಟ್‌ ಪ್ರವೇಶ ಪತ್ತೆಯಾಗಿಲ್ಲ, ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಮರುಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> ರಿಂದ ಉಳಿಸಲಾಗಿದೆ"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Wi‑Fi ಸಹಾಯಕದ ಮೂಲಕ ಸಂಪರ್ಕಿತಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s ಮೂಲಕ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index bd96334..e33b989 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi 연결 실패"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"인증 문제"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"범위 내에 없음"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"감지된 인터넷 액세스가 없으며 자동으로 다시 연결되지 않습니다."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g>(으)로 저장됨"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Wi‑Fi 도우미를 통해 연결됨"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s을(를) 통해 연결됨"</string>
diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml
index 5ca4e7c..22622dd 100644
--- a/packages/SettingsLib/res/values-ky-rKG/strings.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi туташуусу бузулду"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Аутентификация маселеси бар"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Тейлөө аймагында эмес"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Интернетке кирүү мүмкүнчүлүгү табылган жок, андыктан автоматтык түрдө кайра туташпайт."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> тарабынан сакталды"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Wi‑Fi жардамчысы аркылуу туташып турат"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s аркылуу жеткиликтүү"</string>
diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml
index b47629a..716ee6f 100644
--- a/packages/SettingsLib/res/values-lo-rLA/strings.xml
+++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"​ການ​ເຊື່ອມ​ຕໍ່ WiFi ລົ້ມ​ເຫຼວ"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"ບັນຫາການພິສູດຢືນຢັນ"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"ບໍ່ຢູ່ໃນໄລຍະທີ່ເຊື່ອມຕໍ່ໄດ້"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"​ບໍ່​ພົບ​ການ​ເຊື່ອມ​ຕໍ່​ອິນ​ເຕີ​ເນັດ​, ຈະ​ບໍ່​ຖືກ​ເຊື່ອມ​ຕໍ່​ໃໝ່​ໂດຍ​ອັດ​ຕະ​ໂນ​ມັດ."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"ບັນທຶກ​​​ໂດຍ <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"ເຊື່ອມ​ຕໍ່​ຜ່ານ Wi‑Fi ຕົວ​ຊ່ວຍ​ແລ້ວ"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"​ເຊື່ອມຕໍ່​ຜ່ານ %1$s ​ແລ້ວ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 7ac54a8..167e756 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"„Wi-Fi“ ryšio triktis"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Autentifikavimo problema"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Ne diapazone"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Neaptikta jokia prieiga prie interneto, nebus automatiškai iš naujo prisijungta."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Išsaugojo <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Prisijungta naudojant „Wi‑Fi“ pagelbiklį"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Prisijungta naudojant „%1$s“"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 933d374..7f5e111 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi savienojuma kļūme"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Autentificēšanas problēma"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Nav diapazona ietvaros"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Nevar noteikt interneta savienojumu. Savienojums netiks izveidots vēlreiz automātiski."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Saglabāja: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Izveidots savienojums ar Wi‑Fi palīgu"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Savienots, izmantojot %1$s"</string>
diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml
index 1e1c857..2a454d2 100644
--- a/packages/SettingsLib/res/values-mk-rMK/strings.xml
+++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Поврзувањето преку Wi-Fi не успеа"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Проблем со автентикација"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Надвор од опсег"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Не е откриен пристап до интернет, нема автоматски повторно да се поврзете."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Зачувано од <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Поврзано преку помошник за Wi-Fismile"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Поврзано преку %1$s"</string>
diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml
index 6f75886..56d1477 100644
--- a/packages/SettingsLib/res/values-ml-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi കണക്ഷൻ പരാജയം"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"ആധികാരികമാക്കുന്നതിലെ പ്രശ്‌നം"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"പരിധിയിലില്ല"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"ഇന്റർനെറ്റ് ആക്സസ്സൊന്നും കണ്ടെത്താത്തതിനാൽ സ്വയം വീണ്ടും കണക്‌റ്റുചെയ്യില്ല."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> സംരക്ഷിച്ചത്"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"വൈഫൈ അസിസ്റ്റന്റ് മുഖേന കണക്‌റ്റുചെയ്തു"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s വഴി ബന്ധിപ്പിച്ചു"</string>
diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml
index bf7d7ce..9848cae 100644
--- a/packages/SettingsLib/res/values-mn-rMN/strings.xml
+++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi холболт амжилтгүй"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Гэрчлэлийн асуудал"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Хүрээнд байхгүй"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Интернэт холболт илэрсэнгүй, автоматаар дахин холболт хийгдэхгүй"</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> хадгалсан"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Wi-Fi туслагчаар дамжуулан холбогдлоо"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s-р холбогдсон"</string>
diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml
index a1123bc..83ae663 100644
--- a/packages/SettingsLib/res/values-mr-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi कनेक्शन अयशस्वी"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"प्रमाणीकरण समस्या"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"परिक्षेत्रामध्ये नाही"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"कोणताही इंटरनेट प्रवेश आढळला नाही, स्वयंचलितपणे रीकनेक्ट करणार नाही."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> द्वारे जतन केले"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Wi‑Fi सहाय्यक द्वारे कनेक्ट केले"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s द्वारे कनेक्‍ट केले"</string>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index 8f11589..217d82a 100644
--- a/packages/SettingsLib/res/values-ms-rMY/strings.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Kegagalan Sambungan WiFi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Masalah pengesahan"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Tidak dalam liputan"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Tiada Akses Internet Dikesan, tidak akan menyambung secara automatik."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Diselamatkan oleh <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Disambungkan melalui Pembantu Wi-Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Disambungkan melalui %1$s"</string>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index cfba5da..fc977a9 100644
--- a/packages/SettingsLib/res/values-my-rMM/strings.xml
+++ b/packages/SettingsLib/res/values-my-rMM/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi ချိတ်ဆက်မှု မအောင်မြင်ပါ"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"စစ်မှန်ကြောင်းအတည်ပြုရန်၌ ပြသနာရှိခြင်း"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"စက်ကွင်းထဲတွင် မဟုတ်ပါ"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"မည်သည့် အင်တာနက်မျှမရှိပါ၊ အလိုအလျောက် ပြန်လည်မချိတ်ဆက်ပါ။"</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> မှသိမ်းဆည်းခဲ့သည်"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"ကြိုးမဲ့ကူညီသူမှတဆင့် ချိတ်ဆက်၏"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s မှတစ်ဆင့် ချိတ်ဆက်ထားသည်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 2da378a..bd6ae05 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi-tilkoblingsfeil"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Autentiseringsproblem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Utenfor område"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Ingen Internett-tilgang ble funnet. Kan ikke koble til på nytt automatisk."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Lagret av <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Koblet til via en Wi-Fi-assistent"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Tilkoblet via %1$s"</string>
diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml
index a56b655..c671f90 100644
--- a/packages/SettingsLib/res/values-ne-rNP/strings.xml
+++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"वाईफाई जडान असफल"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"प्रमाणीकरण समस्या"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"दायराभित्र छैन"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"कुनै इन्टरनेट पहुँच पाईएन, स्वचालित रूपमा पुन: जडान छैन।"</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> द्वारा सुरक्षित गरियो"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Wi-Fi सहायक द्वारा जोडिएको"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s मार्फत जडित"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 11d92e5..330eb30 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wifi-verbinding mislukt"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Authenticatieprobleem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Niet binnen bereik"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Geen internettoegang gevonden. Er wordt niet automatisch opnieuw verbinding gemaakt."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Opgeslagen door <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Verbonden via wifi-assistent"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Verbonden via %1$s"</string>
diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml
index d526064..9826023 100644
--- a/packages/SettingsLib/res/values-pa-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi ਕਨੈਕਸ਼ਨ ਅਸਫਲਤਾ"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"ਪ੍ਰਮਾਣੀਕਰਨ ਸਮੱਸਿਆ"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"ਰੇਂਜ ਵਿੱਚ ਨਹੀਂ ਹੈ"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"ਕੋਈ ਇੰਟਰਨੈਟ ਪਹੁੰਚ ਨਹੀਂ ਮਿਲੀ, ਆਟੋਮੈਟਿਕਲੀ ਰੀਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾਏਗਾ।"</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> ਵੱਲੋਂ ਸੁਰੱਖਿਅਤ ਕੀਤਾ"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Wi‑Fi ਸਹਾਇਕ ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤਾ"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤਾ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index dcbb934..4dce1a4 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Błąd połączenia Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem z uwierzytelnianiem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Poza zasięgiem"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Nie wykryto dostępu do internetu. Nie można automatycznie przywrócić połączenia."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Zapisane przez: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Połączono przez Asystenta Wi‑Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Połączono przez %1$s"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index fc22225..27332f9 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Falha de conexão Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problema de autenticação"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Fora do alcance"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Nenhum acesso à Internet detectado. O dispositivo não conectará automaticamente."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Salvas por <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Conectado via assistente de Wi‑Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Conectado via %1$s"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index c297de5..c48ccba 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Falha de ligação Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problema de autenticação"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Fora do alcance"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Nenhum acesso à Internet detetado; não será efetuada uma nova ligação automaticamente."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Guardada por <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Ligado através do Assistente de Wi‑Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Ligado através de %1$s"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index fc22225..27332f9 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Falha de conexão Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problema de autenticação"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Fora do alcance"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Nenhum acesso à Internet detectado. O dispositivo não conectará automaticamente."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Salvas por <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Conectado via assistente de Wi‑Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Conectado via %1$s"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 70912f9..8458557 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Eroare de conexiune Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problemă la autentificare"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"În afara ariei de acoperire"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Nu s-a detectat acces la internet, nu se va efectua reconectarea automată."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Salvată de <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Conexiune realizată printr-un asistent Wi-Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Conectată prin %1$s"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 4af530d..a89c553 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Ошибка подключения Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Ошибка аутентификации"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Недоступна"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Подключение к Интернету отсутствует и не будет восстановлено автоматически."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Кто сохранил: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Установлено подключение через Ассистента Wi-Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Подключено к %1$s"</string>
diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml
index d9fed96..c8a0bad 100644
--- a/packages/SettingsLib/res/values-si-rLK/strings.xml
+++ b/packages/SettingsLib/res/values-si-rLK/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi සම්බන්ධතාව අසාර්ථකයි"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"සත්‍යාපනයේ ගැටලුවකි"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"පරාසයේ නැත"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"අන්තර්ජාල ප්‍රවේශය අනාවරණය වුයේ නැත, ස්වයංක්‍රිය නැවත සම්බන්ධ වීම වූ නැත"</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> විසින් සුරකින ලදී"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Wi‑Fi සහායක හරහා සම්බන්ධ කරන ලදි"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s හරහා සම්බන්ධ විය"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 04a256b..958bae6 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Zlyhanie pripojenia Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problém s overením totožnosti"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Mimo dosah"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Nenašiel sa žiadny prístup k internetu, preto nedôjde k automatickému opätovnému pripojeniu"</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Uložil(a) <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Pripojené pomocou Asistenta Wi-Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Pripojené prostredníctvom %1$s"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 2428076..d4ad802 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Povezava prek Wi-Fi-ja ni uspela"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Težava s preverjanjem pristnosti"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Ni v obsegu"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Ni zaznanega dostopa do interneta; samodejna vnovična vzpostavitev povezave se ne bo izvedla."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Shranil(-a): <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Povezava vzpostavljena prek pomočnika za Wi-Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Vzpostavljena povezava prek: %1$s"</string>
diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml
index 1645f10..ba5d2833 100644
--- a/packages/SettingsLib/res/values-sq-rAL/strings.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Dështim i lidhjes WiFi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem me vërtetimin"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Nuk është brenda rrezes"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Nuk u diktua qasje në internet. Lidhja nuk do të realizohet automatikisht."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"E ruajtur nga <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"I lidhur nëpërmjet ndihmësit të Wi‑Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"E lidhur përmes %1$s"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 04dfb24..b04a4c2 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi веза је отказала"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Проблем са потврдом аутентичности"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Није у опсегу"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Приступ интернету није откривен, аутоматско повезивање није могуће."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Сачувао/ла је <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Повезано преко Wi‑Fi помоћника"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Веза је успостављена преко приступне тачке %1$s"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 4b42db5..7562ee0 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi-anslutningsfel"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Autentiseringsproblem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Utom räckhåll"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Ingen internetåtkomst hittades. Det går inte att återansluta automatiskt."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Sparades av <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Ansluten via Wi-Fi-assistent"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Anslutet via %1$s"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index f70a1fa..9e64b91 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Haikuweza Kuunganisha kwenye WiFi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Tatizo la uthibitishaji"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Haiko karibu"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Hakuna Ufikiaji kwa Intaneti Uliogunduliwa, haitaweza kuunganisha kiotomatiki."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Ilihifadhiwa na <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Imeunganishwa kupitia Kisaidizi cha Wi-Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Imeunganishwa kupitia %1$s"</string>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index 5f6b121..b9ff6bc 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"வைஃபை இணைப்பில் தோல்வி"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"அங்கீகரிப்புச் சிக்கல்"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"தொடர்பு எல்லையில் இல்லை"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"இணைய அணுகல் இல்லை, மீண்டும் தானாக இணையாது."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> சேமித்தது"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"வைஃபை அசிஸ்டண்ட் மூலம் இணைக்கப்பட்டது"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s வழியாக இணைக்கப்பட்டது"</string>
diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml
index ff8b855..08bcbda 100644
--- a/packages/SettingsLib/res/values-te-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-te-rIN/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi కనెక్షన్ వైఫల్యం"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"ప్రామాణీకరణ సమస్య"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"పరిధిలో లేదు"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"ఇంటర్నెట్ ప్రాప్యత కనుగొనబడలేదు, స్వయంచాలకంగా మళ్లీ కనెక్ట్ చేయబడదు."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> ద్వారా సేవ్ చేయబడింది"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Wi‑Fi సహాయకం ద్వారా కనెక్ట్ చేయబడింది"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s ద్వారా కనెక్ట్ చేయబడింది"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 4d0a2e4..bd9d8d5 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"การเชื่อมต่อ Wi-Fi ล้มเหลว"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"ปัญหาในการตรวจสอบสิทธิ์"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"ไม่อยู่ในพื้นที่ให้บริการ"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"ไม่พบการเข้าถึงอินเทอร์เน็ต ระบบจะไม่เชื่อมต่อใหม่โดยอัตโนมัติ"</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"บันทึกโดย <xliff:g id="NAME">%1$s</xliff:g> แล้ว"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"เชื่อมต่อผ่านตัวช่วย Wi-Fi อยู่"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"เชื่อมต่อผ่าน %1$s แล้ว"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 95897a3..9c952f5 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Pagkabigo ng Koneksyon sa WiFi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problema sa pagpapatotoo"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Wala sa sakop"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Walang Natukoy na Access sa Internet, hindi awtomatikong muling kumonekta."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Na-save ni <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Nakakonekta sa pamamagitan ng Wi‑Fi assistant"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Nakakonekta sa pamamagitan ng %1$s"</string>
@@ -146,7 +149,7 @@
     <string name="vpn_settings_not_available" msgid="956841430176985598">"Hindi available ang mga setting ng VPN para sa user na ito"</string>
     <string name="tethering_settings_not_available" msgid="6765770438438291012">"Hindi available ang mga setting ng pagte-theter para sa user na ito"</string>
     <string name="apn_settings_not_available" msgid="7873729032165324000">"Hindi available ang mga setting ng Access Point Name para sa user na ito"</string>
-    <string name="enable_adb" msgid="7982306934419797485">"Pagde-debug ng USB"</string>
+    <string name="enable_adb" msgid="7982306934419797485">"Pag-debug ng USB"</string>
     <string name="enable_adb_summary" msgid="4881186971746056635">"Debug mode kapag nakakonekta ang USB"</string>
     <string name="clear_adb_keys" msgid="4038889221503122743">"Bawiin ang mga pahintulot sa pag-debug ng USB"</string>
     <string name="bugreport_in_power" msgid="7923901846375587241">"Shortcut ng ulat sa bug"</string>
@@ -186,8 +189,8 @@
     <string name="debug_view_attributes" msgid="6485448367803310384">"I-enable ang pagsisiyasat sa attribute na view"</string>
     <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Palaging panatilihing aktibo ang mobile data, kahit na aktibo ang Wi‑Fi (para sa mabilis na paglipat ng network)."</string>
     <string name="adb_warning_title" msgid="6234463310896563253">"Payagan ang pag-debug ng USB?"</string>
-    <string name="adb_warning_message" msgid="7316799925425402244">"Ang pag-debug ng USB ay nilalayon para sa mga layuning pagpapabuti lamang. Gamitin ito upang kumopya ng data sa pagitan ng iyong computer at iyong device, mag-install ng apps sa iyong device nang walang notification, at magbasa ng data ng log."</string>
-    <string name="adb_keys_warning_message" msgid="5659849457135841625">"Bawiin ang access sa pagde-debug ng USB mula sa lahat ng computer na dati mong pinahintulutan?"</string>
+    <string name="adb_warning_message" msgid="7316799925425402244">"Ang pag-debug ng USB ay para lang sa mga layuning pag-develop. Gamitin ito upang kumopya ng data sa pagitan ng iyong computer at iyong device, mag-install ng mga app sa iyong device nang walang notification, at magbasa ng data ng log."</string>
+    <string name="adb_keys_warning_message" msgid="5659849457135841625">"Bawiin ang access sa pag-debug ng USB mula sa lahat ng computer na dati mong pinahintulutan?"</string>
     <string name="dev_settings_warning_title" msgid="7244607768088540165">"Payagan ang mga setting ng pag-develop?"</string>
     <string name="dev_settings_warning_message" msgid="2298337781139097964">"Nilalayon ang mga setting na ito para sa paggamit sa pag-develop lamang. Maaaring magsanhi ang mga ito ng pagkasira o hindi paggana nang maayos ng iyong device at mga application na nandito."</string>
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"I-verify ang mga app sa USB"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 3c5b46d..889b631 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Kablosuz Bağlantı Hatası"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Kimlik doğrulama sorunu"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Kapsama alanı dışında"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"İnternet Erişimi algılanmadı, otomatik olarak tekrar bağlanmayacak."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> tarafından kaydedildi"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Kablosuz bağlantı yardımcısıyla bağlandı"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s üzerinden bağlı"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index ef30a69..cdf725f 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Помилка з’єднання Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Проблема з автентифікацією"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Не в діапазоні"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Немає доступу до Інтернету. Спроба під’єднання не здійснюватиметься автоматично."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Збережено додатком <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Під’єднано через Диспетчер Wi-Fi-з’єднання"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Під’єднано через %1$s"</string>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index 57b0b63..c5aaaab 100644
--- a/packages/SettingsLib/res/values-ur-rPK/strings.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"‏WiFi کنکشن کی ناکامی"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"توثیق کا مسئلہ"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"رینج میں نہیں ہے"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"انٹرنیٹ تک کسی رسائی کا پتہ نہیں چلا، خود بخود دوبارہ منسلک نہیں ہوگا۔"</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> کی جانب سے محفوظ کردہ"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"‏Wi‑Fi اسسٹنٹ کے ذریعے منسلک ہے"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"‏منسلک بذریعہ ‎%1$s"</string>
diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
index b4e0505..e2c58a4 100644
--- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml
+++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi ulanishini o‘rnatib bo‘lmadi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Tasdiqdan o‘tishda muammo"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Aloqada emas"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Internetga ulanish aniqlanmadi, avtomatik ravishda qayta ulana olmaydi."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> tomonidan saqlangan"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Wi‑Fi yordamchisi orqali ulangan"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s orqali ulangan"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 494cb7c..fa4174b 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Lỗi kết nối WiFi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Sự cố xác thực"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Ngoài vùng phủ sóng"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Không phát hiện thấy truy cập Internet nào, mạng sẽ không được tự động kết nối lại."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Được lưu bởi <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Được kết nối qua trình hỗ trợ Wi‑Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Được kết nối qua %1$s"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 83c08d4..63199e8 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WLAN 连接失败"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"身份验证出现问题"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"不在范围内"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"未检测到任何互联网连接,因此不会自动重新连接。"</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"已通过<xliff:g id="NAME">%1$s</xliff:g>保存"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"已连接(通过 WLAN 助手)"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"已通过%1$s连接"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 45918f0..edbffc1 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi 連線失敗"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"驗證問題"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"超出可用範圍"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"未能偵測到互聯網連線,因此不會自動重新連線。"</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> 的儲存"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"已透過 Wi-Fi 小幫手連線"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"已透過 %1$s 連線"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index b2e0d12..b1c5f06 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi 連線失敗"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"驗證問題"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"不在有效範圍內"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"未偵測到可用的網際網路連線,系統無法為您自動重新連線。"</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"由<xliff:g id="NAME">%1$s</xliff:g>儲存"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"已透過 Wi‑Fi 小幫手連線"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"已透過 %1$s 連線"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index d137908..e4f0d59 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -28,7 +28,10 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Ukwehlulekla koxhumo le-WiFi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Inkinga yokufakazela ubuqiniso"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Ayikho ebubanzini"</string>
-    <string name="wifi_no_internet" msgid="9151470775868728896">"Ukufinyeela okungekhona kwe-inthanethi kutholakele, ngeke kuxhumeke ngokuzenzakalelayo."</string>
+    <!-- no translation found for wifi_no_internet_no_reconnect (2211781637653149657) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (5011955173375805204) -->
+    <skip />
     <string name="saved_network" msgid="4352716707126620811">"Kulondolozwe ngu-<xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Ixhunywe ngomsizi we-Wi-FI"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Kuxhumeke nge-%1$s"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 3bdb6fb..1a1aa57 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -64,8 +64,10 @@
     <string name="wifi_disabled_password_failure">Authentication problem</string>
     <!-- Summary for the remembered network but currently not in range. -->
     <string name="wifi_not_in_range">Not in range</string>
+    <!-- Summary for the network but no internet connection was detected. -->
+    <string name="wifi_no_internet_no_reconnect">Won\'t automatically connect</string>
     <!-- Summary for the remembered network but no internet connection was detected. -->
-    <string name="wifi_no_internet">No Internet Access Detected, won\'t automatically reconnect.</string>
+    <string name="wifi_no_internet">No Internet access</string>
     <!-- Summary for saved networks -->
     <string name="saved_network">Saved by <xliff:g id="name">%1$s</xliff:g></string>
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
new file mode 100644
index 0000000..ca8edf5
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.deviceinfo;
+
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
+import android.util.Log;
+
+import java.io.File;
+import java.util.Objects;
+
+/**
+ * PrivateStorageInfo provides information about the total and free storage on the device.
+ */
+public class PrivateStorageInfo {
+    private static final String TAG = "PrivateStorageInfo";
+    public final long freeBytes;
+    public final long totalBytes;
+
+    private PrivateStorageInfo(long freeBytes, long totalBytes) {
+        this.freeBytes = freeBytes;
+        this.totalBytes = totalBytes;
+    }
+
+    public static PrivateStorageInfo getPrivateStorageInfo(StorageVolumeProvider sm) {
+        long totalInternalStorage = sm.getPrimaryStorageSize();
+        long privateFreeBytes = 0;
+        long privateTotalBytes = 0;
+        for (VolumeInfo info : sm.getVolumes()) {
+            final File path = info.getPath();
+            if (info.getType() != VolumeInfo.TYPE_PRIVATE || path == null) {
+                continue;
+            }
+            privateTotalBytes += getTotalSize(info, totalInternalStorage);
+            privateFreeBytes += path.getFreeSpace();
+        }
+        return new PrivateStorageInfo(privateFreeBytes, privateTotalBytes);
+    }
+
+    /**
+     * Returns the total size in bytes for a given volume info.
+     * @param info Info of the volume to check.
+     * @param totalInternalStorage Total number of bytes in the internal storage to use if the
+     *                             volume is the internal disk.
+     */
+    public static long getTotalSize(VolumeInfo info, long totalInternalStorage) {
+        // Device could have more than one primary storage, which could be located in the
+        // internal flash (UUID_PRIVATE_INTERNAL) or in an external disk.
+        // If it's internal, try to get its total size from StorageManager first
+        // (totalInternalStorage), because that size is more precise because it accounts for
+        // the system partition.
+        if (info.getType() == VolumeInfo.TYPE_PRIVATE
+                && Objects.equals(info.getFsUuid(), StorageManager.UUID_PRIVATE_INTERNAL)
+                && totalInternalStorage > 0) {
+            return totalInternalStorage;
+        } else {
+            final File path = info.getPath();
+            if (path == null) {
+                // Should not happen, caller should have checked.
+                Log.e(TAG, "info's path is null on getTotalSize(): " + info);
+                return 0;
+            }
+            return path.getTotalSpace();
+        }
+    }
+
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
new file mode 100644
index 0000000..de76279
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.deviceinfo;
+
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
+
+import java.util.List;
+
+/**
+ * StorageManagerVolumeProvider is a thin wrapper around the StorageManager to provide insight into
+ * the storage volumes on a device.
+ */
+public class StorageManagerVolumeProvider implements StorageVolumeProvider {
+    private StorageManager mStorageManager;
+
+    public StorageManagerVolumeProvider(StorageManager sm) {
+        mStorageManager = sm;
+    }
+
+    @Override
+    public long getPrimaryStorageSize() {
+        return mStorageManager.getPrimaryStorageSize();
+    }
+
+    @Override
+    public List<VolumeInfo> getVolumes() {
+        return mStorageManager.getVolumes();
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
new file mode 100644
index 0000000..95bb18d
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.deviceinfo;
+
+import android.os.storage.VolumeInfo;
+
+import java.util.List;
+
+/**
+ * StorageVolumeProvider provides access to the storage volumes on a device for free space
+ * calculations.
+ */
+public interface StorageVolumeProvider {
+    /**
+     * Returns the number of bytes of total storage on the primary storage.
+     */
+    long getPrimaryStorageSize();
+
+    /**
+     * Returns a list of VolumeInfos for the device.
+     */
+    List<VolumeInfo> getVolumes();
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
new file mode 100644
index 0000000..9821fb8
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.drawer;
+
+public final class CategoryKey {
+
+    // Activities in this category shows up in Settings homepage.
+    public static final String CATEGORY_HOMEPAGE = "com.android.settings.category.homepage";
+
+    // Top level categor.
+    public static final String CATEGORY_NETWORK = "com.android.settings.category.wireless";
+    public static final String CATEGORY_DEVICE = "com.android.settings.category.device";
+    public static final String CATEGORY_APPS = "com.android.settings.category.apps";
+    public static final String CATEGORY_BATTERY = "com.android.settings.category.battery";
+    public static final String CATEGORY_DISPLAY = "com.android.settings.category.display";
+    public static final String CATEGORY_SOUND = "com.android.settings.category.sound";
+    public static final String CATEGORY_STORAGE = "com.android.settings.category.storage";
+    public static final String CATEGORY_SECURITY = "com.android.settings.category.security";
+    public static final String CATEGORY_ACCOUNT = "com.android.settings.category.accounts";
+    public static final String CATEGORY_SYSTEM = "com.android.settings.category.system";
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java
new file mode 100644
index 0000000..a8f286d
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java
@@ -0,0 +1,108 @@
+/**
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.drawer;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.settingslib.applications.InterestingConfigChanges;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class CategoryManager {
+
+    private static final String TAG = "CategoryManager";
+
+    private static CategoryManager sInstance;
+
+    private final InterestingConfigChanges mInterestingConfigChanges;
+
+    // Tile cache (key: <packageName, activityName>, value: tile)
+    private final Map<Pair<String, String>, Tile> mTileByComponentCache;
+
+    // Tile cache (key: category key, value: category)
+    private final Map<String, DashboardCategory> mCategoryByKeyMap;
+
+    private List<DashboardCategory> mCategories;
+
+    public static CategoryManager get() {
+        if (sInstance == null) {
+            sInstance = new CategoryManager();
+        }
+        return sInstance;
+    }
+
+    CategoryManager() {
+        mInterestingConfigChanges = new InterestingConfigChanges();
+        mTileByComponentCache = new ArrayMap<>();
+        mCategoryByKeyMap = new ArrayMap<>();
+    }
+
+    public DashboardCategory getTilesByCategory(Context context, String categoryKey) {
+        tryInitCategories(context);
+
+        final DashboardCategory category = mCategoryByKeyMap.get(categoryKey);
+        if (category == null) {
+            throw new IllegalStateException("Can't find category with key " + categoryKey);
+        }
+        return category;
+    }
+
+    public List<DashboardCategory> getCategories(Context context) {
+        tryInitCategories(context);
+        return mCategories;
+    }
+
+    public void reloadAllCategoriesForConfigChange(Context context) {
+        if (mInterestingConfigChanges.applyNewConfig(context.getResources())) {
+            mCategories = null;
+            tryInitCategories(context);
+        }
+    }
+
+    public void updateCategoryFromBlacklist(Set<ComponentName> tileBlacklist) {
+        if (mCategories == null) {
+            Log.w(TAG, "Category is null, skipping blacklist update");
+        }
+        for (int i = 0; i < mCategories.size(); i++) {
+            DashboardCategory category = mCategories.get(i);
+            for (int j = 0; j < category.tiles.size(); j++) {
+                Tile tile = category.tiles.get(j);
+                if (tileBlacklist.contains(tile.intent.getComponent())) {
+                    category.tiles.remove(j--);
+                }
+            }
+        }
+    }
+
+    private void tryInitCategories(Context context) {
+        if (mCategories == null) {
+            mTileByComponentCache.clear();
+            mCategoryByKeyMap.clear();
+            mCategories = TileUtils.getCategories(context, mTileByComponentCache,
+                    false /* categoryDefinedInManifest */);
+            for (DashboardCategory category : mCategories) {
+                mCategoryByKeyMap.put(category.key, category);
+            }
+        }
+    }
+
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java b/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java
index 53be0e6..3fc999f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java
@@ -16,15 +16,20 @@
 
 package com.android.settingslib.drawer;
 
+import android.content.ComponentName;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
+import android.util.Log;
 
 import java.util.ArrayList;
 import java.util.List;
 
 public class DashboardCategory implements Parcelable {
 
+    private static final String TAG = "DashboardCategory";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
     /**
      * Title of the category that is shown to the user.
      */
@@ -74,6 +79,22 @@
         return tiles.get(n);
     }
 
+    public boolean containsComponent(ComponentName component) {
+        for (Tile tile : tiles) {
+            if (TextUtils.equals(tile.intent.getComponent().getClassName(),
+                    component.getClassName())) {
+                if (DEBUG) {
+                    Log.d(TAG,  "category " + key + "contains component" + component);
+                }
+                return true;
+            }
+        }
+        if (DEBUG) {
+            Log.d(TAG,  "category " + key + " does not contain component" + component);
+        }
+        return false;
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index 05585e53e..50867eb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -33,7 +33,6 @@
 import android.provider.Settings;
 import android.support.annotation.VisibleForTesting;
 import android.support.v4.widget.DrawerLayout;
-import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.Pair;
@@ -64,12 +63,9 @@
 
     public static final String EXTRA_SHOW_MENU = "show_drawer_menu";
 
-    private static List<DashboardCategory> sDashboardCategories;
-    private static HashMap<Pair<String, String>, Tile> sTileCache;
     // Serves as a temporary list of tiles to ignore until we heard back from the PM that they
     // are disabled.
     private static ArraySet<ComponentName> sTileBlacklist = new ArraySet<>();
-    private static InterestingConfigChanges sConfigTracker;
 
     private final PackageReceiver mPackageReceiver = new PackageReceiver();
     private final List<CategoryListener> mCategoryListeners = new ArrayList<>();
@@ -80,6 +76,15 @@
     private boolean mShowingMenu;
     private UserManager mUserManager;
 
+    // Remove below after new IA
+    @Deprecated
+    private static List<DashboardCategory> sDashboardCategories;
+    @Deprecated
+    private static HashMap<Pair<String, String>, Tile> sTileCache;
+    @Deprecated
+    private static InterestingConfigChanges sConfigTracker;
+    // Remove above after new IA
+
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -105,7 +110,9 @@
             mDrawerLayout = null;
             return;
         }
-        getDashboardCategories();
+        if (!isDashboardFeatureEnabled()) {
+            getDashboardCategories();
+        }
         setActionBar(toolbar);
         mDrawerAdapter = new SettingsDrawerAdapter(this);
         ListView listView = (ListView) findViewById(R.id.left_drawer);
@@ -144,7 +151,11 @@
             filter.addDataScheme("package");
             registerReceiver(mPackageReceiver, filter);
 
-            new CategoriesUpdater().execute();
+            if (isDashboardFeatureEnabled()) {
+                new CategoriesUpdateTask().execute();
+            } else {
+                new CategoriesUpdater().execute();
+            }
         }
         final Intent intent = getIntent();
         if (intent != null) {
@@ -173,23 +184,23 @@
         if (componentName == null) {
             return false;
         }
-        // Look for a tile that has the same component as incoming intent
-        final List<DashboardCategory> categories = getDashboardCategories();
-        for (DashboardCategory category : categories) {
-            for (Tile tile : category.tiles) {
-                if (TextUtils.equals(tile.intent.getComponent().getClassName(),
-                        componentName.getClassName())) {
-                    if (DEBUG) {
-                        Log.d(TAG, "intent is for top level tile: " + tile.title);
-                    }
+        if (isDashboardFeatureEnabled()) {
+            final DashboardCategory homepageCategories = CategoryManager.get()
+                    .getTilesByCategory(this, CategoryKey.CATEGORY_HOMEPAGE);
+            return homepageCategories.containsComponent(componentName);
+        } else {
+            // Look for a tile that has the same component as incoming intent
+            final List<DashboardCategory> categories = getDashboardCategories();
+            for (DashboardCategory category : categories) {
+                if (category.containsComponent(componentName)) {
                     return true;
                 }
             }
+            if (DEBUG) {
+                Log.d(TAG, "Intent is not for top level settings " + intent);
+            }
+            return false;
         }
-        if (DEBUG) {
-            Log.d(TAG, "Intent is not for top level settings " + intent);
-        }
-        return false;
     }
 
     public void addCategoryListener(CategoryListener listener) {
@@ -255,7 +266,11 @@
             return;
         }
         // TODO: Do this in the background with some loading.
-        mDrawerAdapter.updateCategories();
+        if (isDashboardFeatureEnabled()) {
+            mDrawerAdapter.updateHomepageCategories();
+        } else {
+            mDrawerAdapter.updateCategories();
+        }
         if (mDrawerAdapter.getCount() != 0) {
             mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
         } else {
@@ -343,13 +358,6 @@
         }
     }
 
-    public HashMap<Pair<String, String>, Tile> getTileCache() {
-        if (sTileCache == null) {
-            getDashboardCategories();
-        }
-        return sTileCache;
-    }
-
     public void onProfileTileOpen() {
         finish();
     }
@@ -368,7 +376,11 @@
                     ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
                     : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                     PackageManager.DONT_KILL_APP);
-            new CategoriesUpdater().execute();
+            if (isDashboardFeatureEnabled()) {
+                new CategoriesUpdateTask().execute();
+            } else {
+                new CategoriesUpdater().execute();
+            }
         }
     }
 
@@ -376,6 +388,10 @@
         void onCategoriesChanged();
     }
 
+    /**
+     * @deprecated remove after new IA
+     */
+    @Deprecated
     private class CategoriesUpdater extends AsyncTask<Void, Void, List<DashboardCategory>> {
         @Override
         protected List<DashboardCategory> doInBackground(Void... params) {
@@ -408,10 +424,39 @@
         }
     }
 
+    private class CategoriesUpdateTask extends AsyncTask<Void, Void, Void> {
+
+        private final CategoryManager mCategoryManager;
+
+        public CategoriesUpdateTask() {
+            mCategoryManager = CategoryManager.get();
+        }
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            mCategoryManager.reloadAllCategoriesForConfigChange(SettingsDrawerActivity.this);
+            return null;
+        }
+
+        @Override
+        protected void onPostExecute(Void result) {
+            mCategoryManager.updateCategoryFromBlacklist(sTileBlacklist);
+            onCategoriesChanged();
+        }
+    }
+
+    protected boolean isDashboardFeatureEnabled() {
+        return false;
+    }
+
     private class PackageReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
-            new CategoriesUpdater().execute();
+            if (isDashboardFeatureEnabled()) {
+                new CategoriesUpdateTask().execute();
+            } else {
+                new CategoriesUpdater().execute();
+            }
         }
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
index 1d6197a..e1216a1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
@@ -37,6 +37,10 @@
         mActivity = activity;
     }
 
+    /**
+     * @deprecated Remove after new IA
+     */
+    @Deprecated
     void updateCategories() {
         List<DashboardCategory> categories = mActivity.getDashboardCategories();
         mItems.clear();
@@ -64,6 +68,27 @@
         notifyDataSetChanged();
     }
 
+    public void updateHomepageCategories() {
+        DashboardCategory category =
+                CategoryManager.get().getTilesByCategory(mActivity, CategoryKey.CATEGORY_HOMEPAGE);
+        mItems.clear();
+        // Spacer.
+        mItems.add(null);
+        Item tile = new Item();
+        tile.label = mActivity.getString(R.string.home);
+        tile.icon = Icon.createWithResource(mActivity, R.drawable.home);
+        mItems.add(tile);
+        for (int j = 0; j < category.tiles.size(); j++) {
+            tile = new Item();
+            Tile dashboardTile = category.tiles.get(j);
+            tile.label = dashboardTile.title;
+            tile.icon = dashboardTile.icon;
+            tile.tile = dashboardTile;
+            mItems.add(tile);
+        }
+        notifyDataSetChanged();
+    }
+
     public Tile getTile(int position) {
         return mItems.get(position) != null ? mItems.get(position).tile : null;
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index e70cc29..81f0e84 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -94,6 +94,13 @@
     private static final String EXTRA_CATEGORY_KEY = "com.android.settings.category";
 
     /**
+     * The key used to get the category from metadata of activities of action
+     * {@link #EXTRA_SETTINGS_ACTION}
+     * The value must be one of constants defined in {@code CategoryKey}.
+     */
+    private static final String EXTRA_IA_CATEGORY_KEY = "com.android.settings.iacategory";
+
+    /**
      * Name of the meta-data item that should be set in the AndroidManifest.xml
      * to specify the icon that should be displayed for the preference.
      */
@@ -113,8 +120,24 @@
 
     private static final String SETTING_PKG = "com.android.settings";
 
+    /**
+     * Build a list of DashboardCategory. Each category must be defined in manifest.
+     * eg: .Settings$DeviceSettings
+     * @deprecated
+     */
+    @Deprecated
     public static List<DashboardCategory> getCategories(Context context,
-            HashMap<Pair<String, String>, Tile> cache) {
+            Map<Pair<String, String>, Tile> cache) {
+        return getCategories(context, cache, true /*categoryDefinedInManifest*/);
+    }
+
+    /**
+     * Build a list of DashboardCategory.
+     * @param categoryDefinedInManifest If true, an dummy activity must exists in manifest to
+     * represent this category (eg: .Settings$DeviceSettings)
+     */
+    public static List<DashboardCategory> getCategories(Context context,
+            Map<Pair<String, String>, Tile> cache, boolean categoryDefinedInManifest) {
         final long startTime = System.currentTimeMillis();
         boolean setup = Global.getInt(context.getContentResolver(), Global.DEVICE_PROVISIONED, 0)
                 != 0;
@@ -134,11 +157,12 @@
                 getTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false);
             }
         }
+
         HashMap<String, DashboardCategory> categoryMap = new HashMap<>();
         for (Tile tile : tiles) {
             DashboardCategory category = categoryMap.get(tile.category);
             if (category == null) {
-                category = createCategory(context, tile.category);
+                category = createCategory(context, tile.category, categoryDefinedInManifest);
                 if (category == null) {
                     Log.w(LOG_TAG, "Couldn't find category " + tile.category);
                     continue;
@@ -157,9 +181,21 @@
         return categories;
     }
 
-    private static DashboardCategory createCategory(Context context, String categoryKey) {
+    /**
+     * Create a new DashboardCategory from key.
+     *
+     * @param context Context to query intent
+     * @param categoryKey The category key
+     * @param categoryDefinedInManifest If true, an dummy activity must exists in manifest to
+     * represent this category (eg: .Settings$DeviceSettings)
+     */
+    private static DashboardCategory createCategory(Context context, String categoryKey,
+            boolean categoryDefinedInManifest) {
         DashboardCategory category = new DashboardCategory();
         category.key = categoryKey;
+        if (!categoryDefinedInManifest) {
+            return category;
+        }
         PackageManager pm = context.getPackageManager();
         List<ResolveInfo> results = pm.queryIntentActivities(new Intent(categoryKey), 0);
         if (results.size() == 0) {
@@ -204,14 +240,19 @@
             ActivityInfo activityInfo = resolved.activityInfo;
             Bundle metaData = activityInfo.metaData;
             String categoryKey = defaultCategory;
-            if (checkCategory && ((metaData == null) || !metaData.containsKey(EXTRA_CATEGORY_KEY))
-                    && categoryKey == null) {
+            if (metaData != null && categoryKey == null) {
+                // categoryKey is null, try to get it from metadata.
+                if (metaData.containsKey(EXTRA_IA_CATEGORY_KEY)) {
+                    categoryKey = metaData.getString(EXTRA_IA_CATEGORY_KEY);
+                } else if (metaData.containsKey(EXTRA_CATEGORY_KEY)) {
+                    categoryKey = metaData.getString(EXTRA_CATEGORY_KEY);
+                }
+            }
+            if (checkCategory && categoryKey == null) {
                 Log.w(LOG_TAG, "Found " + resolved.activityInfo.name + " for intent "
                         + intent + " missing metadata "
                         + (metaData == null ? "" : EXTRA_CATEGORY_KEY));
                 continue;
-            } else {
-                categoryKey = metaData.getString(EXTRA_CATEGORY_KEY);
             }
             Pair<String, String> key = new Pair<String, String>(activityInfo.packageName,
                     activityInfo.name);
@@ -238,16 +279,6 @@
         }
     }
 
-    private static DashboardCategory getCategory(List<DashboardCategory> target,
-            String categoryKey) {
-        for (DashboardCategory category : target) {
-            if (categoryKey.equals(category.key)) {
-                return category;
-            }
-        }
-        return null;
-    }
-
     private static boolean updateTileData(Context context, Tile tile,
             ActivityInfo activityInfo, ApplicationInfo applicationInfo, PackageManager pm) {
         if (applicationInfo.isSystemApp()) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 61c1fe2..a514ebb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -49,8 +49,8 @@
 
 import java.util.ArrayList;
 import java.util.Iterator;
-import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
 
 
 public class AccessPoint implements Comparable<AccessPoint> {
@@ -95,6 +95,7 @@
     private static final String KEY_PSKTYPE = "key_psktype";
     private static final String KEY_SCANRESULTCACHE = "key_scanresultcache";
     private static final String KEY_CONFIG = "key_config";
+    private static final AtomicInteger sLastId = new AtomicInteger(0);
 
     /**
      * These values are matched in string arrays -- changes must be kept in sync
@@ -127,10 +128,13 @@
 
     private WifiInfo mInfo;
     private NetworkInfo mNetworkInfo;
-    private AccessPointListener mAccessPointListener;
+    AccessPointListener mAccessPointListener;
 
     private Object mTag;
 
+    // used to co-relate internal vs returned accesspoint.
+    int mId;
+
     public AccessPoint(Context context, Bundle savedState) {
         mContext = context;
         mConfig = savedState.getParcelable(KEY_CONFIG);
@@ -161,16 +165,46 @@
         update(mConfig, mInfo, mNetworkInfo);
         mRssi = getRssi();
         mSeen = getSeen();
+        mId = sLastId.incrementAndGet();
     }
 
     AccessPoint(Context context, ScanResult result) {
         mContext = context;
         initWithScanResult(result);
+        mId = sLastId.incrementAndGet();
     }
 
     AccessPoint(Context context, WifiConfiguration config) {
         mContext = context;
         loadConfig(config);
+        mId = sLastId.incrementAndGet();
+    }
+
+    AccessPoint(Context context, AccessPoint other) {
+        mContext = context;
+        copyFrom(other);
+    }
+
+    /**
+     * Copy accesspoint information. NOTE: We do not copy tag information because that is never
+     * set on the internal copy.
+     * @param that
+     */
+    void copyFrom(AccessPoint that) {
+        that.evictOldScanResults();
+        this.ssid = that.ssid;
+        this.bssid = that.bssid;
+        this.security = that.security;
+        this.networkId = that.networkId;
+        this.pskType = that.pskType;
+        this.mConfig = that.mConfig; //TODO: Watch out, this object is mutated.
+        this.mRssi = that.mRssi;
+        this.mSeen = that.mSeen;
+        this.mInfo = that.mInfo;
+        this.mNetworkInfo = that.mNetworkInfo;
+        this.mScanResultCache.clear();
+        this.mScanResultCache.putAll(that.mScanResultCache);
+        this.mId = that.mId;
     }
 
     @Override
@@ -426,7 +460,10 @@
             String format = mContext.getString(R.string.available_via_passpoint);
             summary.append(String.format(format, config.providerFriendlyName));
         } else if (config != null && config.hasNoInternetAccess()) {
-            summary.append(mContext.getString(R.string.wifi_no_internet));
+            int messageID = config.getNetworkSelectionStatus().isNetworkPermanentlyDisabled()
+                    ? R.string.wifi_no_internet_no_reconnect
+                    : R.string.wifi_no_internet;
+            summary.append(mContext.getString(messageID));
         } else if (config != null && !config.getNetworkSelectionStatus().isNetworkEnabled()) {
             WifiConfiguration.NetworkSelectionStatus networkStatus =
                     config.getNetworkSelectionStatus();
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 7d279eb..bfe8c07 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -29,10 +29,13 @@
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
+import android.os.ConditionVariable;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.util.Log;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
 import android.widget.Toast;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -62,30 +65,59 @@
     // TODO: Allow control of this?
     // Combo scans can take 5-6s to complete - set to 10s.
     private static final int WIFI_RESCAN_INTERVAL_MS = 10 * 1000;
+    private static final int NUM_SCANS_TO_CONFIRM_AP_LOSS = 3;
 
     private final Context mContext;
     private final WifiManager mWifiManager;
     private final IntentFilter mFilter;
     private final ConnectivityManager mConnectivityManager;
     private final NetworkRequest mNetworkRequest;
-    private WifiTrackerNetworkCallback mNetworkCallback;
-
     private final AtomicBoolean mConnected = new AtomicBoolean(false);
     private final WifiListener mListener;
     private final boolean mIncludeSaved;
     private final boolean mIncludeScans;
     private final boolean mIncludePasspoints;
-
     private final MainHandler mMainHandler;
     private final WorkHandler mWorkHandler;
 
+    private WifiTrackerNetworkCallback mNetworkCallback;
+
     private boolean mSavedNetworksExist;
     private boolean mRegistered;
-    private ArrayList<AccessPoint> mAccessPoints = new ArrayList<>();
-    private HashMap<String, Integer> mSeenBssids = new HashMap<>();
-    private HashMap<String, ScanResult> mScanResultCache = new HashMap<>();
+
+    /** Updated using main handler. Clone of this collection is returned
+     * from {@link #getAccessPoints()}
+     */
+    private final List<AccessPoint> mAccessPoints = new ArrayList<>();
+
+    /**
+     * Protects APs contained in {@link #mInternalAccessPoints} from being modified concurrently
+     * while its being read. Usage contract:
+     *
+     * 1. MainHandler opens the condition after copying the states thereby
+     *    allowing WorkerHandler to mutate the contents.
+     * 2. WorkerHandler after mutating the contents, sends a message to MainHandler to copy the
+     *    states and closes the condition.
+     *
+     * This is better than synchronizing on a variable because it prevents MainHandler from
+     * unnecessarily blocking/waiting to acquire lock for copying states. When MainHandler is about
+     * to access {@link #mInternalAccessPoints}, it is assumed that it has exclusively lock on the
+     * contents.
+     */
+    private final ConditionVariable mInternalAccessPointsWriteLock = new ConditionVariable(true);
+
+    /** Guarded by mInternalAccessPointsWriteLock, updated using worker handler.
+     * Never exposed outside this class.
+     */
+    private final List<AccessPoint> mInternalAccessPoints = new ArrayList<>();
+
+    //visible to both worker and main thread. Guarded by #mInternalAccessPoints
+    private final AccessPointListenerAdapter mAccessPointListenerAdapter
+            = new AccessPointListenerAdapter();
+
+    private final HashMap<String, Integer> mSeenBssids = new HashMap<>();
+    private final HashMap<String, ScanResult> mScanResultCache = new HashMap<>();
     private Integer mScanId = 0;
-    private static final int NUM_SCANS_TO_CONFIRM_AP_LOSS = 3;
 
     private NetworkInfo mLastNetworkInfo;
     private WifiInfo mLastInfo;
@@ -231,12 +263,11 @@
     }
 
     /**
-     * Gets the current list of access points.
+     * Gets the current list of access points. Should be called from main thread, otherwise
+     * expect inconsistencies
      */
     public List<AccessPoint> getAccessPoints() {
-        synchronized (mAccessPoints) {
-            return new ArrayList<>(mAccessPoints);
-        }
+        return new ArrayList<>(mAccessPoints);
     }
 
     public WifiManager getManager() {
@@ -316,8 +347,17 @@
     }
 
     private void updateAccessPoints() {
+        // Wait until main worker is done copying the states. This is done to prevent propagation
+        // of accesspoint states while the update is in progress.
+        long before = System.currentTimeMillis();
+        mInternalAccessPointsWriteLock.block();
+        if (DBG) {
+            Log.d(TAG, "Acquired AP lock on WorkerHandler. Time to wait = "
+                    + (System.currentTimeMillis() - before) + " ms.");
+        }
+
         // Swap the current access points into a cached list.
-        List<AccessPoint> cachedAccessPoints = getAccessPoints();
+        List<AccessPoint> cachedAccessPoints = new ArrayList<>(mInternalAccessPoints);
         ArrayList<AccessPoint> accessPoints = new ArrayList<>();
 
         // Clear out the configs so we don't think something is saved when it isn't.
@@ -325,7 +365,7 @@
             accessPoint.clearConfig();
         }
 
-        /** Lookup table to more quickly update AccessPoints by only considering objects with the
+        /* Lookup table to more quickly update AccessPoints by only considering objects with the
          * correct SSID.  Maps SSID -> List of AccessPoints with the given SSID.  */
         Multimap<String, AccessPoint> apMap = new Multimap<String, AccessPoint>();
         WifiConfiguration connectionConfig = null;
@@ -406,8 +446,8 @@
                     if (mLastInfo != null && mLastInfo.getBSSID() != null
                             && mLastInfo.getBSSID().equals(result.BSSID)
                             && connectionConfig != null && connectionConfig.isPasspoint()) {
-                        /* This network is connected via this passpoint config */
-                        /* SSID match is not going to work for it; so update explicitly */
+                    /* This network is connected via this passpoint config */
+                    /* SSID match is not going to work for it; so update explicitly */
                         accessPoint.update(connectionConfig);
                     }
 
@@ -422,12 +462,14 @@
 
         // Log accesspoints that were deleted
         if (DBG) Log.d(TAG, "------ Dumping SSIDs that were not seen on this scan ------");
-        for (AccessPoint prevAccessPoint : mAccessPoints) {
-            if (prevAccessPoint.getSsid() == null) continue;
+        for (AccessPoint prevAccessPoint : mInternalAccessPoints) {
+            if (prevAccessPoint.getSsid() == null)
+                continue;
             String prevSsid = prevAccessPoint.getSsidStr();
             boolean found = false;
             for (AccessPoint newAccessPoint : accessPoints) {
-                if (newAccessPoint.getSsid() != null && newAccessPoint.getSsid().equals(prevSsid)) {
+                if (newAccessPoint.getSsid() != null && newAccessPoint.getSsid()
+                        .equals(prevSsid)) {
                     found = true;
                     break;
                 }
@@ -435,10 +477,11 @@
             if (!found)
                 if (DBG) Log.d(TAG, "Did not find " + prevSsid + " in this scan");
         }
-        if (DBG)  Log.d(TAG, "---- Done dumping SSIDs that were not seen on this scan ----");
+        if (DBG) Log.d(TAG, "---- Done dumping SSIDs that were not seen on this scan ----");
 
-        mAccessPoints = accessPoints;
-        mMainHandler.sendEmptyMessage(MainHandler.MSG_ACCESS_POINT_CHANGED);
+        mInternalAccessPoints.clear();
+        mInternalAccessPoints.addAll(accessPoints);
+        mMainHandler.scheduleAPCopyingAndCloseWriteLock();
     }
 
     private AccessPoint getCachedOrCreate(ScanResult result, List<AccessPoint> cache) {
@@ -462,7 +505,9 @@
                 return ret;
             }
         }
-        return new AccessPoint(mContext, config);
+        AccessPoint accessPoint = new AccessPoint(mContext, config);
+        accessPoint.setListener(mAccessPointListenerAdapter);
+        return accessPoint;
     }
 
     private void updateNetworkInfo(NetworkInfo networkInfo) {
@@ -489,17 +534,24 @@
             connectionConfig = getWifiConfigurationForNetworkId(mLastInfo.getNetworkId());
         }
 
+        // Lock required to prevent accidental copying of AccessPoint states while the modification
+        // is in progress. see #copyAndNotifyListeners
+        long before = System.currentTimeMillis();
+        mInternalAccessPointsWriteLock.block();
+        if (DBG) {
+            Log.d(TAG, "Acquired AP lock on WorkerHandler for updating NetworkInfo. Wait time = " +
+                    (System.currentTimeMillis() - before) + "ms.");
+        }
+
         boolean reorder = false;
-        for (int i = mAccessPoints.size() - 1; i >= 0; --i) {
-            if (mAccessPoints.get(i).update(connectionConfig, mLastInfo, mLastNetworkInfo)) {
+        for (int i = mInternalAccessPoints.size() - 1; i >= 0; --i) {
+            if (mInternalAccessPoints.get(i).update(connectionConfig, mLastInfo, mLastNetworkInfo)) {
                 reorder = true;
             }
         }
         if (reorder) {
-            synchronized (mAccessPoints) {
-                Collections.sort(mAccessPoints);
-            }
-            mMainHandler.sendEmptyMessage(MainHandler.MSG_ACCESS_POINT_CHANGED);
+            Collections.sort(mInternalAccessPoints);
+            mMainHandler.scheduleAPCopyingAndCloseWriteLock();
         }
     }
 
@@ -512,6 +564,7 @@
         WifiTracker tracker = new WifiTracker(context,
                 null, null, includeSaved, includeScans, includePasspoints);
         tracker.forceUpdate();
+        tracker.copyAndNotifyListeners(false /*notifyListeners*/);
         return tracker.getAccessPoints();
     }
 
@@ -576,6 +629,7 @@
                     mListener.onWifiStateChanged(msg.arg1);
                     break;
                 case MSG_ACCESS_POINT_CHANGED:
+                    copyAndNotifyListeners(true /*notifyListeners*/);
                     mListener.onAccessPointsChanged();
                     break;
                 case MSG_RESUME_SCANNING:
@@ -590,6 +644,12 @@
                     break;
             }
         }
+
+        void scheduleAPCopyingAndCloseWriteLock() {
+            //prevent worker thread from modifying mInternalAccessPoints
+            mInternalAccessPointsWriteLock.close();
+            sendEmptyMessage(MSG_ACCESS_POINT_CHANGED);
+        }
     }
 
     private final class WorkHandler extends Handler {
@@ -725,4 +785,94 @@
          */
         void onAccessPointsChanged();
     }
+
+    /**
+     * Helps capture notifications that were generated during AccessPoint modification. Used later
+     * on by {@link #copyAndNotifyListeners(boolean)} to send notifications.
+     */
+    private static class AccessPointListenerAdapter implements AccessPoint.AccessPointListener {
+        static final int AP_CHANGED = 1;
+        static final int LEVEL_CHANGED = 2;
+
+        final SparseIntArray mPendingNotifications = new SparseIntArray();
+
+        @Override
+        public void onAccessPointChanged(AccessPoint accessPoint) {
+            int type = mPendingNotifications.get(accessPoint.mId);
+            mPendingNotifications.put(accessPoint.mId, type | AP_CHANGED);
+        }
+
+        @Override
+        public void onLevelChanged(AccessPoint accessPoint) {
+            int type = mPendingNotifications.get(accessPoint.mId);
+            mPendingNotifications.put(accessPoint.mId, type | LEVEL_CHANGED);
+        }
+    }
+
+    /**
+     * Responsible for copying access points from {@link #mInternalAccessPoints} and notifying
+     * accesspoint listeners. Mutation of the accesspoints returned is done on the main thread.
+     *
+     * @param notifyListeners if true, accesspoint listeners are notified, otherwise notifications
+     *                        dropped.
+     */
+    private void copyAndNotifyListeners(boolean notifyListeners) {
+        // Need to watch out for memory allocations on main thread.
+        SparseArray<AccessPoint> oldAccessPoints = new SparseArray<>();
+        SparseIntArray notificationMap = null;
+        List<AccessPoint> updatedAccessPoints = new ArrayList<>();
+
+        for (AccessPoint accessPoint : mAccessPoints) {
+            oldAccessPoints.put(accessPoint.mId, accessPoint);
+        }
+
+        //synchronize to prevent modification of "mInternalAccessPoints" by worker thread.
+        long before = System.currentTimeMillis();
+        try {
+            if (DBG) {
+                Log.d(TAG, "Starting to copy AP items on the MainHandler");
+            }
+            if (notifyListeners) {
+                notificationMap = mAccessPointListenerAdapter.mPendingNotifications.clone();
+            }
+
+            mAccessPointListenerAdapter.mPendingNotifications.clear();
+            for (AccessPoint internalAccessPoint : mInternalAccessPoints) {
+                AccessPoint accessPoint = oldAccessPoints.get(internalAccessPoint.mId);
+                if (accessPoint == null) {
+                    accessPoint = new AccessPoint(mContext, internalAccessPoint);
+                } else {
+                    accessPoint.copyFrom(internalAccessPoint);
+                }
+                updatedAccessPoints.add(accessPoint);
+            }
+        } finally {
+            mInternalAccessPointsWriteLock.open();
+            if (DBG) {
+                Log.d(TAG, "Opened AP Write lock on the MainHandler. Time to copy = " +
+                        (System.currentTimeMillis() - before) + " ms.");
+            }
+        }
+
+        mAccessPoints.clear();
+        mAccessPoints.addAll(updatedAccessPoints);
+
+        if (notificationMap != null && notificationMap.size() > 0) {
+            for (AccessPoint accessPoint : updatedAccessPoints) {
+                int notificationType = notificationMap.get(accessPoint.mId);
+                AccessPoint.AccessPointListener listener = accessPoint.mAccessPointListener;
+                if (notificationType == 0 || listener == null) {
+                    continue;
+                }
+
+                if ((notificationType & AccessPointListenerAdapter.AP_CHANGED) != 0) {
+                    listener.onAccessPointChanged(accessPoint);
+                }
+
+                if ((notificationType & AccessPointListenerAdapter.LEVEL_CHANGED) != 0) {
+                    listener.onLevelChanged(accessPoint);
+                }
+            }
+        }
+    }
 }
diff --git a/packages/SettingsLib/tests/AndroidManifest.xml b/packages/SettingsLib/tests/AndroidManifest.xml
index e6d133b..18bbbed 100644
--- a/packages/SettingsLib/tests/AndroidManifest.xml
+++ b/packages/SettingsLib/tests/AndroidManifest.xml
@@ -19,6 +19,7 @@
 
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
     <uses-permission android:name="android.permission.MANAGE_USERS" />
+    <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY"/>
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java b/packages/SettingsLib/tests/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java
new file mode 100644
index 0000000..ee03d50
--- /dev/null
+++ b/packages/SettingsLib/tests/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settingslib.utils;
+
+import android.net.NetworkPolicy;
+import android.net.NetworkPolicyManager;
+import android.net.NetworkTemplate;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import com.android.settingslib.NetworkPolicyEditor;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static junit.framework.Assert.assertEquals;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NetworkPolicyEditorTest {
+    private static final long MAX_LIMIT_BYTES = 500000;
+    private static final long TEST_LIMIT_BYTES = 2500;
+    private static final long[] WARNING_BYTES_LIST = {100, 1000, 2000, 3000, 40000};
+
+    private NetworkTemplate mNetworkTemplate;
+    private NetworkPolicyEditor mNetworkPolicyEditor;
+
+    @Before
+    public void setUp() {
+        mNetworkTemplate = NetworkTemplate.buildTemplateMobileAll("123456789123456");
+        NetworkPolicyManager policyManager = NetworkPolicyManager.from(InstrumentationRegistry
+                .getContext());
+        mNetworkPolicyEditor = new NetworkPolicyEditor(policyManager);
+    }
+
+    @Test
+    public void setPolicyWarningBytes_withoutLimit_shouldNotCapWarningBytes() {
+        // Set the limit to disable so we can change the warning bytes freely
+        mNetworkPolicyEditor.setPolicyLimitBytes(mNetworkTemplate, NetworkPolicy.LIMIT_DISABLED);
+
+        for (int i = 0; i < WARNING_BYTES_LIST.length; i++) {
+            mNetworkPolicyEditor.setPolicyWarningBytes(mNetworkTemplate, WARNING_BYTES_LIST[i]);
+            assertEquals(WARNING_BYTES_LIST[i],
+                    mNetworkPolicyEditor.getPolicyWarningBytes(mNetworkTemplate));
+        }
+    }
+
+    @Test
+    public void setPolicyWarningBytes_withLimit_shouldCapWarningBytes() {
+        // Set the limit bytes, so warning bytes cannot exceed the limit bytes.
+        mNetworkPolicyEditor.setPolicyLimitBytes(mNetworkTemplate, TEST_LIMIT_BYTES);
+
+        for (int i = 0; i < WARNING_BYTES_LIST.length; i++) {
+            mNetworkPolicyEditor.setPolicyWarningBytes(mNetworkTemplate, WARNING_BYTES_LIST[i]);
+            long expectedWarningBytes = Math.min(WARNING_BYTES_LIST[i], TEST_LIMIT_BYTES);
+            assertEquals(expectedWarningBytes,
+                    mNetworkPolicyEditor.getPolicyWarningBytes(mNetworkTemplate));
+        }
+    }
+
+    @Test
+    public void setPolicyLimitBytes_warningBytesSmallerThanLimit_shouldNotCapWarningBytes() {
+        long testWarningBytes = MAX_LIMIT_BYTES / 2;
+
+        mNetworkPolicyEditor.setPolicyLimitBytes(mNetworkTemplate, MAX_LIMIT_BYTES);
+        mNetworkPolicyEditor.setPolicyWarningBytes(mNetworkTemplate, testWarningBytes);
+
+        assertEquals(MAX_LIMIT_BYTES, mNetworkPolicyEditor.getPolicyLimitBytes(mNetworkTemplate));
+        assertEquals(testWarningBytes,
+                mNetworkPolicyEditor.getPolicyWarningBytes(mNetworkTemplate));
+    }
+
+    @Test
+    public void setPolicyLimitBytes_warningBytesBiggerThanLimit_shouldCapWarningBytes() {
+        long testWarningBytes = TEST_LIMIT_BYTES * 2;
+
+        mNetworkPolicyEditor.setPolicyLimitBytes(mNetworkTemplate, MAX_LIMIT_BYTES);
+        mNetworkPolicyEditor.setPolicyWarningBytes(mNetworkTemplate, testWarningBytes);
+        mNetworkPolicyEditor.setPolicyLimitBytes(mNetworkTemplate, TEST_LIMIT_BYTES);
+
+        assertEquals(TEST_LIMIT_BYTES, mNetworkPolicyEditor.getPolicyLimitBytes(mNetworkTemplate));
+        long expectedWarningBytes = Math.min(testWarningBytes, TEST_LIMIT_BYTES);
+        assertEquals(expectedWarningBytes,
+                mNetworkPolicyEditor.getPolicyWarningBytes(mNetworkTemplate));
+    }
+
+}
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/src/com/android/settingslib/wifi/AccessPointTest.java
index ec44b45..6481f4d 100644
--- a/packages/SettingsLib/tests/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -15,24 +15,42 @@
  */
 package com.android.settingslib.wifi;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiSsid;
 import android.os.Bundle;
+import android.os.SystemClock;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.text.SpannableString;
 import android.text.style.TtsSpan;
 
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import java.util.ArrayList;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class AccessPointTest {
 
     private static final String TEST_SSID = "test_ssid";
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getTargetContext();
+    }
 
     @Test
     public void testSsidIsTelephoneSpan() {
@@ -48,4 +66,53 @@
         assertEquals(1, spans.length);
         assertEquals(TtsSpan.TYPE_TELEPHONE, spans[0].getType());
     }
+
+    @Test
+    public void testCopyAccessPoint_dataShouldMatch() {
+        WifiConfiguration configuration = createWifiConfiguration();
+
+        NetworkInfo networkInfo =
+                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 2, "WIFI", "WIFI_SUBTYPE");
+        AccessPoint originalAccessPoint = new AccessPoint(mContext, configuration);
+        WifiInfo wifiInfo = new WifiInfo();
+        wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(configuration.SSID));
+        wifiInfo.setBSSID(configuration.BSSID);
+        originalAccessPoint.update(configuration, wifiInfo, networkInfo);
+        AccessPoint copy = new AccessPoint(mContext, originalAccessPoint);
+
+        assertEquals(originalAccessPoint.getSsid().toString(), copy.getSsid().toString());
+        assertEquals(originalAccessPoint.getBssid(), copy.getBssid());
+        assertSame(originalAccessPoint.getConfig(), copy.getConfig());
+        assertEquals(originalAccessPoint.getSecurity(), copy.getSecurity());
+        assertTrue(originalAccessPoint.compareTo(copy) == 0);
+    }
+
+    @Test
+    public void testThatCopyAccessPoint_scanCacheShouldMatch() {
+        Bundle bundle = new Bundle();
+        ArrayList<ScanResult> scanResults = new ArrayList<>();
+        for (int i = 0; i < 5; i++) {
+            ScanResult scanResult = new ScanResult();
+            scanResult.level = i;
+            scanResult.BSSID = "bssid-" + i;
+            scanResult.timestamp = SystemClock.elapsedRealtime() * 1000;
+            scanResults.add(scanResult);
+        }
+
+        bundle.putParcelableArrayList("key_scanresultcache", scanResults);
+        AccessPoint original = new AccessPoint(mContext, bundle);
+        assertEquals(4, original.getRssi());
+        AccessPoint copy = new AccessPoint(mContext, createWifiConfiguration());
+        assertEquals(Integer.MIN_VALUE, copy.getRssi());
+        copy.copyFrom(original);
+        assertEquals(original.getRssi(), copy.getRssi());
+    }
+
+    private WifiConfiguration createWifiConfiguration() {
+        WifiConfiguration configuration = new WifiConfiguration();
+        configuration.BSSID = "bssid";
+        configuration.SSID = "ssid";
+        configuration.networkId = 123;
+        return configuration;
+    }
 }
diff --git a/packages/Shell/Android.mk b/packages/Shell/Android.mk
index 81ab2ff..2170cc1 100644
--- a/packages/Shell/Android.mk
+++ b/packages/Shell/Android.mk
@@ -5,8 +5,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 \
-        android-support-documents-archive
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
 
 LOCAL_PACKAGE_NAME := Shell
 LOCAL_CERTIFICATE := platform
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index f1789ea..227d0e9 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -114,6 +114,8 @@
     <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
     <!-- Permission needed to rename bugreport notifications (so they're not shown as Shell) -->
     <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
+    <!-- Permission needed to hold a wakelock in dumpstate.cpp (drop_root_user()) -->
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
 
     <application android:label="@string/app_label"
                  android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 18c7dbe..772c344 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -180,7 +180,7 @@
     /** System property (and value) used to stop dumpstate. */
     // TODO: should call ActiveManager API instead
     private static final String CTL_STOP = "ctl.stop";
-    private static final String BUGREPORT_SERVICE = "bugreportplus";
+    private static final String BUGREPORT_SERVICE = "bugreport";
 
     /**
      * Directory on Shell's data storage where screenshots will be stored.
diff --git a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
index 9fd80d3..b9b77a4 100644
--- a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
+++ b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
@@ -27,7 +27,6 @@
 import android.provider.DocumentsContract.Document;
 import android.provider.DocumentsContract.Root;
 import android.provider.DocumentsProvider;
-import android.support.provider.DocumentArchiveHelper;
 import android.webkit.MimeTypeMap;
 
 import java.io.File;
@@ -48,12 +47,10 @@
     };
 
     private File mRoot;
-    private DocumentArchiveHelper mArchiveHelper;
 
     @Override
     public boolean onCreate() {
         mRoot = new File(getContext().getFilesDir(), "bugreports");
-        mArchiveHelper = new DocumentArchiveHelper(this, (char) 0);
         return true;
     }
 
@@ -72,10 +69,6 @@
     @Override
     public Cursor queryDocument(String documentId, String[] projection)
             throws FileNotFoundException {
-        if (mArchiveHelper.isArchivedDocument(documentId)) {
-            return mArchiveHelper.queryDocument(documentId, projection);
-        }
-
         final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
         if (DOC_ID_ROOT.equals(documentId)) {
             final RowBuilder row = result.newRow();
@@ -94,11 +87,6 @@
     public Cursor queryChildDocuments(
             String parentDocumentId, String[] projection, String sortOrder)
             throws FileNotFoundException {
-        if (mArchiveHelper.isArchivedDocument(parentDocumentId) ||
-                mArchiveHelper.isSupportedArchiveType(getDocumentType(parentDocumentId))) {
-            return mArchiveHelper.queryChildDocuments(parentDocumentId, projection, sortOrder);
-        }
-
         final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
         if (DOC_ID_ROOT.equals(parentDocumentId)) {
             final File[] files = mRoot.listFiles();
@@ -116,10 +104,6 @@
     public ParcelFileDescriptor openDocument(
             String documentId, String mode, CancellationSignal signal)
             throws FileNotFoundException {
-        if (mArchiveHelper.isArchivedDocument(documentId)) {
-            return mArchiveHelper.openDocument(documentId, mode, signal);
-        }
-
         if (ParcelFileDescriptor.parseMode(mode) != ParcelFileDescriptor.MODE_READ_ONLY) {
             throw new FileNotFoundException("Failed to open: " + documentId + ", mode = " + mode);
         }
@@ -182,10 +166,6 @@
     private void addFileRow(MatrixCursor result, File file) {
         String mimeType = getTypeForName(file.getName());
         int flags = Document.FLAG_SUPPORTS_DELETE;
-        if (mArchiveHelper.isSupportedArchiveType(mimeType)) {
-            flags |= Document.FLAG_ARCHIVE;
-        }
-
         final RowBuilder row = result.newRow();
         row.add(Document.COLUMN_DOCUMENT_ID, getDocIdForFile(file));
         row.add(Document.COLUMN_MIME_TYPE, mimeType);
diff --git a/packages/SystemUI/plugin/ExamplePlugin/AndroidManifest.xml b/packages/SystemUI/plugin/ExamplePlugin/AndroidManifest.xml
index bd2c71c..ff89bbc 100644
--- a/packages/SystemUI/plugin/ExamplePlugin/AndroidManifest.xml
+++ b/packages/SystemUI/plugin/ExamplePlugin/AndroidManifest.xml
@@ -21,7 +21,15 @@
     <uses-permission android:name="com.android.systemui.permission.PLUGIN" />
 
     <application>
-        <service android:name=".SampleOverlayPlugin">
+        <activity android:name=".PluginSettings"
+            android:label="@string/plugin_label">
+            <intent-filter>
+                <action android:name="com.android.systemui.action.PLUGIN_SETTINGS" />
+            </intent-filter>
+        </activity>
+
+        <service android:name=".SampleOverlayPlugin"
+            android:label="@string/plugin_label">
             <intent-filter>
                 <action android:name="com.android.systemui.action.PLUGIN_OVERLAY" />
             </intent-filter>
diff --git a/packages/SystemUI/plugin/ExamplePlugin/res/layout/plugin_settings.xml b/packages/SystemUI/plugin/ExamplePlugin/res/layout/plugin_settings.xml
new file mode 100644
index 0000000..eb90283
--- /dev/null
+++ b/packages/SystemUI/plugin/ExamplePlugin/res/layout/plugin_settings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+-->
+
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:textAppearance="?android:attr/textAppearanceLarge"
+    android:text="@string/plugin_settings_here"
+    android:gravity="center" />
diff --git a/packages/SystemUI/plugin/ExamplePlugin/res/values/strings.xml b/packages/SystemUI/plugin/ExamplePlugin/res/values/strings.xml
new file mode 100644
index 0000000..a0bfe84
--- /dev/null
+++ b/packages/SystemUI/plugin/ExamplePlugin/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <string name="plugin_settings_here" translatable="false">Plugin settings go here</string>
+    <string name="plugin_label" translatable="false">Overlay Plugin</string>
+
+</resources>
diff --git a/packages/SystemUI/plugin/ExamplePlugin/src/com/android/systemui/plugin/testoverlayplugin/PluginSettings.java b/packages/SystemUI/plugin/ExamplePlugin/src/com/android/systemui/plugin/testoverlayplugin/PluginSettings.java
new file mode 100644
index 0000000..cf39075
--- /dev/null
+++ b/packages/SystemUI/plugin/ExamplePlugin/src/com/android/systemui/plugin/testoverlayplugin/PluginSettings.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.plugin.testoverlayplugin;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * DO NOT Reference Plugin interfaces here, this runs in the plugin APK's process
+ * and is only for modifying settings.
+ */
+public class PluginSettings extends Activity {
+
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.plugin_settings);
+    }
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/IntentButtonProvider.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/IntentButtonProvider.java
new file mode 100644
index 0000000..1b8efa7
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/IntentButtonProvider.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.plugins;
+
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+
+/**
+ * An Intent Button represents a triggerable element in SysUI that consists of an
+ * Icon and an intent to trigger when it is activated (clicked, swiped, etc.).
+ */
+public interface IntentButtonProvider extends Plugin {
+
+    public static final int VERSION = 1;
+
+    public IntentButton getIntentButton();
+
+    public interface IntentButton {
+        public static class IconState {
+            public boolean isVisible = true;
+            public CharSequence contentDescription = null;
+            public Drawable drawable;
+        }
+
+        public IconState getIcon();
+
+        public Intent getIntent();
+    }
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
index 2a7139c..495771a 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
@@ -24,7 +24,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.net.Uri;
-import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
@@ -163,6 +162,7 @@
             switch (msg.what) {
                 case PLUGIN_CONNECTED:
                     if (DEBUG) Log.d(TAG, "onPluginConnected");
+                    PluginPrefs.setHasPlugins(mContext);
                     PluginInfo<T> info = (PluginInfo<T>) msg.obj;
                     info.mPlugin.onCreate(mContext, info.mPluginContext);
                     mListener.onPluginConnected(info.mPlugin);
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java
index aa0b3c5..4bf6494 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java
@@ -37,6 +37,7 @@
     private final Context mContext;
     private final PluginInstanceManagerFactory mFactory;
     private final boolean isDebuggable;
+    private final PluginPrefs mPluginPrefs;
 
     private PluginManager(Context context) {
         this(context, new PluginInstanceManagerFactory(), Build.IS_DEBUGGABLE,
@@ -51,6 +52,7 @@
         mBackgroundThread = new HandlerThread("Plugins");
         mBackgroundThread.start();
         isDebuggable = debuggable;
+        mPluginPrefs = new PluginPrefs(mContext);
 
         PluginExceptionHandler uncaughtExceptionHandler = new PluginExceptionHandler(
                 defaultHandler);
@@ -68,6 +70,7 @@
             // Never ever ever allow these on production builds, they are only for prototyping.
             return;
         }
+        mPluginPrefs.addAction(action);
         PluginInstanceManager p = mFactory.createPluginInstanceManager(mContext, action, listener,
                 allowMultiple, mBackgroundThread.getLooper(), version);
         p.startListening();
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginPrefs.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginPrefs.java
new file mode 100644
index 0000000..3671b3c
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginPrefs.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.plugins;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.util.ArraySet;
+
+import java.util.Set;
+
+/**
+ * Storage for all plugin actions in SharedPreferences.
+ *
+ * This allows the list of actions that the Tuner needs to search for to be generated
+ * instead of hard coded.
+ */
+public class PluginPrefs {
+
+    private static final String PREFS = "plugin_prefs";
+
+    private static final String PLUGIN_ACTIONS = "actions";
+    private static final String HAS_PLUGINS = "plugins";
+
+    private final Set<String> mPluginActions;
+    private final SharedPreferences mSharedPrefs;
+
+    public PluginPrefs(Context context) {
+        mSharedPrefs = context.getSharedPreferences(PREFS, 0);
+        mPluginActions = new ArraySet<>(mSharedPrefs.getStringSet(PLUGIN_ACTIONS, null));
+    }
+
+    public Set<String> getPluginList() {
+        return mPluginActions;
+    }
+
+    public synchronized void addAction(String action) {
+        if (mPluginActions.add(action)){
+            mSharedPrefs.edit().putStringSet(PLUGIN_ACTIONS, mPluginActions).commit();
+        }
+    }
+
+    public static boolean hasPlugins(Context context) {
+        return context.getSharedPreferences(PREFS, 0).getBoolean(HAS_PLUGINS, false);
+    }
+
+    public static void setHasPlugins(Context context) {
+        context.getSharedPreferences(PREFS, 0).edit().putBoolean(HAS_PLUGINS, true).commit();
+    }
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainer.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainer.java
new file mode 100644
index 0000000..3270587
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainer.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.plugins.qs;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.RelativeLayout;
+
+public abstract class QSContainer extends FrameLayout {
+
+    public static final String ACTION = "com.android.systemui.action.PLUGIN_QS";
+
+    // This should be incremented any time this class or ActivityStarter or BaseStatusBarHeader
+    // change in incompatible ways.
+    public static final int VERSION = 1;
+
+    public QSContainer(@NonNull Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public abstract void setPanelView(HeightListener notificationPanelView);
+    public abstract BaseStatusBarHeader getHeader();
+
+    public abstract int getQsMinExpansionHeight();
+    public abstract int getDesiredHeight();
+    public abstract void setHeightOverride(int desiredHeight);
+    public abstract void setHeaderClickable(boolean qsExpansionEnabled);
+    public abstract boolean isCustomizing();
+    public abstract void setOverscrolling(boolean overscrolling);
+    public abstract void setExpanded(boolean qsExpanded);
+    public abstract void setListening(boolean listening);
+    public abstract boolean isShowingDetail();
+    public abstract void closeDetail();
+    public abstract void setKeyguardShowing(boolean keyguardShowing);
+    public abstract void animateHeaderSlidingIn(long delay);
+    public abstract void animateHeaderSlidingOut();
+    public abstract void setQsExpansion(float qsExpansionFraction, float headerTranslation);
+    public abstract void setHeaderListening(boolean listening);
+    public abstract void notifyCustomizeChanged();
+
+    public abstract void setContainer(ViewGroup container);
+
+    public interface HeightListener {
+        void onQsHeightChanged();
+    }
+
+    public interface Callback {
+        void onShowingDetail(DetailAdapter detail, int x, int y);
+        void onToggleStateChanged(boolean state);
+        void onScanStateChanged(boolean state);
+    }
+
+    public interface DetailAdapter {
+        CharSequence getTitle();
+        Boolean getToggleState();
+        default boolean getToggleEnabled() {
+            return true;
+        }
+        View createDetailView(Context context, View convertView, ViewGroup parent);
+        Intent getSettingsIntent();
+        void setToggleState(boolean state);
+        int getMetricsCategory();
+
+        /**
+         * Indicates whether the detail view wants to have its header (back button, title and
+         * toggle) shown.
+         */
+        default boolean hasHeader() { return true; }
+    }
+
+    public abstract static class BaseStatusBarHeader extends RelativeLayout {
+
+        public BaseStatusBarHeader(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+
+        public abstract int getCollapsedHeight();
+        public abstract int getExpandedHeight();
+
+        public abstract void setExpanded(boolean b);
+        public abstract void setExpansion(float headerExpansionFraction);
+        public abstract void setListening(boolean listening);
+        public abstract void updateEverything();
+        public abstract void setActivityStarter(ActivityStarter activityStarter);
+        public abstract void setCallback(Callback qsPanelCallback);
+        public abstract View getExpandView();
+    }
+
+    /**
+     * An interface to start activities. This is used to as a callback from the views to
+     * {@link PhoneStatusBar} to allow custom handling for starting the activity, i.e. dismissing the
+     * Keyguard.
+     */
+    public static interface ActivityStarter {
+
+        void startPendingIntentDismissingKeyguard(PendingIntent intent);
+        void startActivity(Intent intent, boolean dismissShade);
+        void startActivity(Intent intent, boolean dismissShade, Callback callback);
+        void preventNextAnimation();
+
+        interface Callback {
+            void onActivityStarted(int resultCode);
+        }
+    }
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java
new file mode 100644
index 0000000..09879d8
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.plugins.statusbar.phone;
+
+import android.annotation.DrawableRes;
+import android.annotation.Nullable;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.systemui.plugins.Plugin;
+
+public interface NavBarButtonProvider extends Plugin {
+
+    public static final String ACTION = "com.android.systemui.action.PLUGIN_NAV_BUTTON";
+
+    public static final int VERSION = 1;
+
+    /**
+     * Returns a view in the nav bar.  If the id is set "back", "home", "recent_apps", "menu",
+     * or "ime_switcher", it is expected to implement ButtonInterface.
+     */
+    public View createView(String spec, ViewGroup parent);
+
+    /**
+     * Interface for button actions.
+     */
+    interface ButtonInterface {
+        void setImageResource(@DrawableRes int resId);
+
+        void setImageDrawable(@Nullable Drawable drawable);
+
+        void abortCurrentGesture();
+
+        void setLandscape(boolean landscape);
+
+        void setCarMode(boolean carMode);
+    }
+}
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml b/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
index b78d3bf..f63dfb12 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -15,15 +15,17 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="32.0dp"
-        android:height="32.0dp"
+        android:width="32dp"
+        android:height="32dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
-        android:fillAlpha="0.3"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
     <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+    <path
+        android:pathData="M17.700001,8.000000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
+        android:fillColor="#4DFFFFFF"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
index e055de7..7fb423e 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -15,18 +15,20 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="32.0dp"
-        android:height="32.0dp"
+        android:width="32dp"
+        android:height="32dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M10.0,14.6l-8.0,8.0l8.0,0.0l0,-8z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.7,20.0l2.0,0.0l0.0,2.0l-2.0,0.0z"/>
     <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
-        android:fillAlpha="0.3"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.7,10.0l2.0,0.0l0.0,8.1l-2.0,0.0z"/>
     <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#4DFFFFFF"
+        android:pathData="M17.7,8.0l4.299999,0.0 0.0,-6.0 -20.0,20.0 15.700001,0.0z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
index 8a48817..3358d65 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -15,18 +15,20 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="32.0dp"
-        android:height="32.0dp"
+        android:width="32dp"
+        android:height="32dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M14.0,10.6l-12.0,12.0l12.0,0.0L14.0,10.6z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
     <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
-        android:fillAlpha="0.3"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
     <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M13.900000,10.000000l-11.900000,12.000000 11.900000,0.000000z"/>
+    <path
+        android:pathData="M17.700001,8.000000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
+        android:fillColor="#4DFFFFFF"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
index 39cc94c..63838a9 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -15,18 +15,20 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="32.0dp"
-        android:height="32.0dp"
+        android:width="32dp"
+        android:height="32dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
-        android:fillAlpha="0.3"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.700001,19.900000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
     <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.700001,9.900000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
     <path
-        android:pathData="M14.1,14.1l2.9,0.0 0.0,-6.5 -15.0,15.0 12.1,0.0z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M16.700001,7.200000l-14.700001,14.700000 14.700001,0.000000z"/>
+    <path
+        android:pathData="M17.700001,7.900000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
+        android:fillColor="#4DFFFFFF"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
index 012e95e..76690cc 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -15,14 +15,17 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="32.0dp"
-        android:height="32.0dp"
+        android:width="32dp"
+        android:height="32dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
     <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M2.000000,22.000000l15.700001,0.000000 0.000000,-14.000000 4.299999,0.000000 0.000000,-6.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
index e6f9292..50c427e 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -14,15 +14,17 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="24.0"
+        android:width="32.0dp"
+        android:height="29.5dp"
+        android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillAlpha="0.3"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#4DFFFFFF"
+        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.200000,-1.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
     <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
index d423ccb..a2d11a0 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -14,18 +14,20 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="24.0"
+        android:width="32.0dp"
+        android:height="29.5dp"
+        android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M13.8,13.2c-0.1,0.0 -0.3,-0.1 -0.4,-0.1c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,0.0 -0.6,-0.1 -0.9,-0.1c0.0,0.0 0.0,0.0 -0.1,0.0c0.0,0.0 0.0,0.0 0.0,0.0s0.0,0.0 0.0,0.0c0.0,0.0 0.0,0.0 -0.1,0.0c-0.3,0.0 -0.6,0.0 -0.9,0.1c-0.1,0.0 -0.3,0.0 -0.4,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.1,0.0 -0.1,0.0 -0.2,0.1c-1.6,0.5 -2.7,1.3 -2.8,1.5l5.3,6.6l0.0,0.0l0.0,0.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.700002,13.2z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#4DFFFFFF"
+        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
     <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillAlpha="0.3"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M13.000000,22.000000l5.500000,-6.800000c-0.200000,-0.200000 -2.300000,-1.900000 -5.500000,-1.900000s-5.300000,1.800000 -5.500000,1.900000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
     <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
index 1982130..f2043fc 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -14,18 +14,20 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="24.0"
+        android:width="32.0dp"
+        android:height="29.5dp"
+        android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M13.8,12.2l4.9,0.0c-1.0,-0.7 -3.4,-2.2 -6.7,-2.2c-4.1,0.0 -6.9,2.2 -7.2,2.5l7.2,9.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.800001,12.2z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#4DFFFFFF"
+        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
     <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillAlpha="0.3"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.000000,11.600000c-1.300000,-0.700000 -3.400000,-1.600000 -6.000000,-1.600000c-4.400000,0.000000 -7.300000,2.400000 -7.600000,2.700000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,11.600000z"/>
     <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.800001,1.9 -1.800001,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
index b350111..b7a4f4c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -14,18 +14,20 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="24.0"
+        android:width="32.0dp"
+        android:height="29.5dp"
+        android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M13.8,12.2l5.7,0.0l1.0,-1.2C20.0,10.6 16.8,8.0 12.0,8.0s-8.0,2.6 -8.5,3.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#4DFFFFFF"
+        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
     <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillAlpha="0.3"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.000000,8.600000c-1.600000,-0.700000 -3.600000,-1.300000 -6.000000,-1.300000c-5.300000,0.000000 -8.900000,3.000000 -9.200000,3.200000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.600000z"/>
     <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
index 136a004..35a9138 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -14,14 +14,17 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="24.0"
+        android:width="32.0dp"
+        android:height="29.5dp"
+        android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
     <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_0.xml b/packages/SystemUI/res/drawable/stat_sys_signal_0.xml
index 8bc872a..643c4f9 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_0.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_0.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -15,14 +15,17 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="17.0dp"
-        android:height="17.0dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
-        android:fillColor="?attr/backgroundColor"/>
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
     <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="?attr/fillColor"/>
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+    <path
+        android:pathData="M17.700001,8.000000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
+        android:fillColor="?attr/backgroundColor"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
index 8fa7630..64781c3 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -15,17 +15,20 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="17.0dp"
-        android:height="17.0dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M10.0,14.6l-8.0,8.0l8.0,0.0l0,-8z"
-        android:fillColor="?attr/fillColor"/>
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M19.7,20.0l2.0,0.0l0.0,2.0l-2.0,0.0z"/>
     <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
-        android:fillColor="?attr/backgroundColor"/>
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M19.7,10.0l2.0,0.0l0.0,8.1l-2.0,0.0z"/>
     <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="?attr/fillColor"/>
+        android:fillColor="?attr/backgroundColor"
+        android:pathData="M17.7,8.0l4.299999,0.0 0.0,-6.0 -20.0,20.0 15.700001,0.0z"/>
+    <path
+        android:fillColor="?attr/fillColor"
+        android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_2.xml b/packages/SystemUI/res/drawable/stat_sys_signal_2.xml
index 2a660a3..eb2be08 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_2.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_2.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -15,17 +15,20 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="17.0dp"
-        android:height="17.0dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M14.0,10.6l-12.0,12.0l12.0,0.0L14.0,10.6z"
-        android:fillColor="?attr/fillColor"/>
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
     <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+    <path
+        android:fillColor="?attr/fillColor"
+        android:pathData="M13.900000,10.000000l-11.900000,12.000000 11.900000,0.000000z"/>
+    <path
+        android:pathData="M17.700001,8.000000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
         android:fillColor="?attr/backgroundColor"/>
-    <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="?attr/fillColor"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_3.xml b/packages/SystemUI/res/drawable/stat_sys_signal_3.xml
index 9e0a433..22afad0 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_3.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_3.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -15,17 +15,20 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="17.0dp"
-        android:height="17.0dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M19.700001,19.900000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+    <path
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M19.700001,9.900000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+    <path
+        android:fillColor="?attr/fillColor"
+        android:pathData="M16.700001,7.200000l-14.700001,14.700000 14.700001,0.000000z"/>
+    <path
+        android:pathData="M17.700001,7.900000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
         android:fillColor="?attr/backgroundColor"/>
-    <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="?attr/fillColor"/>
-    <path
-        android:pathData="M14.1,14.1l2.9,0.0 0.0,-6.5 -15.0,15.0 12.1,0.0z"
-        android:fillColor="?attr/fillColor"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_4.xml b/packages/SystemUI/res/drawable/stat_sys_signal_4.xml
index 01f6703..d1e866d 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_4.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_4.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -15,14 +15,18 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="17.0dp"
-        android:height="17.0dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
+
     <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
-        android:fillColor="?attr/fillColor"/>
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
     <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="?attr/fillColor"/>
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+    <path
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M2.000000,22.000000l15.700001,0.000000 0.000000,-14.000000 4.299999,0.000000 0.000000,-6.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml
index 2de2e36..7f1b715e 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -15,13 +15,16 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="18.41dp"
-        android:height="18.41dp"
-        android:viewportWidth="24.0"
+        android:height="17dp"
+        android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillColor="?attr/backgroundColor"/>
+        android:fillColor="?attr/backgroundColor"
+        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.200000,-1.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
     <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z"
-        android:fillColor="?attr/fillColor"/>
+        android:fillColor="?attr/fillColor"
+        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+    <path
+        android:fillColor="?attr/fillColor"
+        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml
index 144a7c1..acd89be 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -15,16 +15,19 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="18.41dp"
-        android:height="18.41dp"
-        android:viewportWidth="24.0"
+        android:height="17dp"
+        android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M13.8,13.2c-0.1,0.0 -0.3,-0.1 -0.4,-0.1c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,0.0 -0.6,-0.1 -0.9,-0.1c0.0,0.0 0.0,0.0 -0.1,0.0c0.0,0.0 0.0,0.0 0.0,0.0s0.0,0.0 0.0,0.0c0.0,0.0 0.0,0.0 -0.1,0.0c-0.3,0.0 -0.6,0.0 -0.9,0.1c-0.1,0.0 -0.3,0.0 -0.4,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.1,0.0 -0.1,0.0 -0.2,0.1c-1.6,0.5 -2.7,1.3 -2.8,1.5l5.3,6.6l0.0,0.0l0.0,0.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.700002,13.2z"
-        android:fillColor="?attr/fillColor"/>
+        android:fillColor="?attr/backgroundColor"
+        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
     <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillColor="?attr/backgroundColor"/>
+        android:fillColor="?attr/fillColor"
+        android:pathData="M13.000000,22.000000l5.500000,-6.800000c-0.200000,-0.200000 -2.300000,-1.900000 -5.500000,-1.900000s-5.300000,1.800000 -5.500000,1.900000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
     <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z"
-        android:fillColor="?attr/fillColor"/>
+        android:fillColor="?attr/fillColor"
+        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+    <path
+        android:fillColor="?attr/fillColor"
+        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml
index 6b7f712..f33b25c 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -15,16 +15,19 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="18.41dp"
-        android:height="18.41dp"
-        android:viewportWidth="24.0"
+        android:height="17dp"
+        android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M13.8,12.2l4.9,0.0c-1.0,-0.7 -3.4,-2.2 -6.7,-2.2c-4.1,0.0 -6.9,2.2 -7.2,2.5l7.2,9.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.800001,12.2z"
-        android:fillColor="?attr/fillColor"/>
+        android:fillColor="?attr/backgroundColor"
+        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
     <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillColor="?attr/backgroundColor"/>
+        android:fillColor="?attr/fillColor"
+        android:pathData="M19.000000,11.600000c-1.300000,-0.700000 -3.400000,-1.600000 -6.000000,-1.600000c-4.400000,0.000000 -7.300000,2.400000 -7.600000,2.700000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,11.600000z"/>
     <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.800001,1.9 -1.800001,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
-        android:fillColor="?attr/fillColor"/>
+        android:fillColor="?attr/fillColor"
+        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+    <path
+        android:fillColor="?attr/fillColor"
+        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml
index d34b4de..09d2e50 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -15,16 +15,19 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="18.41dp"
-        android:height="18.41dp"
-        android:viewportWidth="24.0"
+        android:height="17dp"
+        android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M13.8,12.2l5.7,0.0l1.0,-1.2C20.0,10.6 16.8,8.0 12.0,8.0s-8.0,2.6 -8.5,3.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillColor="?attr/fillColor"/>
+        android:fillColor="?attr/backgroundColor"
+        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
     <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillColor="?attr/backgroundColor"/>
+        android:fillColor="?attr/fillColor"
+        android:pathData="M19.000000,8.600000c-1.600000,-0.700000 -3.600000,-1.300000 -6.000000,-1.300000c-5.300000,0.000000 -8.900000,3.000000 -9.200000,3.200000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.600000z"/>
     <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
-        android:fillColor="?attr/fillColor"/>
+        android:fillColor="?attr/fillColor"
+        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+    <path
+        android:fillColor="?attr/fillColor"
+        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml
index 5701356..fb1f584 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2014 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -15,13 +15,16 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="18.41dp"
-        android:height="18.41dp"
-        android:viewportWidth="24.0"
+        android:height="17dp"
+        android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillColor="?attr/fillColor"/>
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
     <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
-        android:fillColor="?attr/fillColor"/>
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+    <path
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/layout/emergency_cryptkeeper_text.xml b/packages/SystemUI/res/layout/emergency_cryptkeeper_text.xml
new file mode 100644
index 0000000..0a1730a
--- /dev/null
+++ b/packages/SystemUI/res/layout/emergency_cryptkeeper_text.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<com.android.systemui.statusbar.policy.EmergencyCryptkeeperText
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/emergency_cryptkeeper_text"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+        android:paddingStart="6dp"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:gravity="center_vertical|start"
+        />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 26c7339..9e0a6fe 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -13,7 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.systemui.qs.QSContainer
+<com.android.systemui.qs.QSContainerImpl
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/quick_settings_container"
         android:layout_width="match_parent"
@@ -38,4 +38,4 @@
     <include android:id="@+id/qs_customize" layout="@layout/qs_customize_panel"
         android:visibility="gone" />
 
-</com.android.systemui.qs.QSContainer>
+</com.android.systemui.qs.QSContainerImpl>
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 1978a93..c8e5b61 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -30,8 +30,8 @@
         android:id="@+id/lock_to_app_fab"
         android:layout_width="@dimen/recents_lock_to_app_size"
         android:layout_height="@dimen/recents_lock_to_app_size"
-        android:layout_gravity="bottom|right"
-        android:layout_marginRight="15dp"
+        android:layout_gravity="bottom|end"
+        android:layout_marginEnd="15dp"
         android:layout_marginBottom="15dp"
         android:translationZ="4dp"
         android:contentDescription="@string/recents_lock_to_app_button_label"
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 39c16d7..63af3e0 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -77,4 +77,11 @@
         </com.android.keyguard.AlphaOptimizedLinearLayout>
     </LinearLayout>
 
+    <ViewStub
+        android:id="@+id/emergency_cryptkeeper_text"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout="@layout/emergency_cryptkeeper_text"
+    />
+
 </com.android.systemui.statusbar.phone.PhoneStatusBarView>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 3d70969..0339e03 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -19,7 +19,7 @@
 
 <com.android.systemui.statusbar.phone.NotificationPanelView 
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/notification_panel"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -39,14 +39,15 @@
         android:clipToPadding="false"
         android:clipChildren="false">
 
-        <com.android.systemui.AutoReinflateContainer
+        <com.android.systemui.PluginInflateContainer
             android:id="@+id/qs_auto_reinflate_container"
             android:layout="@layout/qs_panel"
             android:layout_width="@dimen/notification_panel_width"
             android:layout_height="match_parent"
             android:layout_gravity="@integer/notification_panel_layout_gravity"
             android:clipToPadding="false"
-            android:clipChildren="false" />
+            android:clipChildren="false"
+            systemui:viewType="com.android.systemui.plugins.qs.QSContainer" />
 
         <com.android.systemui.statusbar.stack.NotificationStackScrollLayout
             android:id="@+id/notification_stack_scroller"
diff --git a/packages/SystemUI/res/layout/tuner_widget_settings_switch.xml b/packages/SystemUI/res/layout/tuner_widget_settings_switch.xml
new file mode 100644
index 0000000..c89c02f
--- /dev/null
+++ b/packages/SystemUI/res/layout/tuner_widget_settings_switch.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:gravity="center_vertical">
+
+    <ImageView
+        android:id="@+id/settings"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/ic_settings"
+        android:tint="@android:color/black"
+        android:padding="12dp"
+        android:background="?android:attr/selectableItemBackgroundBorderless" />
+
+    <View
+        android:id="@+id/divider"
+        android:layout_width="1dp"
+        android:layout_height="30dp"
+        android:layout_marginEnd="8dp"
+        android:background="?android:attr/listDivider" />
+
+    <Switch
+        android:id="@android:id/switch_widget"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:focusable="false"
+        android:clickable="false"
+        android:background="@null" />
+</LinearLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index ec77d77..9fc0b6e 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data is laat wag"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Sellulêre data is onderbreek"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data is onderbreek"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Omdat die gestelde dataperk bereik is, het die toestel datagebruik vir die res van hierdie siklus onderbreek.\n\nAs dit hervat word, kan dit tot heffings deur jou diensverskaffer lei."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Hervat"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Geen internetverbinding nie"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi gekoppel"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 9e00b7a..0e49ab96 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4ጂ ውሂብ ላፍታ ቆሟል"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"የተንቀሳቃሽ ስልክ ውሂብ ላፍታ ቆሟል"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ውሂብ ላፍታ ቆሟል"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"የእርስዎ የተዋቀረው የውሂብ ገደብ ላይ ስለተደረሰ፣ የዚህን ዑደት አጠቃቀም ለማስታወስ መሣሪያው ላፍታ ቆሟል።\n\nከቆመበት ማስቀጠሉ ከእርስዎ የአገልግሎት አቅራቢ ክፍያን ሊያስጠይቅዎት ይችላል።"</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"ከቆመበት ቀጥል"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"ምንም በይነመረብ ተያያዥ የለም።"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi ተያይዟል"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 93c46472..abd32b7 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -241,7 +241,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"تم إيقاف بيانات شبكة الجيل الرابع مؤقتًا"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"تم إيقاف بيانات شبكة الجوّال مؤقتًا"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"تم إيقاف البيانات مؤقتًا"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"نظرًا لأنك بلغت الحد الأقصى المحدد للبيانات، فقد أوقف الجهاز استخدام البيانات مؤقتًا في بقية هذه الدورة.\n\nومن الممكن أن يؤدي الاستئناف إلى تحصيل رسوم من قِبل مشغِّل شبكة الجوّال."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"استئناف"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"لا يوجد اتصال إنترنت"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"‏Wi-Fi متصل"</string>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index 1096108..ca54794 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G məlumatlarına fasilə verildi"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobil məlumatlara fasilə verildi"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Məlumatlara fasilə verildi"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Məlumatlar dəsti limitinizi keçdiyiniz üçün cihaz bu dövrənin qalan hissəsi üçün məlumatların istifadəsinə fasilə verib.\n\nDavam etmək operaturunuzdan xərclərə səbəb ola bilər."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Davam et"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"İnternet bağlantısı yoxdur"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi qoşulub"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index d184130..d22928d 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -238,7 +238,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G podaci su pauzirani"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobilni podaci su pauzirani"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Podaci su pauzirani"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Zbog toga što ste dostigli podešeno ograničenje za podatke, uređaj je pauzirao korišćenje podataka tokom ostatka ovog ciklusa.\n\nAko nastavite, mobilni operater može da vam naplati dodatne troškove."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Nastavi"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Nema internet veze"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi je povezan"</string>
diff --git a/packages/SystemUI/res/values-be-rBY/strings.xml b/packages/SystemUI/res/values-be-rBY/strings.xml
index cc71580..c215680 100644
--- a/packages/SystemUI/res/values-be-rBY/strings.xml
+++ b/packages/SystemUI/res/values-be-rBY/strings.xml
@@ -241,7 +241,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Перадача даных 4G прыпынена"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Мабільная перадача даных прыпынена"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Перадача даных прыпынена"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Быў дасягнуты ліміт перадачы даных, таму прылада прыпыніла перадачу даных на астатнюю частку гэтага цыкла.\n\nУзнаўленне перадачы можа прывесці да спагнання платы вашым аператарам."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Узнавіць"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Няма падключэння да Iнтэрнэту"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi падключаны"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 42ac038..c2a2a92 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Данните от 4G са поставени на пауза"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Мобилните данни са поставени на пауза"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Данните са поставени на пауза"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Тъй като зададеното от вас ограничение за данни бе достигнато, устройството постави преноса им на пауза за остатъка от този цикъл.\n\nВъзобновяването може да доведе до таксуване от оператора ви."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Възобновяване"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Няма връзка с интернет"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: Има връзка"</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 1467eea..5ed264e 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G ডেটা বিরতি দেওয়া হয়েছে"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"সেলুলার ডেটা বিরতি দেওয়া হয়েছে"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ডেট বিরতি দেওয়া হয়েছে"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"আপনার সেট ডেটার সীমা অবধি পৌঁছনোর কারনে ডিভাইস এই চক্রের অবশিষ্টাংশের জন্য ডেটা ব্যবহারে বিরতি দেওয়া হয়েছে৷ \n\nপুনরায় চালু করা হলে পরিষেবা প্রদানকারীর দ্বারা চার্জের করা হতে পারে৷"</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"পুনঃসূচনা করুন"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"কোনো ইন্টারনেট সংযোগ নেই"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"ওয়াই-ফাই সংযুক্ত হয়েছে"</string>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml
index 349098a..c621ecd 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings.xml
@@ -238,7 +238,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G prijenos podataka je pauzirano"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobilni podaci su pauzirani"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Prijenos podataka je pauziran"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Dostigli ste postavljeno ograničenje prijenosa podataka pa je uređaj zaustavio prijenos podataka za preostali dio ovog ciklusa.\n\nAko nastavite, operater vam može naplatiti dodatne troškove."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Nastavi"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Nema internet veze"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi veza aktivna"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index b764bf6..882c8e3 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Les dades 4G estan aturades"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Les dades mòbils estan aturades"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Les dades estan aturades"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Com que has arribat al límit de dades establert, s\'ha aturat l\'ús de dades del dispositiu per a la resta d\'aquest cicle.\n\nSi el reprens, l\'operador de telefonia mòbil pot aplicar càrrecs."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Reprèn"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"No hi ha connexió a Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: connectada"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index a829fe7..216e763 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -241,7 +241,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data 4G jsou pozastavena"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobilní data jsou pozastavena"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data jsou pozastavena"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Protože jste dosáhli nastaveného limitu dat, zařízení využití dat pro zbytek tohoto cyklu pozastavilo.\n\nObnovení může vést k poplatkům od operátora."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Pokračovat"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Žádné přip. k internetu"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: připojeno"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 64046e7..77727bb 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data er sat på pause"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobildata er sat på pause"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data er sat på pause"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Eftersom din fastsatte datagrænse blev nået, har enheden sat dataforbruget på pause i den resterende del af cyklussen.\n\nHvis du genaktiverer dataforbruget, kan det medføre gebyrer fra dit mobilselskab."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Genoptag"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ingen internetforb."</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi er forbundet"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 134e41f..5aa99a1 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-Daten pausiert"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobilfunkdaten pausiert"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Daten pausiert"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Da dein festgelegtes Datenlimit erreicht wurde, hat das Gerät die Datennutzung für den Rest dieses Zeitraums pausiert.\n\nWenn du die Nutzung fortsetzt, entstehen möglicherweise Kosten bei deinem Mobilfunkanbieter."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Fortsetzen"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Keine Internetverbindung"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"WLAN verbunden"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index b108543..4c5718b 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Τα δεδομένα 4G τέθηκαν σε παύση"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Τα δεδομένα κινητής τηλεφωνίας τέθηκαν σε παύση"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Τα δεδομένα τέθηκαν σε παύση"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Επειδή συμπληρώθηκε το όριο των δεδομένων που ορίστηκε για τη συσκευή σας, η χρήση δεδομένων τέθηκε σε παύση για το υπόλοιπο αυτού του κύκλου.\n\nΗ εκ νέου ενεργοποίησή τους ενδέχεται να επιφέρει χρεώσεις από την εταιρεία κινητής τηλεφωνίας σας."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Συνέχιση"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Χωρ. σύνδ. στο Διαδ."</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi συνδεδεμένο"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 776e043..d12b448 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data is paused"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobile data is paused"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data is paused"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Because your set data limit was reached, the device has paused data usage for the remainder of this cycle.\n\nResuming may lead to charges from your operator."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Resume"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"No Internet connection"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi connected"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 776e043..d12b448 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data is paused"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobile data is paused"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data is paused"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Because your set data limit was reached, the device has paused data usage for the remainder of this cycle.\n\nResuming may lead to charges from your operator."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Resume"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"No Internet connection"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi connected"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 776e043..d12b448 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data is paused"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobile data is paused"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data is paused"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Because your set data limit was reached, the device has paused data usage for the remainder of this cycle.\n\nResuming may lead to charges from your operator."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Resume"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"No Internet connection"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi connected"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index abaeafe..45198cf 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Datos 4G pausados"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Datos móviles pausados"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Datos pausados"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Debido que se alcanzó el límite de datos establecido, el dispositivo pausó el uso de datos para el resto de este ciclo.\n\nLa reanudación podría tener como resultado cargos del proveedor."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Reanudar"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Sin conexión a Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi conectado"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index bfb37b6..3d69e5e 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Datos 4G pausados"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Datos móviles pausados"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Datos pausados"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Has alcanzado el límite de datos establecido, por lo que el dispositivo ha pausado el uso de datos para el resto de este ciclo.\n\nSi lo reanudas, el operador puede facturar cargos."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Reanudar"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Sin conexión a Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Con conexión Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index ac55422..17cbc13 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G andmekasutus on peatatud"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobiilse andmeside kasutus on peatatud"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Andmekasutus on peatatud"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Kuna jõudsite andmemahu määratud piirini, peatas seade andmekasutuse ülejäänud tsükliks.\n\nJätkamisel võivad lisanduda operaatoritasud."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Jätka"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Interneti-ühendus puudub"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"WiFi on ühendatud"</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index e0912e5..5715c506 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G datuen erabilera eten da"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Sare mugikorreko datuen erabilera eten da"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Datuen erabilera eten da"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Zehaztuta duzun datuen erabilera-mugara iritsi zarenez, gailuak datuen erabilera eten du zikloa amaitzen den arte.\n\nDatuak erabiltzen jarraitzen baduzu, gastu gehiago ordaindu beharko dizkiozu agian operadoreari."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Jarraitu erabiltzen"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ez duzu Interneteko konexiorik"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi konektatuta"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index df8ba8c..d92b4c0 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"‏داده 4G موقتاً متوقف شده است"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"داده شبکه همراه موقتاً متوقف شده است"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"داده موقتاً متوقف شده است"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"چون به محدودیت داده تنظیم شده رسیده‌اید، دستگاه مصرف داده را برای باقیمانده این دوره موقتاً متوقف کرده است.\n\nاگر ادامه دهید شاید موجب کسر هزینه از طرف شرکت مخابراتی شما شود."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"از سر‌گیری"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"اتصال اینترنتی ندارید"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"‏Wi-Fi متصل شد"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index d157472..7bb7dd6 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-tiedonsiirto keskeytettiin"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobiilitiedonsiirto keskeytettiin"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Tiedonsiirto keskeytettiin"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Määrittämäsi tiedonsiirtorajoitus saavutettiin, ja laite keskeytti tiedonsiirron tämän kauden loppuajaksi.\n\nOperaattorisi voi veloittaa sinulta lisämaksun, jos jatkat tiedonsiirtoa."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Jatka"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ei internetyhteyttä"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi yhdistetty"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 465de96..b0215bd 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Données 4G désactivées"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Données cellulaires désactivées"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Données désactivées"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Vous avez atteint le quota de données maximal. La consommation des données a donc été interrompue pour la fin de la période de facturation en cours.\n\nSi vous réactivez les données, votre fournisseur de services risque de vous facturer des frais supplémentaires."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Reprendre"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Aucune connexion Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Connecté au Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 3ed8977..2a37637 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Données 4G désactivées"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Données mobiles désactivées"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Données désactivées"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Vous avez atteint le quota de données maximal. La consommation des données a donc été interrompue pour la fin de la période de facturation en cours.\n\nSi vous réactivez les données, votre opérateur risque de vous facturer des frais supplémentaires."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Réactiver"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Aucune connexion Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Connecté au Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index dafe79d..40c5ca7 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Os datos 4G están en pausa"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Os datos de móbiles están en pausa"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Os datos están en pausa"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Como acadaches o límite de datos definido, o dispositivo puxo en pausa o uso de datos para o resto do ciclo.\n\nSe retomas o uso, poden aplicarse cargos do operador."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Retomar"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Sen Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi conectada"</string>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index b230bac..5b3c9c2 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G ડેટા થોભાવ્યો છે"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"સેલ્યુલર ડેટા થોભાવ્યો છે"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ડેટા થોભાવ્યો છે"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"તમે સેટ કરેલ ડેટા મર્યાદા સુધી પહોંચી ગયા હોવાથી, ઉપકરણે આ ચક્રના શેષ માટે ડેટા વપરાશ થોભાવ્યો છે.\n\nફરીથી શરૂ કરવું તમારા કેરીઅર તરફથી શુલ્ક તરફ દોરી શકે છે."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"ફરી શરૂ કરો"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"કોઈ ઇન્ટરનેટ કનેક્શન નથી"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi કનેક્ટ કર્યું"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index c781403..217a5f1 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G डेटा रोक दिया गया है"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"सेल्युलर डेटा रोक दिया गया है"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"डेटा रोक दिया गया है"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"चूंकि आपके निर्धारित डेटा की सीमा, सीमा पर पहुंच गई थी, इसलिए डिवाइस ने इस चक्र के रिमाइंडर के लिए डेटा उपयोग को रोक दिया है.\n\nफिर से शुरू करने से आपके वाहक की ओर से शुल्क लगाया जाता है."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"फिर से शुरू करें"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"कोई इंटरनेट कनेक्शन नहीं"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"वाई-फ़ाई  कनेक्‍ट किया गया"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 1de9f78..a9815d5 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -238,7 +238,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G podaci pauzirani"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobilni podaci pauzirani"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Podaci su pauzirani"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Budući da je dosegnuto postavljeno ograničenje podataka, uređaj je pauzirao upotrebu podataka za preostali dio ovog ciklusa.\n\nMobilni operater može naplatiti daljnju upotrebu."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Nastavi"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Nema internetske veze"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi povezan"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 6d699ad..9fd4eb7 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"A 4G adatforgalom szünetel"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"A mobilhálózati adatforgalom szünetel"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Az adatforgalom szünetel"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Mivel elérte a beállított adatkorlátot, az eszköz a ciklus fennmaradó részére felfüggesztette az adathasználatot.\n\nHa mégis használja az adatkapcsolatot, akkor szolgáltatója többletköltséget számíthat fel."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Folytatás"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Nincs internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi csatlakoztatva"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index e08ec46..236663d 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4Գ տվյալների օգտագործումը դադարեցված է"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Բջջային տվյալների օգտագործումը դադարեցված է"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Տվյալների օգտագործումը դադարեցված է"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Քանի որ ձեր սահմանված տվյալների սահմանաչափը սպառվել է, սարքն այլևս չի օգտագործի տվյալները այս ցիկլի մնացած ընթացքում:\n\nԵթե վերսկսեք, հնարավոր է կիրառվեն գանձումներ ձեր օպերատորի կողմից:"</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Վերսկսել"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ինտերնետ կապ չկա"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi-ը միացված է"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index de4b68d..5e26008 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data 4G dijeda"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Data seluler dijeda"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data dijeda"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Karena batas data yang disetel telah tercapai, perangkat telah menjeda penggunaan data selama sisa waktu siklus ini.\n\nMelanjutkan dapat mengakibatkan tagihan dari operator."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Lanjutkan"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Tidak ada sambungan internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi tersambung"</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 9b1e139..02b59b6 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Slökkt er á 4G-gögnum"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Slökkt er á farsímagögnum"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Slökkt er á gagnanotkun"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Þar sem gagnahámarkinu var náð hefur tækið slökkt á gagnanotkun það sem eftir er af þessu tímabili.\n\nEf þú heldur áfram kann það að leiða til kostnaðar frá símafyrirtækinu."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Halda áfram"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Engin nettenging"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi tengt"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index f207e43..9d76477 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Dati 4G sospesi"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Dati cellulari sospesi"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Dati sospesi"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Hai raggiunto il tuo limite di dati, pertanto sul dispositivo è stato sospeso l\'utilizzo di dati per la parte rimanente del ciclo.\n\nSe riprendi a utilizzare i dati, l\'operatore potrebbe addebitarti costi."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Riprendi"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Nessuna connessione"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi connesso"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 6462ae5..3429497 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"‏השימוש בנתוני 4G מושהה"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"השימוש בנתונים סלולריים מושהה"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"השימוש בנתונים מושהה"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"מכיוון שהגעת למגבלת הנתונים שהגדרת, המכשיר השהה את השימוש בנתונים עד סוף התקופה.\n\nאם תמשיך, אתה עשוי לקבל חיובים מהספק."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"המשך"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"אין חיבור לאינטרנט"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"‏Wi-Fi מחובר"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index fd59bc5..bbd8033 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4Gデータは一時停止中です"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"モバイルデータは一時停止中です"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"データの一時停止"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"設定されたデータの上限に達したため、このサイクルの終了までこの端末でのデータの利用を一時停止しました。\n\n再開すると、携帯通信会社から課金される可能性があります。"</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"再開"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"インターネット未接続"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi接続済み"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 28e37ca..c00c54c 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G მონაცემები შეჩერებულია"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"ფიჭური მონაცემები შეჩერებულია"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"მონაცემები შეჩერებულია"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"რადგან თქვენი მონაცემების ლიმიტი ამოწურულია, მოწყობილობამ შეაჭერა მონაცემების გამოყენება დარჩენილი ციკლისათვის. \n\n შეჯამაბ შეიძლება გამოიწვიოს თქვენს პროვაიდერთან დამატებითი ხარჯები."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"გაგრძელება"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"ინტერნეტ კავშირი არ არის"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi დაკავშირებულია"</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index ad25a1c..8051cd8 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G деректері кідіртілді"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Ұялы деректер кідіртілді"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Деректер кідіртілді"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Орнатылған деректер шегіне жеткендіктен, құрылғы осы циклдың қалған бөлігі бойы деректерді пайдалануды кідіртті.\n\nЖалғастыру оператор ақыларына әкелуі мүмкін."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Жалғастыру"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Интернет байланысы жоқ"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi қосулы"</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 76a8f59..c0d002c 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"ទិន្នន័យ 4G ត្រូវបានផ្អាក"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"ទិន្នន័យចល័តត្រូវបានផ្អាក"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ទិន្នន័យត្រូវបានផ្អាក"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"ដោយសារទិន្នន័យរបស់អ្នកបានឈានដល់កំណត់ ឧបករណ៍នេះបានផ្អាកការប្រើប្រាស់ទិន្នន័យសម្រាប់ការរំលឹកនៃវគ្គនេះ។\n\nការបន្តប្រើប្រាស់អាចនាំឲ្យមានការគិតប្រាក់ពីក្រុមហ៊ុនផ្តល់សេវាកម្ម។"</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"បន្ត"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"គ្មាន​ការ​តភ្ជាប់​អ៊ីនធឺណិត"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"បាន​ភ្ជាប់​វ៉ាយហ្វាយ"</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 0e5fd38..e1c42d7 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G ಡೇಟಾ ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"ಸೆಲ್ಯುಲಾರ್ ಡೇಟಾ ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ಡೇಟಾ ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"ಏಕೆಂದರೆ ನಿಮ್ಮ ಹೊಂದಾಣಿಕೆ ಡೇಟಾ ಮೀತಿಯನ್ನು ತಲುಪಿದೆ, ಈ ಆವರ್ತನೆಯ ಉಳಿದ ಭಾಗಕ್ಕೆ ಸಾಧನವು ಡೇಟಾ ಬಳಕೆಯನ್ನು ವಿರಾಮಗೊಳಿಸಿದೆ.\n\nಮುಂದುವರೆಯುವಿಕೆಯು ನಿಮ್ಮ ವಾಹಕದ ಶುಲ್ಕಗಳಿಗೆ ಕಾರಣವಾಗಬಹುದು."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"ಮುಂದುವರಿಸು"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವಿಲ್ಲ"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"ವೈ-ಫೈ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
@@ -592,8 +593,8 @@
     <string name="add_button" msgid="4134946063432258161">"ಬಟನ್ ಸೇರಿಸು"</string>
     <string name="save" msgid="2311877285724540644">"ಉಳಿಸು"</string>
     <string name="reset" msgid="2448168080964209908">"ಮರುಹೊಂದಿಸು"</string>
-    <string name="no_home_title" msgid="1563808595146071549">"ಯಾವುದೇ ಹೋಮ್ ಬಟನ್ ಕಂಡುಬಂದಿಲ್ಲ"</string>
-    <string name="no_home_message" msgid="5408485011659260911">"ಈ ಸಾಧನವನ್ನು ನ್ಯಾವಿಗೇಟ್ ಮಾಡಲು ಹೋಮ್ ಬಟನ್ ಅಗತ್ಯವಿರುತ್ತದೆ. ಉಳಿಸುವ ಮೊದಲು ದಯವಿಟ್ಟು ಹೋಮ್ ಬಟನ್ ಸೇರಿಸಿ."</string>
+    <string name="no_home_title" msgid="1563808595146071549">"ಯಾವುದೇ ಮುಖಪುಟ ಬಟನ್ ಕಂಡುಬಂದಿಲ್ಲ"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"ಈ ಸಾಧನವನ್ನು ನ್ಯಾವಿಗೇಟ್ ಮಾಡಲು ಮುಖಪುಟ ಬಟನ್ ಅಗತ್ಯವಿರುತ್ತದೆ. ಉಳಿಸುವ ಮೊದಲು ದಯವಿಟ್ಟು ಮುಖಪುಟ ಬಟನ್ ಸೇರಿಸಿ."</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"ಬಟನ್ ಅಳತೆ ಹೊಂದಿಸು"</string>
     <string name="clipboard" msgid="1313879395099896312">"ಕ್ಲಿಪ್‌ಬೋರ್ಡ್"</string>
     <string name="clipboard_description" msgid="3819919243940546364">"ಐಟಂಗಳನ್ನು ನೇರವಾಗಿ ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ಗೆ ಡ್ರ್ಯಾಗ್ ಮಾಡಲು ಕ್ಲಿಪ್‌ಬೋರ್ಡ್ ಅನುಮತಿಸುತ್ತದೆ. ಐಟಂಗಳು ಅಸ್ತಿತ್ವದಲ್ಲಿರುವಾಗ ಅವುಗಳನ್ನು ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ನಿಂದ ನೇರವಾಗಿ ಹೊರಗೆ ಹಾಕಬಹುದಾಗಿರುತ್ತದೆ."</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings_tv.xml b/packages/SystemUI/res/values-kn-rIN/strings_tv.xml
index 5afb322..edaa8e6 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings_tv.xml
@@ -25,7 +25,7 @@
     <string name="pip_pause" msgid="8412075640017218862">"ವಿರಾಮ"</string>
     <string name="pip_hold_home" msgid="340086535668778109">"PIP ನಿಯಂತ್ರಿಸಲು "<b>"HOME"</b>" ಕೀಯನ್ನು ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
     <string name="pip_onboarding_title" msgid="7850436557670253991">"ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರ"</string>
-    <string name="pip_onboarding_description" msgid="4028124563309465267">"ನೀವು ಮತ್ತೊಂದನ್ನು ಪ್ಲೇ ಮಾಡುವ ತನಕ ಇದು ನಿಮ್ಮ ವೀಡಿಯೋವನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿರಿಸುತ್ತದೆ. ಅದನ್ನು ನಿಯಂತ್ರಿಸಲು "<b>"ಹೋಮ್"</b>" ಅನ್ನು ಒತ್ತಿ ಹಿಡಿಯಿರಿ."</string>
+    <string name="pip_onboarding_description" msgid="4028124563309465267">"ನೀವು ಮತ್ತೊಂದನ್ನು ಪ್ಲೇ ಮಾಡುವ ತನಕ ಇದು ನಿಮ್ಮ ವೀಡಿಯೋವನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿರಿಸುತ್ತದೆ. ಅದನ್ನು ನಿಯಂತ್ರಿಸಲು "<b>"ಮುಖಪುಟ"</b>" ಅನ್ನು ಒತ್ತಿ ಹಿಡಿಯಿರಿ."</string>
     <string name="pip_onboarding_button" msgid="3957426748484904611">"ಅರ್ಥವಾಯಿತು"</string>
     <string name="recents_tv_dismiss" msgid="3555093879593377731">"ವಜಾಗೊಳಿಸಿ"</string>
   <string-array name="recents_tv_blacklist_array">
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index d477412..1c97212 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G 데이터 사용 중지됨"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"모바일 데이터 사용 중지됨"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"데이터 사용 중지됨"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"설정된 데이터 한도에 도달했기 때문에 기기에서 사이클의 나머지 기간 동안 데이터 사용을 일시 중지했습니다. \n\n데이터 사용을 재개하면 이동통신사 요금이 청구될 수 있습니다."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"재개"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"인터넷에 연결되지 않음"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi 연결됨"</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index b84bea2..b17f523 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G дайындары тындырылды"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Уюлдук дайындар тындырылды"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Дайындар тындырылды"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Киргизиле турган дайындар белгиленген эң жогорку чекке жеткендиктен, ушул мерчимдин калган бөлүгүндө түзмөгүңүздө дайындардын колдонулушу тындырылды.\n\nУлантсаңыз, байланыш операторуңузга акы төлөп калышыңыз мүмкүн."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Улантуу"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Интернет байланыш жок"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi байланышта"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index f1be8b3..0dc3d50 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"ຂໍ້​ມູນ 4G ຢຸດ​ຊົ່ວ​ຄາວແລ້ວ"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"ຂໍ້​ມູນເຊວ​ລູ​ລາຢຸດ​ຊົ່ວ​ຄາວແລ້ວ"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ຂໍ້​ມູນ​ຢຸດ​ຊົ່ວ​ຄາວແລ້ວ"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"ເນື່ອງ​ຈາກວ່າ​ຮອດ​ຂີດ​ຈຳ​ກັດ​ຂໍ້​ມູນ​ທີ່​ຕັ້ງ​ໄວ້​ຂອ​ງ​ທ່ານ​ແລ້ວ, ອຸ​ປະ​ກອນ​ຢຸດ​ການ​ນຳ​ໃຊ້​ຂໍ້​ມູນ​ສຳ​ລັບ​ສ່ວນ​ທີ່​ຍັງ​ເຫຼືອ​ຂອງ​ຮອບ​ວຽນ​ນີ້.\n\nການ​ເລີ່ມ​ຕໍ່​ອາດ​ຈະ​ນຳ​ໄປ​ສູ່​ການ​ປ່ຽນ​ແປງ​ຈາກ​ຜູ້​ໃຫ້​ບໍ​ລິ​ການ​ເຄືອ​ຂ່າຍ​ຂອງ​ທ່ານ."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"ເລີ່ມຕໍ່"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"ເຊື່ອມ​ຕໍ່ Wi-​-Fi ແລ້ວ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index d5d0631..dd2f198 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G duomenys pristabdyti"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Korinio ryšio duomenys pristabdyti"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Duomenys pristabdyti"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Kadangi buvo pasiektas nustatytas duomenų limitas, įrenginys pristabdė duomenų naudojimą likusį šio ciklo laikotarpį.\n\nAtnaujinus gali būti taikomi operatoriaus mokesčiai."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Atnaujinti"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Nėra interneto ryš."</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Prisij. prie „Wi-Fi“"</string>
@@ -274,10 +275,10 @@
     <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"„Bluetooth“ išjungta"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Nėra pasiekiamų susietų įrenginių"</string>
     <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Šviesumas"</string>
-    <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatinis kaitaliojimas"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatinis pasukimas"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Automatiškai sukti ekraną"</string>
     <string name="accessibility_quick_settings_rotation_value" msgid="1428962304214992318">"Nustatyti kaip <xliff:g id="ID_1">%s</xliff:g>"</string>
-    <string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Kaitaliojimas užrakintas"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Pasukimas užrakintas"</string>
     <string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"Stačias"</string>
     <string name="quick_settings_rotation_locked_landscape_label" msgid="8553157770061178719">"Gulsčias"</string>
     <string name="quick_settings_ime_label" msgid="7073463064369468429">"Įvesties metodas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 76d0da4..4242497 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -238,7 +238,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G datu lietojums ir apturēts"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobilo datu lietojums ir apturēts"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Datu lietojums ir apturēts"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Tika sasniegts iestatītais datu lietojuma ierobežojums, tādēļ ierīcē ir apturēts datu lietojums cikla atlikušajā periodā.\n\nJa atsāksiet lietot datus, iespējams, jūsu mobilo sakaru operators iekasēs maksu."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Atsākt"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Nav interneta sav."</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Izv. sav. ar Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index d7982c7..4091bbe 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Податоците 4G се паузирани"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Мобилните податоци се паузирани"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Податоците се паузирани"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Поради тоа што го достигнавте поставеното ограничување на податоци, уредот го паузираше користењето податоци до крајот на циклусот.\n\nОператорот може да ви наплати ако продолжите."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Продолжи"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Нема интернет"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Поврзано на Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 34aaa92..6ae547e 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G ഡാറ്റ താൽക്കാലികമായി നിർത്തി"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"സെല്ലുലാർ ഡാറ്റ താൽക്കാലികമായി നിർത്തി"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ഡാറ്റ താൽക്കാലികമായി നിർത്തി"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"നിങ്ങൾ നേരത്തെ ക്രമീകരിച്ച ഡാറ്റ പരിധിയിലെത്തിയതിനാൽ, ഈ സൈക്കിളിന്റെ അവശേഷിക്കുന്ന ഡാറ്റ ഉപയോഗം, ഉപകരണം താൽക്കാലികമായി നിർത്തി.\n\nപുനരാരംഭിക്കുന്നത്, നിങ്ങളുടെ കാരിയറിൽ നിന്ന് നിരക്കുകൾക്ക് ഇടയാക്കാം."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"പുനരാരംഭിക്കുക"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"ഇന്റർനെറ്റ് കണക്ഷൻ ഇല്ല"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"വൈഫൈ കണക്‌റ്റുചെയ്‌തു"</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 44f0125..95cbcae 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -235,7 +235,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G дата-г түр зогсоосон байна"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Гар утасны дата-г түр зогсоосон байна"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Дата-г түр зогсоосон байна"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Таны багц дата эрхийн дээд хэмжээнд хүрсэн байгаа тул төхөөрөмж нь үлдсэн хэсэгт дата хэрэглээг түр зогсоосон байна.\n\nТа үйлдлийг үргэлжлүүлэхийг хүсвэл үйлчилгээ үзүүлж буй үүрэн холбооны газраас нэмж дата эрх авна уу."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Үргэлжлүүлэх"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Интернет холболт байхгүй"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi холбогдсон"</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index eeb16c7..830cda4 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G डेटास विराम दिला आहे"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"सेल्युलर डेटास विराम दिला आहे"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"डेटास विराम दिला आहे"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"आपली सेट केलेली डेटा मर्यादा गाठल्यामुळे, डिव्हाइसने या चक्राच्या उर्वरित डेटा वापरास विराम दिला आहे.\n\nपुन्हा सुरु करण्यामुळे आपल्या वाहकाकडून शुल्क आकारले जाऊ शकते."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"पुन्हा सुरु करा"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"इंटरनेट कनेक्शन नाही"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"वाय-फाय कनेक्ट केले"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 45215b4..82de7a3 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data 4G dijeda"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Data selular dijeda"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data dijeda"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Oleh kerana had data tetap anda telah dicapai, peranti telah menjeda penggunaan data bagi baki kitaran ini.\n\nMenyambung semula boleh menyebabkan anda dikenakan bayaran daripada pembawa anda."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Sambung semula"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Tiada smbg Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi disambungkan"</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 31efa64..3899b00 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data ခေတ္တရပ်တန့်သည်"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"cellular data ခေတ္တရပ်တန့်သည်"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ဒေတာ ခေတ္တရပ်တန့်သည်"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"သင့် ဒေတာ အသုံးပြုမှု သတ်မှတ်ထားချက်သို့ ရောက်ရှိသောကြောင့်၊ ဤကာလအတွက် ကျန်ရှိသည့် ဒေတာအသုံးပြုမှုအား စက်ပစ္စည်းမှ ရပ်တန့်ထားသည်။\n\nဆက်လက်သွားပါက သင့်ဖုန်းဝန်ဆောင်မှုမှ သင့်အား ကုန်ကျစရိတ်တောင်းခံလိမ့်မည်။"</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"ပြန်ဆက်လုပ်ရန်"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"အင်တာနက်မရှိ"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"ကြိုးမဲ့ဆက်သွယ်မှု"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 9d13ebf..0a4e045 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data er satt på pause"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobildata er satt på pause"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data er satt på pause"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Fordi den angitte datagrensen ble nådd, har enheten satt databruk på pause for resten av denne syklusen. \n\nHvis du gjenopptar bruken, kan det føre til avgifter fra operatøren din."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Gjenoppta"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ingen Internett-forbindelse"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi tilkoblet"</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 0a37810..47d326c 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G डेटा रोकिएको छ"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"सेल्यूलर डेटा रोकिएको छ"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"डेटा रोकिएको छ"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"तपाईंले सेट गर्नुभएको डेटाको सीमा पुगेकाले, यन्त्रले यस चक्रको बाँकी भागका लागि डेटाको प्रयोग रोकेको छ।\n\nपुन: सुरू गर्दा तपाईंको क्यारियरले शुल्कहरू लिन सक्छ।"</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"पुनः सुरु गर्नुहोस्"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"इन्टरनेट जडान छैन"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi जडित"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index ef55b3c..49319d1 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data zijn onderbroken"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobiele gegevens zijn onderbroken"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Gegevens zijn onderbroken"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Omdat de ingestelde gegevenslimiet is bereikt, heeft het apparaat het gegevensverbruik onderbroken voor de rest van deze cyclus.\n\nAls u het gegevensverbruik hervat, kan je provider kosten in rekening brengen."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Hervatten"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Geen internetverbinding"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Verbonden via wifi"</string>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 635e96e..082ff3a 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G ਡੈਟਾ ਰੁਕ ਗਿਆ ਹੈ"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"ਸੈਲਿਊਲਰ ਡੈਟਾ ਰੁਕ ਗਿਆ ਹੈ"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ਡੈਟਾ ਰੁਕ ਗਿਆ ਹੈ"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"ਕਿਉਂਕਿ ਤੁਹਾਡੀ ਸੈਟ ਡੈਟਾ ਸੀਮਾ ਪੂਰੀ ਹੋ ਗਈ ਸੀ,  ਡੀਵਾਈਸ ਨੇ ਇਸ ਬਾਕੀ ਚੱਕਰ ਲਈ ਡੈਟਾ ਉਪਯੋਗ ਰੋਕ ਦਿੱਤਾ ਹੈ।\n\nਇਸਨੂੰ ਦੁਬਾਰਾ ਸ਼ੁਰੂ ਕਰਨ ਨਾਲ ਤੁਹਾਡੇ ਕੈਰੀਅਰ ਵੱਲੋਂ ਖ਼ਰਚੇ ਪਾਏ ਜਾ ਸਕਦੇ ਹਨ।"</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"ਦੁਬਾਰਾ ਸ਼ੁਰੂ ਕਰੋ"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"ਕੋਈ ਇੰਟਰਨੈਟ ਕਨੈਕਸ਼ਨ ਨਹੀਂ"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi ਕਨੈਕਟ ਕੀਤਾ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 5d3fd99..52bce7c 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Transmisja danych 4G została wstrzymana"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Komórkowa transmisja danych została wstrzymana"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Transmisja danych została wstrzymana"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Ponieważ został osiągnięty ustawiony przez Ciebie limit danych, urządzenie wstrzymało użycie danych na pozostałą część tego cyklu.\n\nWznowienie może spowodować naliczenie opłat przez operatora."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Wznów"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Brak internetu"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: połączono"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 298fc3c..5ecf074 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Os dados 4G foram pausados"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Os dados da rede celular foram pausados"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Os dados foram pausados"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Como seu limite de dados definido foi atingido, o dispositivo pausou o uso de dados para o restante deste ciclo.\n\nA retomada pode gerar cobranças por parte da sua operadora."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Retomar"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Sem conexão à Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi conectado"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 33176b6..c1e662c 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Dados 4G em pausa"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Dados de redes móveis em pausa"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Dados em pausa"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Uma vez que foi atingido o limite de dados definido, foi interrompida a utilização de dados no seu dispositivo durante o tempo restante deste ciclo.\n\nSe retomar a utilização, o seu operador pode efetuar cobranças."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Retomar"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Sem ligação internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi ligado"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 298fc3c..5ecf074 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Os dados 4G foram pausados"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Os dados da rede celular foram pausados"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Os dados foram pausados"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Como seu limite de dados definido foi atingido, o dispositivo pausou o uso de dados para o restante deste ciclo.\n\nA retomada pode gerar cobranças por parte da sua operadora."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Retomar"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Sem conexão à Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi conectado"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 9d6b7d9..bedb7d0 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -240,7 +240,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Conexiunea de date 4G este întreruptă"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Conexiunea de date mobile este întreruptă"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Conexiunea de date este întreruptă"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Deoarece limita setată pentru date a fost atinsă, dispozitivul a întrerupt utilizarea datelor pentru restul acestui ciclu.\n\nReluarea utilizării de date poate genera aplicarea de taxe de către operator."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Reluați"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Fără conex. internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi conectat"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9ac4155..a155104 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -241,7 +241,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Передача данных 4G приостановлена"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Передача мобильных данных приостановлена"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Передача данных приостановлена"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Передача данных выключена до конца цикла, поскольку достигнут установленный вами лимит.\n\nЕсли вы возобновите ее, оператор может взимать плату за дополнительный расход трафика."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Возобновить"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Нет интернет-подключения"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi подключено"</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 95cac9e..567d9e9 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G දත්ත විරාම කර ඇත"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"සෙලියුලර් දත්ත විරාම කර ඇත"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"දත්ත විරාම කර ඇත"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"ඔබ සකසා ඇති දත්ත සීමාවට ළඟා වූ නිසා, උපාංගය මගින් මෙම චක්‍රයේ ඉතිරිය සඳහා දත්ත භාවිතය විරාම කර ඇත. \n\nනැවත පටන් ගැනීමෙන් ඔබගේ වාහකයෙන් අය කිරීම් වලට පොළඹවනු ඇත."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"නැවත පටන්ගන්න"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"අන්තර්ජාල සම්බන්ධතාවයක් නැත"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi සම්බන්ධිතයි"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 9c534c5..527a1fc 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -241,7 +241,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Dátové prenosy 4G sú pozastavené"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobilné dáta sú pozastavené"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Dáta sú pozastavené"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Keďže ste dosiahli nastavený limit pre mobilné dáta, na zariadení bola pre zvyšok tohto cyklu pozastavená spotreba dát.\n\nJej opätovné spustenie môže mať za následok účtovanie poplatkov vaším operátorom."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Znova spustiť"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Bez prip. na Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: pripojené"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index d930a72..3134962 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -241,7 +241,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Prenos podatkov v omrežju 4G je zaustavljen"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Prenos mobilnih podatkov je zaustavljen"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Prenos podatkov je zaustavljen"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Dosegli ste nastavljeno omejitev količine prenesenih podatkov, zato je naprava zaustavila porabo podatkov za preostanek cikla.\n\nČe nadaljujete s porabo, boste morda morali plačati stroške operaterju."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Nadaljuj"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ni internetne povez."</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi povezan"</string>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 7c11eb9..afa7694 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Të dhënat 4G janë ndërprerë"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Të dhënat celulare janë ndërprerë"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Të dhënat janë ndërprerë"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Pajisja jote ka ndërprerë përdorimin e të dhënave për pjesën e mbetur të ciklit sepse është arritur kufiri i caktuar i të dhënave.\n\nVazhdimi mund të sjellë tarifa nga operatori celular."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Rifillo"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Nuk ka lidhje interneti"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi është i lidhur"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 30c1468..06fabee 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -238,7 +238,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G подаци су паузирани"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Мобилни подаци су паузирани"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Подаци су паузирани"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Због тога што сте достигли подешено ограничење за податке, уређај је паузирао коришћење података током остатка овог циклуса.\n\nАко наставите, мобилни оператер може да вам наплати додатне трошкове."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Настави"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Нема интернет везе"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi је повезан"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index e7b5df1..8b110c5 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data har pausats"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobildata har pausats"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Dataanvändningen har pausats"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Eftersom du har nått den angivna datagränsen har dataanvändningen pausats under resten av perioden.\n\nOm du återupptar dataanvändningen kan avgifter från operatören tillkomma."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Återuppta"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ingen anslutning"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi-ansluten"</string>
@@ -351,7 +352,7 @@
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Mindre brådskande aviseringar nedan"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Tryck igen för att öppna"</string>
-    <string name="keyguard_unlock" msgid="8043466894212841998">"Svep uppåt om du vill låsa upp"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Svep uppåt för att låsa upp"</string>
     <string name="phone_hint" msgid="4872890986869209950">"Svep från ikonen och öppna telefonen"</string>
     <string name="voice_hint" msgid="8939888732119726665">"Svep från ikonen och öppna röstassistenten"</string>
     <string name="camera_hint" msgid="7939688436797157483">"Svep från ikonen och öppna kameran"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 4e9d628..be91af3 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data ya 4G imesitishwa"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Data ya simu ya mkononi imesitishwa"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data imesitishwa"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Kwa sababu ulifikia kiwango cha juu cha data kilichowekwa, kifaa kimesitisha matumizi ya data katika awamu hii iliyosalia.\n\n Kuendelea kunaweza kusababisha malipo kwa mtoa huduma wako."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Endelea"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Hakuna muunganisho wa mtandao"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Mtandao-hewa umeunganishwa"</string>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index a2ed16f..799d628 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G டேட்டா இடைநிறுத்தப்பட்டது"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"செல்லுலார் தரவு இடைநிறுத்தப்பட்டது"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"தரவு இடைநிறுத்தப்பட்டது"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"அமைக்கப்பட்ட தரவின் வரம்பை அடைந்துவிட்டதால், இந்தச் சுழற்சியின் மீதமுள்ள நாட்களுக்கான தரவுப் பயன்பாட்டைச் சாதனம் இடைநிறுத்தியுள்ளது.\n\nமீண்டும் தொடங்குவது, மொபைல் நிறுவனக் கட்டணங்களுக்கு உட்படுத்தலாம்."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"மீண்டும் தொடங்கு"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"இணைய இணைப்பு இல்லை"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"வைஃபை இணைக்கப்பட்டது"</string>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index fdb5092..f6e3ee2 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G డేటా పాజ్ చేయబడింది"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"సెల్యులార్ డేటా పాజ్ చేయబడింది"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"డేటా పాజ్ చేయబడింది"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"మీ సెట్ చేయబడిన డేటా పరిమితిని చేరుకున్నందున పరికరం ఈ సైకిల్‌లో మిగిలిన భాగానికి డేటా వినియోగాన్ని పాజ్ చేసింది.\n\nపునఃప్రారంభించడం వలన మీ క్యారియర్ ఛార్జీలు విధించవచ్చు."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"పునఃప్రారంభించు"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"ఇంటర్నెట్ కనెక్షన్ లేదు"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi కనెక్ట్ చేయబడింది"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 678937a..0482e3b 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"หยุดการใช้ข้อมูล 4G ชั่วคราวแล้ว"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"หยุดการใช้ข้อมูลมือถือชั่วคราวแล้ว"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"หยุดการใช้ข้อมูลชั่วคราวแล้ว"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"เนื่องจากใช้งานข้อมูลถึงขีดจำกัดที่กำหนดไว้แล้ว อุปกรณ์จึงหยุดการใช้งานข้อมูลไว้ชั่วคราวตลอดระยะเวลาที่เหลือของรอบนี้\n\nการทำให้กลับมาทำงานอีกครั้งอาจทำให้เกิดค่าใช้จ่ายจากผู้ให้บริการ"</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"ทำต่อ"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"ไม่มีอินเทอร์เน็ต"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"เชื่อมต่อ WiFi แล้ว"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 50c7e5c..9b104f5 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Naka-pause ang 4G data"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Naka-pause ang cellular data"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Naka-pause ang data"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Dahil naabot ang iyong nakatakdang limitasyon sa data, na-pause ng device ang paggamit ng data para sa nalalabing bahagi ng cycle na ito.\n\nMaaaring makakuha ng mga singilin mula sa iyong carrier ang pagpapatuloy."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Ipagpatuloy"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Walang koneksyon sa Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"nakakonekta ang Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 575d011..e655cd6 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G veri kullanımı duraklatıldı"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Hücresel veri kullanımı duraklatıldı"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Veri kullanımı duraklatıldı"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Ayarlanmış olan veri sınırınıza ulaşıldığından, bu dönemin kalan süresi için cihazda veri kullanımı duraklatıldı.\n\nVeri kullanımını devam ettirmek, operatörünüzün sizden ödeme almasına neden olabilir."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Devam ettir"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"İnternet bağlantısı yok"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Kablosuz bağlandı"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 4d4162c..eccc4a2 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -241,7 +241,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Передавання даних 4G призупинено"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Передавання мобільних даних призупинено"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Передавання даних призупинено"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Пристрій призупинив передавання даних до кінця цього циклу, оскільки ваш ліміт перевищено.\n\nЯкщо ви відновите передавання даних, оператор може стягувати додаткову плату."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Відновити"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Немає з’єднання"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi під’єднано"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 6a3e4db..dc177d1 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"‏4G ڈیٹا موقوف کر دیا گیا"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"سیلولر ڈیٹا موقوف کر دیا گیا"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ڈیٹا موقوف کر دیا گیا"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"چونکہ آپ کی سیٹ کردہ ڈیٹا کی حد تک پہنچ گیا، لہذا آلہ نے اس سائیکل کے بقیہ حصے کیلئے ڈیٹا کے استعمال کو موقوف کر دیا ہے۔\n\nدوبارہ شروع کرنے سے آپ کے کیریئر سے چارجز لگ سکتے ہیں۔"</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"دوبارہ شروع کریں"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"کوئی انٹرنیٹ کنکشن نہیں"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"‏Wi-Fi مربوط ہے"</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index f7bae9b..32fb303 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G internet to‘xtatib qo‘yildi"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobil internetdan foydalanish to‘xtatib qo‘yildi"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Internetdan foydalanish to‘xtatib qo‘yildi"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Siz o‘rnatgan mobil internet chekloviga yetgani bois joriy hisob-kitob davrining qolgan muddati uchun mobil internetdan foydalanish vaqtinchalik to‘xtatib qo‘yildi.\n\nAgar internetdan foydalanishni davom ettirsangiz, buning uchun uyali aloqa operatoringiz ortiqcha haq talab qilishi mumkin."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Davom etish"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Internetga ulanmagan"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi ulandi"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index df6fdb9..4146796 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Đã tạm dừng dữ liệu 4G"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Đã tạm dừng dữ liệu di động"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Đã tạm dừng dữ liệu"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Vì bạn đã đạt tới giới hạn dữ liệu thiết lập nên thiết bị đã tạm dừng sử dụng dữ liệu cho phần còn lại của chu kỳ này.\n\nTiếp tục có thể dẫn tới nhà cung cấp dịch vụ của bạn sẽ tính phí."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Tiếp tục"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ko có k.nối Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Đã kết nối Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 7bda7a0..30f6245 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G 数据网络已暂停使用"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"移动数据网络已暂停使用"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"数据网络已暂停使用"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"由于使用的数据流量已达到您所设置的上限,因此您的设备已暂停在此周期的剩余时间内使用数据流量。\n\n如果恢复数据流量使用,您的运营商可能会向您收取相应费用。"</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"恢复"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"未连接互联网"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"已连接到WLAN网络"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 9dbf41f..f00a30b 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -239,7 +239,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"已暫停 4G 數據"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"已暫停流動數據"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"已暫停使用數據"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"由於您已達到設定的數據用量上限,裝置已暫停使用數據,直到週期結束。\n\n如恢復使用數據,流動網絡供應商可能會向您收取費用。"</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"恢復"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"沒有互聯網連線"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi 已連線"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index b061037..34d12ff 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"已暫停 4G 數據連線"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"已暫停行動數據連線"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"已暫停數據連線"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"由於數據用量已達設定上限,裝置在這個週期的剩餘時間將暫停使用數據連線。\n\n如果恢復使用,行動通訊業者可能會向您收取額外的連線費用。"</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"恢復連線"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"沒有網際網路連線"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi 已連線"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index f97e71a2..1b2794e 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -237,7 +237,8 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G idatha imisiwe"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Idatha yeselula imisiwe"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Idatha imisiwe"</string>
-    <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Ngoba umkhawulo wakho wedatha osethiwe ufinyelelwe, idivayisi imise kancane ukusetshenziswa kwedatha ngesikhumbuzi salo mjikelezo.\n\nUkuqhuba futhi kungaholela kuzindleko kusuka kwinkampani yakho yenethiwekhi."</string>
+    <!-- no translation found for data_usage_disabled_dialog (1841738975235283398) -->
+    <skip />
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Qalisa kabusha"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Alukho uxhumano lwe-Inthanethi"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"I-Wi-Fi ixhunyiwe"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 8d44048..eb1a1eb 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -100,7 +100,7 @@
 
     <!-- The default tiles to display in QuickSettings -->
     <string name="quick_settings_tiles_default" translatable="false">
-        wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location
+        wifi,cell,battery,dnd,flashlight,rotation,bt,airplane
     </string>
 
     <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
@@ -240,6 +240,9 @@
     -->
     <string name="doze_pickup_subtype_performs_proximity_check"></string>
 
+    <!-- Type of the double tap sensor. Empty if double tap is not supported. -->
+    <string name="doze_double_tap_sensor_type" translatable="false"></string>
+
     <!-- Doze: pulse parameter - how long does it take to fade in? -->
     <integer name="doze_pulse_duration_in">900</integer>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c4bea9c..3f485c3 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -567,7 +567,7 @@
     <!-- Title of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
     <string name="data_usage_disabled_dialog_title">Data is paused</string>
     <!-- Body of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=NONE] -->
-    <string name="data_usage_disabled_dialog">Because your set data limit was reached, the device has paused data usage for the remainder of this cycle.\n\nResuming may lead to charges from your carrier.</string>
+    <string name="data_usage_disabled_dialog">The data limit you set has been reached. You are no longer using cellular data.\n\nIf you resume, charges may apply for data usage.</string>
     <!-- Dialog button indicating that data connection should be re-enabled. [CHAR LIMIT=28] -->
     <string name="data_usage_disabled_dialog_enable">Resume</string>
 
@@ -1667,4 +1667,8 @@
     <!-- accessibility label for paging indicator in quick settings [CHAR LIMITi=NONE] -->
     <string name="accessibility_quick_settings_page">Page <xliff:g name="current_page" example="1">%1$d</xliff:g> of <xliff:g name="num_pages" example="2">%2$d</xliff:g></string>
 
+    <!-- Plugin control section of the tuner. Non-translatable since it should
+         not appear on production builds ever. -->
+    <string name="plugins" translatable="false">Plugins</string>
+
 </resources>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index b46e862..211f8e8 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -133,6 +133,11 @@
             android:title="@string/other"
             android:fragment="com.android.systemui.tuner.OtherPrefs" />
 
+    <Preference
+            android:key="plugins"
+            android:title="@string/plugins"
+            android:fragment="com.android.systemui.tuner.PluginFragment" />
+
     <!-- Warning, this goes last. -->
     <Preference
         android:summary="@string/tuner_persistent_warning"
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index 874021a..b3038b9 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -35,12 +35,13 @@
     private static final int SIZE = Build.IS_DEBUGGABLE ? 400 : 50;
     static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
 
-    private static final int PULSE_REASONS = 4;
+    private static final int PULSE_REASONS = 5;
 
     public static final int PULSE_REASON_INTENT = 0;
     public static final int PULSE_REASON_NOTIFICATION = 1;
     public static final int PULSE_REASON_SENSOR_SIGMOTION = 2;
     public static final int PULSE_REASON_SENSOR_PICKUP = 3;
+    public static final int PULSE_REASON_SENSOR_DOUBLE_TAP = 4;
 
     private static long[] sTimes;
     private static String[] sMessages;
@@ -167,6 +168,7 @@
             case PULSE_REASON_NOTIFICATION: return "notification";
             case PULSE_REASON_SENSOR_SIGMOTION: return "sigmotion";
             case PULSE_REASON_SENSOR_PICKUP: return "pickup";
+            case PULSE_REASON_SENSOR_DOUBLE_TAP: return "doubletap";
             default: throw new IllegalArgumentException("bad reason: " + pulseReason);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index ec4f447..261d241 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -16,12 +16,14 @@
 
 package com.android.systemui.doze;
 
+import android.app.ActivityManager;
 import android.app.UiModeManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.Configuration;
+import android.database.ContentObserver;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
@@ -29,11 +31,15 @@
 import android.hardware.TriggerEvent;
 import android.hardware.TriggerEventListener;
 import android.media.AudioAttributes;
+import android.net.Uri;
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.os.Vibrator;
+import android.provider.Settings;
 import android.service.dreams.DreamService;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.Display;
 
@@ -45,6 +51,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.Date;
+import java.util.List;
 
 public class DozeService extends DreamService {
     private static final String TAG = "DozeService";
@@ -59,8 +66,8 @@
     private final Handler mHandler = new Handler();
 
     private DozeHost mHost;
-    private SensorManager mSensors;
-    private TriggerSensor mSigMotionSensor;
+    private SensorManager mSensorManager;
+    private TriggerSensor[] mSensors;
     private TriggerSensor mPickupSensor;
     private PowerManager mPowerManager;
     private PowerManager.WakeLock mWakeLock;
@@ -86,8 +93,10 @@
         pw.print("  mWakeLock: held="); pw.println(mWakeLock.isHeld());
         pw.print("  mHost: "); pw.println(mHost);
         pw.print("  mBroadcastReceiverRegistered: "); pw.println(mBroadcastReceiverRegistered);
-        pw.print("  mSigMotionSensor: "); pw.println(mSigMotionSensor);
-        pw.print("  mPickupSensor:"); pw.println(mPickupSensor);
+        for (TriggerSensor s : mSensors) {
+            pw.print("  sensor: ");
+            pw.println(s);
+        }
         pw.print("  mDisplayStateSupported: "); pw.println(mDisplayStateSupported);
         pw.print("  mPowerSaveActive: "); pw.println(mPowerSaveActive);
         pw.print("  mCarMode: "); pw.println(mCarMode);
@@ -110,13 +119,25 @@
 
         setWindowless(true);
 
-        mSensors = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
-        mSigMotionSensor = new TriggerSensor(Sensor.TYPE_SIGNIFICANT_MOTION,
-                mDozeParameters.getPulseOnSigMotion(), mDozeParameters.getVibrateOnSigMotion(),
-                DozeLog.PULSE_REASON_SENSOR_SIGMOTION);
-        mPickupSensor = new TriggerSensor(Sensor.TYPE_PICK_UP_GESTURE,
-                mDozeParameters.getPulseOnPickup(), mDozeParameters.getVibrateOnPickup(),
-                DozeLog.PULSE_REASON_SENSOR_PICKUP);
+        mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
+        mSensors = new TriggerSensor[] {
+                new TriggerSensor(
+                        mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION),
+                        null /* setting */,
+                        mDozeParameters.getPulseOnSigMotion(),
+                        mDozeParameters.getVibrateOnSigMotion(),
+                        DozeLog.PULSE_REASON_SENSOR_SIGMOTION),
+                mPickupSensor = new TriggerSensor(
+                        mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE),
+                        Settings.Secure.DOZE_PULSE_ON_PICK_UP,
+                        mDozeParameters.getPulseOnPickup(), mDozeParameters.getVibrateOnPickup(),
+                        DozeLog.PULSE_REASON_SENSOR_PICKUP),
+                new TriggerSensor(
+                        findSensorWithType(mDozeParameters.getDoubleTapSensorType()),
+                        Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP,
+                        mDozeParameters.getPulseOnPickup(), mDozeParameters.getVibrateOnPickup(),
+                        DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP)
+        };
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
         mWakeLock.setReferenceCounted(true);
@@ -159,18 +180,15 @@
         // Ask the host to get things ready to start dozing.
         // Once ready, we call startDozing() at which point the CPU may suspend
         // and we will need to acquire a wakelock to do work.
-        mHost.startDozing(new Runnable() {
-            @Override
-            public void run() {
-                if (mDreaming) {
-                    startDozing();
+        mHost.startDozing(mWakeLock.wrap(() -> {
+            if (mDreaming) {
+                startDozing();
 
-                    // From this point until onDreamingStopped we will need to hold a
-                    // wakelock whenever we are doing work.  Note that we never call
-                    // stopDozing because can we just keep dozing until the bitter end.
-                }
+                // From this point until onDreamingStopped we will need to hold a
+                // wakelock whenever we are doing work.  Note that we never call
+                // stopDozing because can we just keep dozing until the bitter end.
             }
-        });
+        }));
     }
 
     @Override
@@ -283,8 +301,9 @@
 
     private void listenForPulseSignals(boolean listen) {
         if (DEBUG) Log.d(mTag, "listenForPulseSignals: " + listen);
-        mSigMotionSensor.setListening(listen);
-        mPickupSensor.setListening(listen);
+        for (TriggerSensor s : mSensors) {
+            s.setListening(listen);
+        }
         listenForBroadcasts(listen);
         listenForNotifications(listen);
     }
@@ -293,11 +312,21 @@
         if (listen) {
             final IntentFilter filter = new IntentFilter(PULSE_ACTION);
             filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
+            filter.addAction(Intent.ACTION_USER_SWITCHED);
             mContext.registerReceiver(mBroadcastReceiver, filter);
+
+            for (TriggerSensor s : mSensors) {
+                if (s.mConfigured && !TextUtils.isEmpty(s.mSetting)) {
+                    mContext.getContentResolver().registerContentObserver(
+                            Settings.Secure.getUriFor(s.mSetting), false /* descendants */,
+                            mSettingsObserver, UserHandle.USER_ALL);
+                }
+            }
             mBroadcastReceiverRegistered = true;
         } else {
             if (mBroadcastReceiverRegistered) {
                 mContext.unregisterReceiver(mBroadcastReceiver);
+                mContext.getContentResolver().unregisterContentObserver(mSettingsObserver);
             }
             mBroadcastReceiverRegistered = false;
         }
@@ -344,6 +373,23 @@
                     finishForCarMode();
                 }
             }
+            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
+                for (TriggerSensor s : mSensors) {
+                    s.updateListener();
+                }
+            }
+        }
+    };
+
+    private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
+        @Override
+        public void onChange(boolean selfChange, Uri uri, int userId) {
+            if (userId != ActivityManager.getCurrentUser()) {
+                return;
+            }
+            for (TriggerSensor s : mSensors) {
+                s.updateListener();
+            }
         }
     };
 
@@ -375,18 +421,34 @@
         }
     };
 
+    private Sensor findSensorWithType(String type) {
+        if (TextUtils.isEmpty(type)) {
+            return null;
+        }
+        List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
+        for (Sensor s : sensorList) {
+            if (type.equals(s.getStringType())) {
+                return s;
+            }
+        }
+        return null;
+    }
+
     private class TriggerSensor extends TriggerEventListener {
-        private final Sensor mSensor;
-        private final boolean mConfigured;
-        private final boolean mDebugVibrate;
-        private final int mPulseReason;
+        final Sensor mSensor;
+        final boolean mConfigured;
+        final boolean mDebugVibrate;
+        final int mPulseReason;
+        final String mSetting;
 
         private boolean mRequested;
         private boolean mRegistered;
         private boolean mDisabled;
 
-        public TriggerSensor(int type, boolean configured, boolean debugVibrate, int pulseReason) {
-            mSensor = mSensors.getDefaultSensor(type);
+        public TriggerSensor(Sensor sensor, String setting, boolean configured,
+                boolean debugVibrate, int pulseReason) {
+            mSensor = sensor;
+            mSetting = setting;
             mConfigured = configured;
             mDebugVibrate = debugVibrate;
             mPulseReason = pulseReason;
@@ -404,18 +466,26 @@
             updateListener();
         }
 
-        private void updateListener() {
+        public void updateListener() {
             if (!mConfigured || mSensor == null) return;
-            if (mRequested && !mDisabled && !mRegistered) {
-                mRegistered = mSensors.requestTriggerSensor(this, mSensor);
+            if (mRequested && !mDisabled && enabledBySetting() && !mRegistered) {
+                mRegistered = mSensorManager.requestTriggerSensor(this, mSensor);
                 if (DEBUG) Log.d(mTag, "requestTriggerSensor " + mRegistered);
             } else if (mRegistered) {
-                final boolean rt = mSensors.cancelTriggerSensor(this, mSensor);
+                final boolean rt = mSensorManager.cancelTriggerSensor(this, mSensor);
                 if (DEBUG) Log.d(mTag, "cancelTriggerSensor " + rt);
                 mRegistered = false;
             }
         }
 
+        private boolean enabledBySetting() {
+            if (TextUtils.isEmpty(mSetting)) {
+                return true;
+            }
+            return Settings.Secure.getIntForUser(mContext.getContentResolver(), mSetting, 1,
+                    UserHandle.USER_CURRENT) != 0;
+        }
+
         @Override
         public String toString() {
             return new StringBuilder("{mRegistered=").append(mRegistered)
@@ -484,7 +554,7 @@
 
         public void check() {
             if (mFinished || mRegistered) return;
-            final Sensor sensor = mSensors.getDefaultSensor(Sensor.TYPE_PROXIMITY);
+            final Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
             if (sensor == null) {
                 if (DEBUG) Log.d(mTag, "No sensor found");
                 finishWithResult(RESULT_UNKNOWN);
@@ -494,7 +564,8 @@
             mPickupSensor.setDisabled(true);
 
             mMaxRange = sensor.getMaximumRange();
-            mSensors.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL, 0, mHandler);
+            mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL, 0,
+                    mHandler);
             mHandler.postDelayed(this, TIMEOUT_DELAY_MS);
             mRegistered = true;
         }
@@ -521,7 +592,7 @@
             if (mFinished) return;
             if (mRegistered) {
                 mHandler.removeCallbacks(this);
-                mSensors.unregisterListener(this);
+                mSensorManager.unregisterListener(this);
                 // we're done - reenable the pickup sensor
                 mPickupSensor.setDisabled(false);
                 mRegistered = false;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index d483e42..e1cd143 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -14,13 +14,13 @@
 
 package com.android.systemui.qs;
 
-import android.graphics.Path;
 import android.util.Log;
 import android.view.View;
 import android.view.View.OnAttachStateChangeListener;
 import android.view.View.OnLayoutChangeListener;
 import android.widget.TextView;
 
+import com.android.systemui.plugins.qs.QSContainer;
 import com.android.systemui.qs.PagedTileLayout.PageListener;
 import com.android.systemui.qs.QSPanel.QSTileLayout;
 import com.android.systemui.qs.QSTile.Host.Callback;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
similarity index 92%
rename from packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
rename to packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 19a5d52..2173922 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -24,14 +24,16 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
-import android.widget.FrameLayout;
+
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.plugins.qs.QSContainer;
 import com.android.systemui.qs.customize.QSCustomizer;
-import com.android.systemui.statusbar.phone.BaseStatusBarHeader;
-import com.android.systemui.statusbar.phone.NotificationPanelView;
+import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
 import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.statusbar.phone.QuickStatusBarHeader;
 import com.android.systemui.statusbar.stack.StackStateAnimator;
 
 /**
@@ -39,7 +41,7 @@
  *
  * Also manages animations for the QS Header and Panel.
  */
-public class QSContainer extends FrameLayout {
+public class QSContainerImpl extends QSContainer {
     private static final String TAG = "QSContainer";
     private static final boolean DEBUG = false;
 
@@ -49,7 +51,7 @@
     private int mHeightOverride = -1;
     protected QSPanel mQSPanel;
     private QSDetail mQSDetail;
-    protected BaseStatusBarHeader mHeader;
+    protected QuickStatusBarHeader mHeader;
     protected float mQsExpansion;
     private boolean mQsExpanded;
     private boolean mHeaderAnimating;
@@ -59,10 +61,10 @@
     private long mDelay;
     private QSAnimator mQSAnimator;
     private QSCustomizer mQSCustomizer;
-    private NotificationPanelView mPanelView;
+    private HeightListener mPanelView;
     private boolean mListening;
 
-    public QSContainer(Context context, AttributeSet attrs) {
+    public QSContainerImpl(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
 
@@ -71,7 +73,7 @@
         super.onFinishInflate();
         mQSPanel = (QSPanel) findViewById(R.id.quick_settings_panel);
         mQSDetail = (QSDetail) findViewById(R.id.qs_detail);
-        mHeader = (BaseStatusBarHeader) findViewById(R.id.header);
+        mHeader = (QuickStatusBarHeader) findViewById(R.id.header);
         mQSDetail.setQsPanel(mQSPanel, mHeader);
         mQSAnimator = new QSAnimator(this, (QuickQSPanel) mHeader.findViewById(R.id.quick_qs_panel),
                 mQSPanel);
@@ -92,7 +94,7 @@
         mQSAnimator.setHost(qsh);
     }
 
-    public void setPanelView(NotificationPanelView panelView) {
+    public void setPanelView(HeightListener panelView) {
         mPanelView = panelView;
     }
 
@@ -137,6 +139,13 @@
         updateBottom();
     }
 
+    @Override
+    public void setContainer(ViewGroup container) {
+        if (container instanceof NotificationsQuickSettingsContainer) {
+            mQSCustomizer.setContainer((NotificationsQuickSettingsContainer) container);
+        }
+    }
+
     /**
      * The height this view wants to be. This is different from {@link #getMeasuredHeight} such that
      * during closing the detail panel, this already returns the smaller height.
@@ -291,6 +300,11 @@
                 .start();
     }
 
+    @Override
+    public void closeDetail() {
+        mQSPanel.closeDetail();
+    }
+
     private final ViewTreeObserver.OnPreDrawListener mStartHeaderSlidingIn
             = new ViewTreeObserver.OnPreDrawListener() {
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 90b2e90..2b9320b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -35,8 +35,9 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSTile.DetailAdapter;
-import com.android.systemui.statusbar.phone.BaseStatusBarHeader;
+import com.android.systemui.plugins.qs.QSContainer.BaseStatusBarHeader;
+import com.android.systemui.plugins.qs.QSContainer.Callback;
+import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
 import com.android.systemui.statusbar.phone.QSTileHost;
 
 public class QSDetail extends LinearLayout {
@@ -151,7 +152,7 @@
 
 
 
-    public void handleShowingDetail(final QSTile.DetailAdapter adapter, int x, int y,
+    public void handleShowingDetail(final DetailAdapter adapter, int x, int y,
             boolean toggleQs) {
         final boolean showingDetail = adapter != null;
         setClickable(showingDetail);
@@ -287,7 +288,7 @@
                             mDetailAdapter != null && mDetailAdapter.getToggleEnabled());
     }
 
-    protected QSPanel.Callback mQsPanelCallback = new QSPanel.Callback() {
+    protected Callback mQsPanelCallback = new Callback() {
         @Override
         public void onToggleStateChanged(final boolean state) {
             post(new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index ed0fc1f..e1db8c6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -30,7 +30,8 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSTile.DetailAdapter;
+import com.android.systemui.plugins.qs.QSContainer;
+import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
 import com.android.systemui.qs.QSTile.Host.Callback;
 import com.android.systemui.qs.customize.QSCustomizer;
 import com.android.systemui.qs.external.CustomTile;
@@ -59,7 +60,7 @@
     protected boolean mExpanded;
     protected boolean mListening;
 
-    private Callback mCallback;
+    private QSContainer.Callback mCallback;
     private BrightnessController mBrightnessController;
     protected QSTileHost mHost;
 
@@ -170,7 +171,7 @@
         return mBrightnessView;
     }
 
-    public void setCallback(Callback callback) {
+    public void setCallback(QSContainer.Callback callback) {
         mCallback = callback;
     }
 
@@ -542,12 +543,6 @@
         public QSTile.Callback callback;
     }
 
-    public interface Callback {
-        void onShowingDetail(DetailAdapter detail, int x, int y);
-        void onToggleStateChanged(boolean state);
-        void onScanStateChanged(boolean state);
-    }
-
     public interface QSTileLayout {
         void addTile(TileRecord tile);
         void removeTile(TileRecord tile);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 6657b62..39ce324 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -27,12 +27,11 @@
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseArray;
-import android.view.View;
-import android.view.ViewGroup;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
 import com.android.systemui.qs.QSTile.State;
 import com.android.systemui.qs.external.TileServices;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
@@ -42,7 +41,6 @@
 import com.android.systemui.statusbar.policy.FlashlightController;
 import com.android.systemui.statusbar.policy.HotspotController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.statusbar.policy.Listenable;
 import com.android.systemui.statusbar.policy.LocationController;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.RotationLockController;
@@ -147,29 +145,6 @@
         return true;
     }
 
-    public interface DetailAdapter {
-        CharSequence getTitle();
-        Boolean getToggleState();
-        default boolean getToggleEnabled() {
-            return true;
-        }
-        View createDetailView(Context context, View convertView, ViewGroup parent);
-        Intent getSettingsIntent();
-        void setToggleState(boolean state);
-        int getMetricsCategory();
-
-        /**
-         * @return the height in px the content of the detail view should take.
-         */
-        default int getDetailViewHeight() { throw new UnsupportedOperationException(); };
-
-        /**
-         * Indicates whether the detail view wants to have its header (back button, title and
-         * toggle) shown.
-         */
-        default boolean hasHeader() { return true; }
-    }
-
     // safe to call from any thread
 
     public void addCallback(Callback callback) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 0de1e30..3493d24 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -33,10 +33,11 @@
 import android.widget.LinearLayout;
 import android.widget.Toolbar;
 import android.widget.Toolbar.OnMenuItemClickListener;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSContainer;
+import com.android.systemui.plugins.qs.QSContainer;
 import com.android.systemui.qs.QSDetailClipper;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
index 985bc9f..b61a81c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -40,6 +40,7 @@
 import com.android.settingslib.graph.UsageView;
 import com.android.systemui.BatteryMeterDrawable;
 import com.android.systemui.R;
+import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.BatteryController;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 8d8474a..18bde27 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -32,6 +32,7 @@
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.systemui.R;
+import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
 import com.android.systemui.qs.QSDetailItems;
 import com.android.systemui.qs.QSDetailItems.Item;
 import com.android.systemui.qs.QSTile;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index c3e9b6e..61bad77 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -28,6 +28,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
+import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
 import com.android.systemui.qs.QSDetailItems;
 import com.android.systemui.qs.QSDetailItems.Item;
 import com.android.systemui.qs.QSTile;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 0de5105..7de883e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -24,12 +24,12 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
-import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.R;
+import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
 import com.android.systemui.qs.QSIconView;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.qs.SignalTileView;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
index a63eabc..c7b6aea 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
@@ -115,6 +115,12 @@
         final TextView infoBottom = (TextView) findViewById(R.id.usage_info_bottom_text);
         infoBottom.setVisibility(bottom != null ? View.VISIBLE : View.GONE);
         infoBottom.setText(bottom);
+        boolean showLevel = info.warningLevel > 0 || info.limitLevel > 0;
+        graph.setVisibility(showLevel ? View.VISIBLE : View.GONE);
+        if (!showLevel) {
+            infoTop.setVisibility(View.GONE);
+        }
+
     }
 
     private String formatBytes(long bytes) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 91821ba..89bb1d2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -37,6 +37,7 @@
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.SysUIToast;
+import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.volume.ZenModePanel;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
index cc875ac..b5fbfe0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
@@ -22,6 +22,7 @@
 import android.util.Pair;
 
 import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index ba79a18..27306fc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -31,6 +31,7 @@
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.settingslib.wifi.AccessPoint;
 import com.android.systemui.R;
+import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
 import com.android.systemui.qs.QSDetailItems;
 import com.android.systemui.qs.QSDetailItems.Item;
 import com.android.systemui.qs.QSIconView;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 44a5bd3..390ef87 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -206,9 +206,17 @@
     }
 
     public void onConfigurationChanged() {
+        Resources res = mContext.getResources();
         reloadResources();
         mDummyStackView.reloadOnConfigurationChange();
+        // Update the header bar direction directly as it is not attached to anything and does not
+        // layout except in updateHeaderBarLayout()
+        mHeaderBar.setLayoutDirection(res.getConfiguration().getLayoutDirection());
         mHeaderBar.onConfigurationChanged();
+        mHeaderBar.forceLayout();
+        mHeaderBar.measure(
+                MeasureSpec.makeMeasureSpec(mHeaderBar.getMeasuredWidth(), MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(mHeaderBar.getMeasuredHeight(), MeasureSpec.EXACTLY));
     }
 
     /**
@@ -629,6 +637,7 @@
                 synchronized (mHeaderBarLock) {
                     if (mHeaderBar.getMeasuredWidth() != taskViewWidth ||
                             mHeaderBar.getMeasuredHeight() != mTaskBarHeight) {
+                        mHeaderBar.forceLayout();
                         mHeaderBar.measure(
                                 MeasureSpec.makeMeasureSpec(taskViewWidth, MeasureSpec.EXACTLY),
                                 MeasureSpec.makeMeasureSpec(mTaskBarHeight, MeasureSpec.EXACTLY));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index d29fbfd..f7d61835 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -164,6 +164,8 @@
     @ViewDebug.ExportedProperty(category="recents")
     private boolean mAwaitingFirstLayout = true;
     @ViewDebug.ExportedProperty(category="recents")
+    private boolean mLaunchNextAfterFirstMeasure = false;
+    @ViewDebug.ExportedProperty(category="recents")
     @InitialStateAction
     private int mInitialState = INITIAL_STATE_UPDATE_ALL;
     @ViewDebug.ExportedProperty(category="recents")
@@ -339,6 +341,7 @@
         // Since we always animate to the same place in (the initial state), always reset the stack
         // to the initial state when resuming
         mAwaitingFirstLayout = true;
+        mLaunchNextAfterFirstMeasure = false;
         mInitialState = INITIAL_STATE_UPDATE_ALL;
         requestLayout();
     }
@@ -1226,6 +1229,12 @@
                 mInitialState = INITIAL_STATE_UPDATE_NONE;
             }
         }
+        // If we got the launch-next event before the first layout pass, then re-send it after the
+        // initial state has been updated
+        if (mLaunchNextAfterFirstMeasure) {
+            mLaunchNextAfterFirstMeasure = false;
+            EventBus.getDefault().post(new LaunchNextTaskRequestEvent());
+        }
 
         // Rebind all the views, including the ignore ones
         bindVisibleTaskViews(mStackScroller.getStackScroll(), false /* ignoreTaskOverrides */);
@@ -1669,6 +1678,11 @@
     }
 
     public final void onBusEvent(LaunchNextTaskRequestEvent event) {
+        if (mAwaitingFirstLayout) {
+            mLaunchNextAfterFirstMeasure = true;
+            return;
+        }
+
         int launchTaskIndex = mStack.indexOfStackTask(mStack.getLaunchTarget());
         if (launchTaskIndex != -1) {
             launchTaskIndex = Math.max(0, launchTaskIndex - 1);
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 67a2595..d44aa84 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -634,6 +634,12 @@
             }
 
             int taskIndex = mCurrentTasks.indexOf(task);
+            if (taskIndex == -1) {
+                // If a task was added to the stack view after the start of the dismiss gesture,
+                // just ignore it
+                continue;
+            }
+
             TaskViewTransform fromTransform = mCurrentTaskTransforms.get(taskIndex);
             TaskViewTransform toTransform = mFinalTaskTransforms.get(taskIndex);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index e35ef44..bc46548 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -593,6 +593,9 @@
             public void onAnimationEnd(Animator animation) {
                 updateBackground();
                 mBackgroundAnimator = null;
+                if (mFadeInFromDarkAnimator == null) {
+                    mDimmedBackgroundFadeInAmount = -1;
+                }
             }
         });
         mBackgroundAnimator.addUpdateListener(mBackgroundVisibilityUpdater);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 78e56c0..58d57f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -116,6 +116,8 @@
     private boolean mForceSelectNextLayout = true;
     private PendingIntent mPreviousExpandedRemoteInputIntent;
     private PendingIntent mPreviousHeadsUpRemoteInputIntent;
+    private RemoteInputView mCachedExpandedRemoteInput;
+    private RemoteInputView mCachedHeadsUpRemoteInput;
 
     private int mContentHeightAtAnimationStart = UNDEFINED;
     private boolean mFocusOnVisibilityChange;
@@ -298,6 +300,9 @@
             mExpandedRemoteInput.onNotificationUpdateOrReset();
             if (mExpandedRemoteInput.isActive()) {
                 mPreviousExpandedRemoteInputIntent = mExpandedRemoteInput.getPendingIntent();
+                mCachedExpandedRemoteInput = mExpandedRemoteInput;
+                mExpandedRemoteInput.dispatchStartTemporaryDetach();
+                ((ViewGroup)mExpandedRemoteInput.getParent()).removeView(mExpandedRemoteInput);
             }
         }
         if (mExpandedChild != null) {
@@ -310,6 +315,9 @@
             mHeadsUpRemoteInput.onNotificationUpdateOrReset();
             if (mHeadsUpRemoteInput.isActive()) {
                 mPreviousHeadsUpRemoteInputIntent = mHeadsUpRemoteInput.getPendingIntent();
+                mCachedHeadsUpRemoteInput = mHeadsUpRemoteInput;
+                mHeadsUpRemoteInput.dispatchStartTemporaryDetach();
+                ((ViewGroup)mHeadsUpRemoteInput.getParent()).removeView(mHeadsUpRemoteInput);
             }
         }
         if (mHeadsUpChild != null) {
@@ -963,22 +971,35 @@
         View bigContentView = mExpandedChild;
         if (bigContentView != null) {
             mExpandedRemoteInput = applyRemoteInput(bigContentView, entry, hasRemoteInput,
-                    mPreviousExpandedRemoteInputIntent);
+                    mPreviousExpandedRemoteInputIntent, mCachedExpandedRemoteInput);
         } else {
             mExpandedRemoteInput = null;
         }
+        if (mCachedExpandedRemoteInput != null
+                && mCachedExpandedRemoteInput != mExpandedRemoteInput) {
+            // We had a cached remote input but didn't reuse it. Clean up required.
+            mCachedExpandedRemoteInput.dispatchFinishTemporaryDetach();
+        }
+        mCachedExpandedRemoteInput = null;
 
         View headsUpContentView = mHeadsUpChild;
         if (headsUpContentView != null) {
             mHeadsUpRemoteInput = applyRemoteInput(headsUpContentView, entry, hasRemoteInput,
-                    mPreviousHeadsUpRemoteInputIntent);
+                    mPreviousHeadsUpRemoteInputIntent, mCachedHeadsUpRemoteInput);
         } else {
             mHeadsUpRemoteInput = null;
         }
+        if (mCachedHeadsUpRemoteInput != null
+                && mCachedHeadsUpRemoteInput != mHeadsUpRemoteInput) {
+            // We had a cached remote input but didn't reuse it. Clean up required.
+            mCachedHeadsUpRemoteInput.dispatchFinishTemporaryDetach();
+        }
+        mCachedHeadsUpRemoteInput = null;
     }
 
     private RemoteInputView applyRemoteInput(View view, NotificationData.Entry entry,
-            boolean hasRemoteInput, PendingIntent existingPendingIntent) {
+            boolean hasRemoteInput, PendingIntent existingPendingIntent,
+            RemoteInputView cachedView) {
         View actionContainerCandidate = view.findViewById(
                 com.android.internal.R.id.actions_container);
         if (actionContainerCandidate instanceof FrameLayout) {
@@ -991,15 +1012,22 @@
 
             if (existing == null && hasRemoteInput) {
                 ViewGroup actionContainer = (FrameLayout) actionContainerCandidate;
-                RemoteInputView riv = RemoteInputView.inflate(
-                        mContext, actionContainer, entry, mRemoteInputController);
+                if (cachedView == null) {
+                    RemoteInputView riv = RemoteInputView.inflate(
+                            mContext, actionContainer, entry, mRemoteInputController);
 
-                riv.setVisibility(View.INVISIBLE);
-                actionContainer.addView(riv, new LayoutParams(
-                        ViewGroup.LayoutParams.MATCH_PARENT,
-                        ViewGroup.LayoutParams.MATCH_PARENT)
-                );
-                existing = riv;
+                    riv.setVisibility(View.INVISIBLE);
+                    actionContainer.addView(riv, new LayoutParams(
+                            ViewGroup.LayoutParams.MATCH_PARENT,
+                            ViewGroup.LayoutParams.MATCH_PARENT)
+                    );
+                    existing = riv;
+                } else {
+                    actionContainer.addView(cachedView);
+                    cachedView.dispatchFinishTemporaryDetach();
+                    cachedView.requestFocus();
+                    existing = cachedView;
+                }
             }
             if (hasRemoteInput) {
                 int color = entry.notification.getNotification().color;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
index 6cbacea..66cc15d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
@@ -21,7 +21,9 @@
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.RemoteInputView;
 
+import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.Pair;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -31,8 +33,9 @@
  */
 public class RemoteInputController {
 
-    private final ArrayList<WeakReference<NotificationData.Entry>> mOpen = new ArrayList<>();
-    private final ArraySet<String> mSpinning = new ArraySet<>();
+    private final ArrayList<Pair<WeakReference<NotificationData.Entry>, Object>> mOpen
+            = new ArrayList<>();
+    private final ArrayMap<String, Object> mSpinning = new ArrayMap<>();
     private final ArrayList<Callback> mCallbacks = new ArrayList<>(3);
     private final HeadsUpManager mHeadsUpManager;
 
@@ -41,36 +44,72 @@
         mHeadsUpManager = headsUpManager;
     }
 
-    public void addRemoteInput(NotificationData.Entry entry) {
+    /**
+     * Adds a currently active remote input.
+     *
+     * @param entry the entry for which a remote input is now active.
+     * @param token a token identifying the view that is managing the remote input
+     */
+    public void addRemoteInput(NotificationData.Entry entry, Object token) {
         Preconditions.checkNotNull(entry);
+        Preconditions.checkNotNull(token);
 
         boolean found = pruneWeakThenRemoveAndContains(
-                entry /* contains */, null /* remove */);
+                entry /* contains */, null /* remove */, token /* removeToken */);
         if (!found) {
-            mOpen.add(new WeakReference<>(entry));
+            mOpen.add(new Pair<>(new WeakReference<>(entry), token));
         }
 
         apply(entry);
     }
 
-    public void removeRemoteInput(NotificationData.Entry entry) {
+    /**
+     * Removes a currently active remote input.
+     *
+     * @param entry the entry for which a remote input should be removed.
+     * @param token a token identifying the view that is requesting the removal. If non-null,
+     *              the entry is only removed if the token matches the last added token for this
+     *              entry. If null, the entry is removed regardless.
+     */
+    public void removeRemoteInput(NotificationData.Entry entry, Object token) {
         Preconditions.checkNotNull(entry);
 
-        pruneWeakThenRemoveAndContains(null /* contains */, entry /* remove */);
+        pruneWeakThenRemoveAndContains(null /* contains */, entry /* remove */, token);
 
         apply(entry);
     }
 
-    public void addSpinning(String key) {
-        mSpinning.add(key);
+    /**
+     * Adds a currently spinning (i.e. sending) remote input.
+     *
+     * @param key the key of the entry that's spinning.
+     * @param token the token of the view managing the remote input.
+     */
+    public void addSpinning(String key, Object token) {
+        Preconditions.checkNotNull(key);
+        Preconditions.checkNotNull(token);
+
+        mSpinning.put(key, token);
     }
 
-    public void removeSpinning(String key) {
-        mSpinning.remove(key);
+    /**
+     * Removes a currently spinning remote input.
+     *
+     * @param key the key of the entry for which a remote input should be removed.
+     * @param token a token identifying the view that is requesting the removal. If non-null,
+     *              the entry is only removed if the token matches the last added token for this
+     *              entry. If null, the entry is removed regardless.
+     */
+    public void removeSpinning(String key, Object token) {
+        Preconditions.checkNotNull(key);
+
+        if (token == null || mSpinning.get(key) == token) {
+            mSpinning.remove(key);
+        }
     }
 
     public boolean isSpinning(String key) {
-        return mSpinning.contains(key);
+        return mSpinning.containsKey(key);
     }
 
     private void apply(NotificationData.Entry entry) {
@@ -86,14 +125,16 @@
      * @return true if {@param entry} has an active RemoteInput
      */
     public boolean isRemoteInputActive(NotificationData.Entry entry) {
-        return pruneWeakThenRemoveAndContains(entry /* contains */, null /* remove */);
+        return pruneWeakThenRemoveAndContains(entry /* contains */, null /* remove */,
+                null /* removeToken */);
     }
 
     /**
      * @return true if any entry has an active RemoteInput
      */
     public boolean isRemoteInputActive() {
-        pruneWeakThenRemoveAndContains(null /* contains */, null /* remove */);
+        pruneWeakThenRemoveAndContains(null /* contains */, null /* remove */,
+                null /* removeToken */);
         return !mOpen.isEmpty();
     }
 
@@ -101,17 +142,27 @@
      * Prunes dangling weak references, removes entries referring to {@param remove} and returns
      * whether {@param contains} is part of the array in a single loop.
      * @param remove if non-null, removes this entry from the active remote inputs
+     * @param removeToken if non-null, only removes an entry if this matches the token when the
+     *                    entry was added.
      * @return true if {@param contains} is in the set of active remote inputs
      */
     private boolean pruneWeakThenRemoveAndContains(
-            NotificationData.Entry contains, NotificationData.Entry remove) {
+            NotificationData.Entry contains, NotificationData.Entry remove, Object removeToken) {
         boolean found = false;
         for (int i = mOpen.size() - 1; i >= 0; i--) {
-            NotificationData.Entry item = mOpen.get(i).get();
-            if (item == null || item == remove) {
+            NotificationData.Entry item = mOpen.get(i).first.get();
+            Object itemToken = mOpen.get(i).second;
+            boolean removeTokenMatches = (removeToken == null || itemToken == removeToken);
+
+            if (item == null || (item == remove && removeTokenMatches)) {
                 mOpen.remove(i);
             } else if (item == contains) {
-                found = true;
+                if (removeToken != null && removeToken != itemToken) {
+                    // We need to update the token. Remove here and let caller reinsert it.
+                    mOpen.remove(i);
+                } else {
+                    found = true;
+                }
             }
         }
         return found;
@@ -138,7 +189,7 @@
         // Make a copy because closing the remote inputs will modify mOpen.
         ArrayList<NotificationData.Entry> list = new ArrayList<>(mOpen.size());
         for (int i = mOpen.size() - 1; i >= 0; i--) {
-            NotificationData.Entry item = mOpen.get(i).get();
+            NotificationData.Entry item = mOpen.get(i).first.get();
             if (item != null && item.row != null) {
                 list.add(item);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
index da57f7a..baff680 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
@@ -15,17 +15,14 @@
  */
 package com.android.systemui.statusbar.car;
 
-import android.app.ActivityManager;
 import android.app.ActivityManager.StackId;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
-import android.os.Handler;
 import android.support.v4.util.SimpleArrayMap;
 import android.util.Log;
 import android.util.SparseBooleanArray;
@@ -33,7 +30,7 @@
 import android.widget.LinearLayout;
 
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.ActivityStarter;
+import com.android.systemui.plugins.qs.QSContainer.ActivityStarter;
 
 import java.net.URISyntaxException;
 import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index cf87ddd..a7331d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -105,7 +105,7 @@
                         R.dimen.status_bar_connected_device_signal_margin_end));
 
         mConnectedDeviceSignalController = new ConnectedDeviceSignalController(mContext,
-                mSignalsView);
+                mSignalsView, mBluetoothController);
 
         if (Log.isLoggable(TAG, Log.DEBUG)) {
             Log.d(TAG, "makeStatusBarView(). mBatteryMeterView: " + mBatteryMeterView);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
index 07856daa9..66030b9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
@@ -17,11 +17,15 @@
 import android.widget.ImageView;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ScalingDrawableWrapper;
+import com.android.systemui.statusbar.policy.BluetoothController;
+
+import static com.android.systemui.statusbar.phone.PhoneStatusBar.DEBUG;
 
 /**
  * Controller that monitors signal strength for a device that is connected via bluetooth.
  */
-public class ConnectedDeviceSignalController extends BroadcastReceiver {
+public class ConnectedDeviceSignalController extends BroadcastReceiver implements
+        BluetoothController.Callback {
     private final static String TAG = "DeviceSignalCtlr";
 
     /**
@@ -54,18 +58,21 @@
 
     private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
     private final Context mContext;
-    private final View mSignalsView;
+    private final BluetoothController mController;
 
+    private final View mSignalsView;
     private final ImageView mNetworkSignalView;
 
     private final float mIconScaleFactor;
 
     private BluetoothHeadsetClient mBluetoothHeadsetClient;
 
-    public ConnectedDeviceSignalController(Context context, View signalsView) {
+    public ConnectedDeviceSignalController(Context context, View signalsView,
+            BluetoothController controller) {
         mContext = context;
-        mSignalsView = signalsView;
+        mController = controller;
 
+        mSignalsView = signalsView;
         mNetworkSignalView = (ImageView)
                 mSignalsView.findViewById(R.id.connected_device_network_signal);
 
@@ -86,22 +93,46 @@
         filter.addAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED);
         filter.addAction(BluetoothHeadsetClient.ACTION_AG_EVENT);
         mContext.registerReceiver(this, filter);
+
+        mController.addStateChangedCallback(this);
     }
 
     public void stopListening() {
         mContext.unregisterReceiver(this);
+        mController.removeStateChangedCallback(this);
+    }
+
+    @Override
+    public void onBluetoothDevicesChanged() {
+        // Nothing to do here because this Controller is not displaying a list of possible
+        // bluetooth devices.
+    }
+
+    @Override
+    public void onBluetoothStateChange(boolean enabled) {
+        if (DEBUG) {
+            Log.d(TAG, "onBluetoothStateChange(). enabled: " + enabled);
+        }
+
+        // Only need to handle the case if bluetooth has been disabled, in which case the
+        // signal indicators are hidden. If bluetooth has been enabled, then this class should
+        // receive updates to the connection state via onReceive().
+        if (!enabled) {
+            mNetworkSignalView.setVisibility(View.GONE);
+            mSignalsView.setVisibility(View.GONE);
+        }
     }
 
     @Override
     public void onReceive(Context context, Intent intent) {
         String action = intent.getAction();
 
-        if (Log.isLoggable(TAG, Log.DEBUG)) {
+        if (DEBUG) {
             Log.d(TAG, "onReceive(). action: " + action);
         }
 
         if (BluetoothHeadsetClient.ACTION_AG_EVENT.equals(action)) {
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
+            if (DEBUG) {
                 Log.d(TAG, "Received ACTION_AG_EVENT");
             }
 
@@ -109,13 +140,13 @@
         } else if (BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
             int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
 
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
+            if (DEBUG) {
                 int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1);
                 Log.d(TAG, "ACTION_CONNECTION_STATE_CHANGED event: "
                         + oldState + " -> " + newState);
             }
             BluetoothDevice device =
-                    (BluetoothDevice)intent.getExtra(BluetoothDevice.EXTRA_DEVICE);
+                    (BluetoothDevice) intent.getExtra(BluetoothDevice.EXTRA_DEVICE);
             updateViewVisibility(device, newState);
         }
     }
@@ -128,7 +159,7 @@
         int networkStatus = intent.getIntExtra(BluetoothHeadsetClient.EXTRA_NETWORK_STATUS,
                 INVALID_SIGNAL);
         if (networkStatus != INVALID_SIGNAL) {
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
+            if (DEBUG) {
                 Log.d(TAG, "EXTRA_NETWORK_STATUS: " + " " + networkStatus);
             }
 
@@ -140,7 +171,7 @@
         int signalStrength = intent.getIntExtra(
                 BluetoothHeadsetClient.EXTRA_NETWORK_SIGNAL_STRENGTH, INVALID_SIGNAL);
         if (signalStrength != INVALID_SIGNAL) {
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
+            if (DEBUG) {
                 Log.d(TAG, "EXTRA_NETWORK_SIGNAL_STRENGTH: " + signalStrength);
             }
 
@@ -150,7 +181,7 @@
         int roamingStatus = intent.getIntExtra(BluetoothHeadsetClient.EXTRA_NETWORK_ROAMING,
                 INVALID_SIGNAL);
         if (roamingStatus != INVALID_SIGNAL) {
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
+            if (DEBUG) {
                 Log.d(TAG, "EXTRA_NETWORK_ROAMING: " + roamingStatus);
             }
         }
@@ -169,7 +200,7 @@
 
     private void updateViewVisibility(BluetoothDevice device, int newState) {
         if (newState == BluetoothProfile.STATE_CONNECTED) {
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
+            if (DEBUG) {
                 Log.d(TAG, "Device connected");
             }
 
@@ -186,14 +217,14 @@
             int signalStrength = featuresBundle.getInt(
                     BluetoothHeadsetClient.EXTRA_NETWORK_SIGNAL_STRENGTH, INVALID_SIGNAL);
             if (signalStrength != INVALID_SIGNAL) {
-                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                if (DEBUG) {
                     Log.d(TAG, "EXTRA_NETWORK_SIGNAL_STRENGTH: " + signalStrength);
                 }
 
                 setNetworkSignalIcon(SIGNAL_STRENGTH_ICONS[signalStrength]);
             }
         } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
+            if (DEBUG) {
                 Log.d(TAG, "Device disconnected");
             }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
deleted file mode 100644
index 8f689c6..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.app.PendingIntent;
-import android.content.Intent;
-
-/**
- * An interface to start activities. This is used to as a callback from the views to
- * {@link PhoneStatusBar} to allow custom handling for starting the activity, i.e. dismissing the
- * Keyguard.
- */
-public interface ActivityStarter {
-    void startPendingIntentDismissingKeyguard(PendingIntent intent);
-    void startActivity(Intent intent, boolean dismissShade);
-    void startActivity(Intent intent, boolean dismissShade, Callback callback);
-    void preventNextAnimation();
-
-    interface Callback {
-        void onActivityStarted(int resultCode);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java
deleted file mode 100644
index 79eef43..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.RelativeLayout;
-import com.android.systemui.qs.QSPanel;
-import com.android.systemui.qs.QSPanel.Callback;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.NetworkControllerImpl;
-import com.android.systemui.statusbar.policy.NextAlarmController;
-import com.android.systemui.statusbar.policy.UserInfoController;
-
-public abstract class BaseStatusBarHeader extends RelativeLayout implements
-        NetworkControllerImpl.EmergencyListener {
-
-    public BaseStatusBarHeader(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public abstract int getCollapsedHeight();
-    public abstract int getExpandedHeight();
-
-    public abstract void setExpanded(boolean b);
-    public abstract void setExpansion(float headerExpansionFraction);
-    public abstract void setListening(boolean listening);
-    public abstract void updateEverything();
-    public abstract void setActivityStarter(ActivityStarter activityStarter);
-    public abstract void setQSPanel(QSPanel qSPanel);
-    public abstract void setBatteryController(BatteryController batteryController);
-    public abstract void setNextAlarmController(NextAlarmController nextAlarmController);
-    public abstract void setUserInfoController(UserInfoController userInfoController);
-    public abstract void setCallback(Callback qsPanelCallback);
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index 95cb672..f6fe176 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -14,11 +14,11 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.annotation.DrawableRes;
-import android.annotation.Nullable;
 import android.graphics.drawable.Drawable;
 import android.view.View;
 
+import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
+
 import java.util.ArrayList;
 
 /**
@@ -186,18 +186,4 @@
         }
     }
 
-    /**
-     * Interface for button actions.
-     */
-    public interface ButtonInterface {
-        void setImageResource(@DrawableRes int resId);
-
-        void setImageDrawable(@Nullable Drawable drawable);
-
-        void abortCurrentGesture();
-
-        void setLandscape(boolean landscape);
-
-        void setCarMode(boolean carMode);
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index efceed1..d5bf499 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -84,8 +84,8 @@
         return getPulseInDuration(pickup) + getPulseVisibleDuration() + getPulseOutDuration();
     }
 
-    public int getPulseInDuration(boolean pickup) {
-        return pickup
+    public int getPulseInDuration(boolean pickupOrDoubleTap) {
+        return pickupOrDoubleTap
                 ? getInt("doze.pulse.duration.in.pickup", R.integer.doze_pulse_duration_in_pickup)
                 : getInt("doze.pulse.duration.in", R.integer.doze_pulse_duration_in);
     }
@@ -114,6 +114,10 @@
         return SystemProperties.getBoolean("doze.vibrate.pickup", false);
     }
 
+    public String getDoubleTapSensorType() {
+        return mContext.getString(R.string.doze_double_tap_sensor_type);
+    }
+
     public boolean getProxCheckBeforePulse() {
         return getBoolean("doze.pulse.proxcheck", R.bool.doze_proximity_check_before_pulse);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index 7d4515e..b44f5f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -109,10 +109,11 @@
 
     public void onScreenTurnedOn() {
         if (isPulsing()) {
-            final boolean pickup = mPulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP;
+            final boolean pickupOrDoubleTap = mPulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP
+                    || mPulseReason == DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP;
             startScrimAnimation(true /* inFront */, 0f,
-                    mDozeParameters.getPulseInDuration(pickup),
-                    pickup ? Interpolators.LINEAR_OUT_SLOW_IN : Interpolators.ALPHA_OUT,
+                    mDozeParameters.getPulseInDuration(pickupOrDoubleTap),
+                    pickupOrDoubleTap ? Interpolators.LINEAR_OUT_SLOW_IN : Interpolators.ALPHA_OUT,
                     mPulseInFinished);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 8cabfb9..4270147 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -61,6 +61,12 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.assist.AssistManager;
+import com.android.systemui.plugins.IntentButtonProvider;
+import com.android.systemui.plugins.IntentButtonProvider.IntentButton;
+import com.android.systemui.plugins.IntentButtonProvider.IntentButton.IconState;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.plugins.qs.QSContainer.ActivityStarter;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.KeyguardAffordanceView;
 import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -85,6 +91,11 @@
     public static final String EXTRA_CAMERA_LAUNCH_SOURCE
             = "com.android.systemui.camera_launch_source";
 
+    private static final String LEFT_BUTTON_PLUGIN
+            = "com.android.systemui.action.PLUGIN_LOCKSCREEN_LEFT_BUTTON";
+    private static final String RIGHT_BUTTON_PLUGIN
+            = "com.android.systemui.action.PLUGIN_LOCKSCREEN_RIGHT_BUTTON";
+
     private static final Intent SECURE_CAMERA_INTENT =
             new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
                     .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
@@ -94,7 +105,7 @@
     private static final int DOZE_ANIMATION_STAGGER_DELAY = 48;
     private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250;
 
-    private KeyguardAffordanceView mCameraImageView;
+    private KeyguardAffordanceView mRightAffordanceView;
     private KeyguardAffordanceView mLeftAffordanceView;
     private LockIcon mLockIcon;
     private TextView mIndicationText;
@@ -131,6 +142,9 @@
     private boolean mLeftIsVoiceAssist;
     private AssistManager mAssistManager;
 
+    private IntentButton mRightButton = new DefaultRightButton();
+    private IntentButton mLeftButton = new DefaultLeftButton();
+
     public KeyguardBottomAreaView(Context context) {
         this(context, null);
     }
@@ -155,7 +169,7 @@
             String label = null;
             if (host == mLockIcon) {
                 label = getResources().getString(R.string.unlock_label);
-            } else if (host == mCameraImageView) {
+            } else if (host == mRightAffordanceView) {
                 label = getResources().getString(R.string.camera_label);
             } else if (host == mLeftAffordanceView) {
                 if (mLeftIsVoiceAssist) {
@@ -174,7 +188,7 @@
                     mPhoneStatusBar.animateCollapsePanels(
                             CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
                     return true;
-                } else if (host == mCameraImageView) {
+                } else if (host == mRightAffordanceView) {
                     launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
                     return true;
                 } else if (host == mLeftAffordanceView) {
@@ -191,7 +205,7 @@
         super.onFinishInflate();
         mLockPatternUtils = new LockPatternUtils(mContext);
         mPreviewContainer = (ViewGroup) findViewById(R.id.preview_container);
-        mCameraImageView = (KeyguardAffordanceView) findViewById(R.id.camera_button);
+        mRightAffordanceView = (KeyguardAffordanceView) findViewById(R.id.camera_button);
         mLeftAffordanceView = (KeyguardAffordanceView) findViewById(R.id.left_button);
         mLockIcon = (LockIcon) findViewById(R.id.lock_icon);
         mIndicationText = (TextView) findViewById(R.id.keyguard_indication_text);
@@ -206,15 +220,31 @@
         inflateCameraPreview();
         mLockIcon.setOnClickListener(this);
         mLockIcon.setOnLongClickListener(this);
-        mCameraImageView.setOnClickListener(this);
+        mRightAffordanceView.setOnClickListener(this);
         mLeftAffordanceView.setOnClickListener(this);
         initAccessibility();
     }
 
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        PluginManager.getInstance(getContext()).addPluginListener(RIGHT_BUTTON_PLUGIN,
+                mRightListener, IntentButtonProvider.VERSION, false /* Only allow one */);
+        PluginManager.getInstance(getContext()).addPluginListener(LEFT_BUTTON_PLUGIN,
+                mLeftListener, IntentButtonProvider.VERSION, false /* Only allow one */);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        PluginManager.getInstance(getContext()).removePluginListener(mRightListener);
+        PluginManager.getInstance(getContext()).removePluginListener(mLeftListener);
+    }
+
     private void initAccessibility() {
         mLockIcon.setAccessibilityDelegate(mAccessibilityDelegate);
         mLeftAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate);
-        mCameraImageView.setAccessibilityDelegate(mAccessibilityDelegate);
+        mRightAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate);
     }
 
     @Override
@@ -233,11 +263,11 @@
                 getResources().getDimensionPixelSize(
                         com.android.internal.R.dimen.text_size_small_material));
 
-        ViewGroup.LayoutParams lp = mCameraImageView.getLayoutParams();
+        ViewGroup.LayoutParams lp = mRightAffordanceView.getLayoutParams();
         lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
         lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height);
-        mCameraImageView.setLayoutParams(lp);
-        mCameraImageView.setImageDrawable(mContext.getDrawable(R.drawable.ic_camera_alt_24dp));
+        mRightAffordanceView.setLayoutParams(lp);
+        updateRightAffordanceIcon();
 
         lp = mLockIcon.getLayoutParams();
         lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
@@ -252,6 +282,13 @@
         updateLeftAffordanceIcon();
     }
 
+    private void updateRightAffordanceIcon() {
+        IconState state = mRightButton.getIcon();
+        mRightAffordanceView.setVisibility(state.isVisible ? View.VISIBLE : View.GONE);
+        mRightAffordanceView.setImageDrawable(state.drawable);
+        mRightAffordanceView.setContentDescription(state.contentDescription);
+    }
+
     public void setActivityStarter(ActivityStarter activityStarter) {
         mActivityStarter = activityStarter;
     }
@@ -278,11 +315,7 @@
     }
 
     private Intent getCameraIntent() {
-        KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
-        boolean canSkipBouncer = updateMonitor.getUserCanSkipBouncer(
-                KeyguardUpdateMonitor.getCurrentUser());
-        boolean secure = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser());
-        return (secure && !canSkipBouncer) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
+        return mRightButton.getIntent();
     }
 
     /**
@@ -295,33 +328,19 @@
     }
 
     private void updateCameraVisibility() {
-        if (mCameraImageView == null) {
+        if (mRightAffordanceView == null) {
             // Things are not set up yet; reply hazy, ask again later
             return;
         }
-        ResolveInfo resolved = resolveCameraIntent();
-        boolean visible = !isCameraDisabledByDpm() && resolved != null
-                && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance)
-                && mUserSetupComplete;
-        mCameraImageView.setVisibility(visible ? View.VISIBLE : View.GONE);
+        mRightAffordanceView.setVisibility(mRightButton.getIcon().isVisible
+                ? View.VISIBLE : View.GONE);
     }
 
     private void updateLeftAffordanceIcon() {
-        mLeftIsVoiceAssist = canLaunchVoiceAssist();
-        int drawableId;
-        int contentDescription;
-        boolean visible = mUserSetupComplete;
-        if (mLeftIsVoiceAssist) {
-            drawableId = R.drawable.ic_mic_26dp;
-            contentDescription = R.string.accessibility_voice_assist_button;
-        } else {
-            visible &= isPhoneVisible();
-            drawableId = R.drawable.ic_phone_24dp;
-            contentDescription = R.string.accessibility_phone_button;
-        }
-        mLeftAffordanceView.setVisibility(visible ? View.VISIBLE : View.GONE);
-        mLeftAffordanceView.setImageDrawable(mContext.getDrawable(drawableId));
-        mLeftAffordanceView.setContentDescription(mContext.getString(contentDescription));
+        IconState state = mLeftButton.getIcon();
+        mLeftAffordanceView.setVisibility(state.isVisible ? View.VISIBLE : View.GONE);
+        mLeftAffordanceView.setImageDrawable(state.drawable);
+        mLeftAffordanceView.setContentDescription(state.contentDescription);
     }
 
     public boolean isLeftVoiceAssist() {
@@ -362,16 +381,16 @@
 
     @Override
     public void onStateChanged(boolean accessibilityEnabled, boolean touchExplorationEnabled) {
-        mCameraImageView.setClickable(touchExplorationEnabled);
+        mRightAffordanceView.setClickable(touchExplorationEnabled);
         mLeftAffordanceView.setClickable(touchExplorationEnabled);
-        mCameraImageView.setFocusable(accessibilityEnabled);
+        mRightAffordanceView.setFocusable(accessibilityEnabled);
         mLeftAffordanceView.setFocusable(accessibilityEnabled);
         mLockIcon.update();
     }
 
     @Override
     public void onClick(View v) {
-        if (v == mCameraImageView) {
+        if (v == mRightAffordanceView) {
             launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
         } else if (v == mLeftAffordanceView) {
             launchLeftAffordance();
@@ -540,7 +559,7 @@
                 }
             });
         } else {
-            mActivityStarter.startActivity(PHONE_INTENT, false /* dismissShade */);
+            mActivityStarter.startActivity(mLeftButton.getIntent(), false /* dismissShade */);
         }
     }
 
@@ -559,7 +578,7 @@
     }
 
     public KeyguardAffordanceView getRightView() {
-        return mCameraImageView;
+        return mRightAffordanceView;
     }
 
     public View getLeftPreview() {
@@ -612,7 +631,7 @@
             mLeftPreview = mPreviewInflater.inflatePreviewFromService(
                     mAssistManager.getVoiceInteractorComponentName());
         } else {
-            mLeftPreview = mPreviewInflater.inflatePreview(PHONE_INTENT);
+            mLeftPreview = mPreviewInflater.inflatePreview(mLeftButton.getIntent());
         }
         if (mLeftPreview != null) {
             mPreviewContainer.addView(mLeftPreview);
@@ -628,8 +647,8 @@
         }
         startFinishDozeAnimationElement(mLockIcon, delay);
         delay += DOZE_ANIMATION_STAGGER_DELAY;
-        if (mCameraImageView.getVisibility() == View.VISIBLE) {
-            startFinishDozeAnimationElement(mCameraImageView, delay);
+        if (mRightAffordanceView.getVisibility() == View.VISIBLE) {
+            startFinishDozeAnimationElement(mRightAffordanceView, delay);
         }
         mIndicationText.setAlpha(0f);
         mIndicationText.animate()
@@ -663,46 +682,46 @@
 
     private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
             new KeyguardUpdateMonitorCallback() {
-        @Override
-        public void onUserSwitchComplete(int userId) {
-            updateCameraVisibility();
-        }
+                @Override
+                public void onUserSwitchComplete(int userId) {
+                    updateCameraVisibility();
+                }
 
-        @Override
-        public void onStartedWakingUp() {
-            mLockIcon.setDeviceInteractive(true);
-        }
+                @Override
+                public void onStartedWakingUp() {
+                    mLockIcon.setDeviceInteractive(true);
+                }
 
-        @Override
-        public void onFinishedGoingToSleep(int why) {
-            mLockIcon.setDeviceInteractive(false);
-        }
+                @Override
+                public void onFinishedGoingToSleep(int why) {
+                    mLockIcon.setDeviceInteractive(false);
+                }
 
-        @Override
-        public void onScreenTurnedOn() {
-            mLockIcon.setScreenOn(true);
-        }
+                @Override
+                public void onScreenTurnedOn() {
+                    mLockIcon.setScreenOn(true);
+                }
 
-        @Override
-        public void onScreenTurnedOff() {
-            mLockIcon.setScreenOn(false);
-        }
+                @Override
+                public void onScreenTurnedOff() {
+                    mLockIcon.setScreenOn(false);
+                }
 
-        @Override
-        public void onKeyguardVisibilityChanged(boolean showing) {
-            mLockIcon.update();
-        }
+                @Override
+                public void onKeyguardVisibilityChanged(boolean showing) {
+                    mLockIcon.update();
+                }
 
-        @Override
-        public void onFingerprintRunningStateChanged(boolean running) {
-            mLockIcon.update();
-        }
+                @Override
+                public void onFingerprintRunningStateChanged(boolean running) {
+                    mLockIcon.update();
+                }
 
-        @Override
-        public void onStrongAuthStateChanged(int userId) {
-            mLockIcon.update();
-        }
-    };
+                @Override
+                public void onStrongAuthStateChanged(int userId) {
+                    mLockIcon.update();
+                }
+            };
 
     public void setKeyguardIndicationController(
             KeyguardIndicationController keyguardIndicationController) {
@@ -723,4 +742,96 @@
         updateLeftAffordance();
         inflateCameraPreview();
     }
+
+    private void setRightButton(IntentButton button) {
+        mRightButton = button;
+        updateRightAffordanceIcon();
+        updateCameraVisibility();
+        inflateCameraPreview();
+    }
+
+    private void setLeftButton(IntentButton button) {
+        mLeftButton = button;
+        mLeftIsVoiceAssist = false;
+        updateLeftAffordance();
+    }
+
+    private final PluginListener<IntentButtonProvider> mRightListener =
+            new PluginListener<IntentButtonProvider>() {
+        @Override
+        public void onPluginConnected(IntentButtonProvider plugin) {
+            setRightButton(plugin.getIntentButton());
+        }
+
+        @Override
+        public void onPluginDisconnected(IntentButtonProvider plugin) {
+            setRightButton(new DefaultRightButton());
+        }
+    };
+
+    private final PluginListener<IntentButtonProvider> mLeftListener =
+            new PluginListener<IntentButtonProvider>() {
+        @Override
+        public void onPluginConnected(IntentButtonProvider plugin) {
+            setLeftButton(plugin.getIntentButton());
+        }
+
+        @Override
+        public void onPluginDisconnected(IntentButtonProvider plugin) {
+            setLeftButton(new DefaultLeftButton());
+        }
+    };
+
+    private class DefaultLeftButton implements IntentButton {
+
+        private IconState mIconState = new IconState();
+
+        @Override
+        public IconState getIcon() {
+            mLeftIsVoiceAssist = canLaunchVoiceAssist();
+            if (mLeftIsVoiceAssist) {
+                mIconState.isVisible = mUserSetupComplete;
+                mIconState.drawable = mContext.getDrawable(R.drawable.ic_mic_26dp);
+                mIconState.contentDescription = mContext.getString(
+                        R.string.accessibility_voice_assist_button);
+            } else {
+                mIconState.isVisible = mUserSetupComplete && isPhoneVisible();
+                mIconState.drawable = mContext.getDrawable(R.drawable.ic_phone_24dp);
+                mIconState.contentDescription = mContext.getString(
+                        R.string.accessibility_phone_button);
+            }
+            return mIconState;
+        }
+
+        @Override
+        public Intent getIntent() {
+            return PHONE_INTENT;
+        }
+    }
+
+    private class DefaultRightButton implements IntentButton {
+
+        private IconState mIconState = new IconState();
+
+        @Override
+        public IconState getIcon() {
+            ResolveInfo resolved = resolveCameraIntent();
+            mIconState.isVisible = !isCameraDisabledByDpm() && resolved != null
+                    && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance)
+                    && mUserSetupComplete;
+            mIconState.drawable = mContext.getDrawable(R.drawable.ic_camera_alt_24dp);
+            mIconState.contentDescription =
+                    mContext.getString(R.string.accessibility_camera_button);
+            return mIconState;
+        }
+
+        @Override
+        public Intent getIntent() {
+            KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+            boolean canSkipBouncer = updateMonitor.getUserCanSkipBouncer(
+                    KeyguardUpdateMonitor.getCurrentUser());
+            boolean secure = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser());
+            return (secure && !canSkipBouncer) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index 0de06c9..af9454c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.ContactsContract;
 import android.text.TextUtils;
@@ -31,8 +30,8 @@
 import android.widget.FrameLayout;
 
 import com.android.systemui.R;
+import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
 import com.android.systemui.qs.QSPanel;
-import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 
@@ -183,7 +182,7 @@
         return false;
     }
 
-    protected QSTile.DetailAdapter getUserDetailAdapter() {
+    protected DetailAdapter getUserDetailAdapter() {
         return mUserSwitcherController.userDetailAdapter;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 06c8b68..c420927 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -28,12 +28,19 @@
 import android.widget.Space;
 
 import com.android.systemui.R;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider;
 import com.android.systemui.statusbar.policy.KeyButtonView;
 import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Objects;
 
-public class NavigationBarInflaterView extends FrameLayout implements TunerService.Tunable {
+public class NavigationBarInflaterView extends FrameLayout
+        implements Tunable, PluginListener<NavBarButtonProvider> {
 
     private static final String TAG = "NavBarInflater";
 
@@ -57,6 +64,8 @@
     public static final String KEY_IMAGE_DELIM = ":";
     public static final String KEY_CODE_END = ")";
 
+    private final List<NavBarButtonProvider> mPlugins = new ArrayList<>();
+
     protected LayoutInflater mLayoutInflater;
     protected LayoutInflater mLandscapeInflater;
     private int mDensity;
@@ -129,6 +138,8 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         TunerService.get(getContext()).addTunable(this, NAV_BAR_VIEWS);
+        PluginManager.getInstance(getContext()).addPluginListener(NavBarButtonProvider.ACTION, this,
+                NavBarButtonProvider.VERSION, true /* Allow multiple */);
     }
 
     @Override
@@ -240,8 +251,36 @@
             int indexInParent) {
         LayoutInflater inflater = landscape ? mLandscapeInflater : mLayoutInflater;
         float size = extractSize(buttonSpec);
-        String button = extractButton(buttonSpec);
+        View v = createView(buttonSpec, parent, inflater, landscape);
+        if (v == null) return null;
+
+        if (size != 0) {
+            ViewGroup.LayoutParams params = v.getLayoutParams();
+            params.width = (int) (params.width * size);
+        }
+        parent.addView(v);
+        addToDispatchers(v, landscape);
+        View lastView = landscape ? mLastRot90 : mLastRot0;
+        if (lastView != null) {
+            v.setAccessibilityTraversalAfter(lastView.getId());
+        }
+        if (landscape) {
+            mLastRot90 = v;
+        } else {
+            mLastRot0 = v;
+        }
+        return v;
+    }
+
+    private View createView(String buttonSpec, ViewGroup parent, LayoutInflater inflater,
+            boolean landscape) {
         View v = null;
+        String button = extractButton(buttonSpec);
+        // Let plugins go first so they can override a standard view if they want.
+        for (NavBarButtonProvider provider : mPlugins) {
+            v = provider.createView(buttonSpec, parent);
+            if (v != null) return v;
+        }
         if (HOME.equals(button)) {
             v = inflater.inflate(R.layout.home, parent, false);
             if (landscape && isSw600Dp()) {
@@ -271,24 +310,6 @@
             if (uri != null) {
                 ((KeyButtonView) v).loadAsync(uri);
             }
-        } else {
-            return null;
-        }
-
-        if (size != 0) {
-            ViewGroup.LayoutParams params = v.getLayoutParams();
-            params.width = (int) (params.width * size);
-        }
-        parent.addView(v);
-        addToDispatchers(v, landscape);
-        View lastView = landscape ? mLastRot90 : mLastRot0;
-        if (lastView != null) {
-            v.setAccessibilityTraversalAfter(lastView.getId());
-        }
-        if (landscape) {
-            mLastRot90 = v;
-        } else {
-            mLastRot0 = v;
         }
         return v;
     }
@@ -374,4 +395,18 @@
             ((ViewGroup) group.getChildAt(i)).removeAllViews();
         }
     }
+
+    @Override
+    public void onPluginConnected(NavBarButtonProvider plugin) {
+        mPlugins.add(plugin);
+        clearViews();
+        inflateLayout(mCurrentLayout);
+    }
+
+    @Override
+    public void onPluginDisconnected(NavBarButtonProvider plugin) {
+        mPlugins.remove(plugin);
+        clearViews();
+        inflateLayout(mCurrentLayout);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 812c5c1..fb2c335 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -50,7 +50,7 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingManager;
-import com.android.systemui.qs.QSContainer;
+import com.android.systemui.plugins.qs.QSContainer;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.ExpandableView;
 import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -70,7 +70,7 @@
         ExpandableView.OnHeightChangedListener,
         View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
         KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener,
-        HeadsUpManager.OnHeadsUpChangedListener {
+        HeadsUpManager.OnHeadsUpChangedListener, QSContainer.HeightListener {
 
     private static final boolean DEBUG = false;
 
@@ -242,7 +242,7 @@
             public void onInflated(View v) {
                 mQsContainer = (QSContainer) v.findViewById(R.id.quick_settings_container);
                 mQsContainer.setPanelView(NotificationPanelView.this);
-                mQsContainer.getHeader().findViewById(R.id.expand_indicator)
+                mQsContainer.getHeader().getExpandView()
                         .setOnClickListener(NotificationPanelView.this);
 
                 // recompute internal state when qspanel height changes
@@ -328,7 +328,7 @@
         } else if (!mQsExpanded) {
             setQsExpansion(mQsMinExpansionHeight + mLastOverscroll);
         }
-        updateStackHeight(getExpandedHeight());
+        updateExpandedHeight(getExpandedHeight());
         updateHeader();
 
         // If we are running a size change animation, the animation takes care of the height of
@@ -376,10 +376,7 @@
         boolean animate = mNotificationStackScroller.isAddOrRemoveAnimationPending();
         int stackScrollerPadding;
         if (mStatusBarState != StatusBarState.KEYGUARD) {
-            int bottom = mQsContainer.getHeader().getHeight();
-            stackScrollerPadding = mStatusBarState == StatusBarState.SHADE
-                    ? bottom + mQsPeekHeight
-                    : mKeyguardStatusBar.getHeight();
+            stackScrollerPadding = mQsContainer.getHeader().getHeight() + mQsPeekHeight;
             mTopPaddingAdjustment = 0;
         } else {
             mClockPositionAlgorithm.setup(
@@ -1166,6 +1163,7 @@
 
     private void updateQsState() {
         mQsContainer.setExpanded(mQsExpanded);
+        mNotificationStackScroller.setQsExpanded(mQsExpanded);
         mNotificationStackScroller.setScrollingEnabled(
                 mStatusBarState != StatusBarState.KEYGUARD && (!mQsExpanded
                         || mQsExpansionFromOverscroll));
@@ -1427,7 +1425,7 @@
             setQsExpansion(mQsMinExpansionHeight
                     + t * (getTempQsMaxExpansion() - mQsMinExpansionHeight));
         }
-        updateStackHeight(expandedHeight);
+        updateExpandedHeight(expandedHeight);
         updateHeader();
         updateUnlockIcon();
         updateNotificationTranslucency();
@@ -1487,7 +1485,7 @@
                 maxQsHeight, mStatusBarState == StatusBarState.KEYGUARD
                         ? mClockPositionResult.stackScrollerPadding - mTopPaddingAdjustment
                         : 0)
-                + notificationHeight;
+                + notificationHeight + mNotificationStackScroller.getTopPaddingOverflow();
         if (totalHeight > mNotificationStackScroller.getHeight()) {
             float fullyCollapsedHeight = maxQsHeight
                     + mNotificationStackScroller.getLayoutMinHeight();
@@ -1730,6 +1728,14 @@
         if (view == null && mQsExpanded) {
             return;
         }
+        ExpandableView firstChildNotGone = mNotificationStackScroller.getFirstChildNotGone();
+        ExpandableNotificationRow firstRow = firstChildNotGone instanceof ExpandableNotificationRow
+                ? (ExpandableNotificationRow) firstChildNotGone
+                : null;
+        if (firstRow != null
+                && (view == firstRow || (firstRow.getNotificationParent() == firstRow))) {
+            requestScrollerTopPaddingUpdate(false);
+        }
         requestPanelHeightUpdate();
     }
 
@@ -2011,7 +2017,7 @@
     }
 
     public void closeQsDetail() {
-        mQsContainer.getQsPanel().closeDetail();
+        mQsContainer.closeDetail();
     }
 
     @Override
@@ -2249,8 +2255,8 @@
         mQsAutoReinflateContainer.setTranslationX(translation);
     }
 
-    protected void updateStackHeight(float stackHeight) {
-        mNotificationStackScroller.setStackHeight(stackHeight);
+    protected void updateExpandedHeight(float expandedHeight) {
+        mNotificationStackScroller.setExpandedHeight(expandedHeight);
         updateKeyguardBottomAreaAlpha();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
index 36e59db..8b1fcd6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
@@ -24,10 +24,10 @@
 import android.view.ViewStub;
 import android.view.WindowInsets;
 import android.widget.FrameLayout;
+
 import com.android.systemui.AutoReinflateContainer;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSContainer;
-import com.android.systemui.qs.customize.QSCustomizer;
+import com.android.systemui.plugins.qs.QSContainer;
 
 /**
  * The container with notification stack scroller and quick settings inside.
@@ -130,8 +130,8 @@
 
     @Override
     public void onInflated(View v) {
-        QSCustomizer customizer = ((QSContainer) v).getCustomizer();
-        customizer.setContainer(this);
+        QSContainer container = (QSContainer) v;
+        container.setContainer(this);
     }
 
     public void setQsExpanded(boolean expanded) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 089f7a9..8ee014c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -141,7 +141,10 @@
 import com.android.systemui.doze.DozeHost;
 import com.android.systemui.doze.DozeLog;
 import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.qs.QSContainer;
+import com.android.systemui.plugins.qs.QSContainer.ActivityStarter;
+import com.android.systemui.plugins.qs.QSContainer.BaseStatusBarHeader;
+import com.android.systemui.plugins.qs.QSContainer;
+import com.android.systemui.qs.QSContainerImpl;
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.recents.ScreenPinningRequest;
 import com.android.systemui.recents.events.EventBus;
@@ -175,12 +178,14 @@
 import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 import com.android.systemui.statusbar.policy.CastControllerImpl;
+import com.android.systemui.statusbar.policy.EncryptionHelper;
 import com.android.systemui.statusbar.policy.FlashlightController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.HotspotControllerImpl;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
 import com.android.systemui.statusbar.policy.LocationControllerImpl;
+import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl;
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.PreviewInflater;
@@ -308,7 +313,7 @@
     PhoneStatusBarPolicy mIconPolicy;
 
     // These are no longer handled by the policy, because we need custom strategies for them
-    BluetoothControllerImpl mBluetoothController;
+    protected BluetoothControllerImpl mBluetoothController;
     SecurityControllerImpl mSecurityController;
     protected BatteryController mBatteryController;
     LocationControllerImpl mLocationController;
@@ -897,6 +902,7 @@
 
         initSignalCluster(mStatusBarView);
         initSignalCluster(mKeyguardStatusBar);
+        initEmergencyCryptkeeperText();
 
         mFlashlightController = new FlashlightController(mContext);
         mKeyguardBottomArea.setFlashlightController(mFlashlightController);
@@ -930,10 +936,12 @@
                 public void onInflated(View v) {
                     QSContainer qsContainer = (QSContainer) v.findViewById(
                             R.id.quick_settings_container);
-                    qsContainer.setHost(qsh);
-                    mQSPanel = qsContainer.getQsPanel();
-                    mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
-                    mKeyguardStatusBar.setQSPanel(mQSPanel);
+                    if (qsContainer instanceof QSContainerImpl) {
+                        ((QSContainerImpl) qsContainer).setHost(qsh);
+                        mQSPanel = ((QSContainerImpl) qsContainer).getQsPanel();
+                        mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
+                        mKeyguardStatusBar.setQSPanel(mQSPanel);
+                    }
                     mHeader = qsContainer.getHeader();
                     initSignalCluster(mHeader);
                     mHeader.setActivityStarter(PhoneStatusBar.this);
@@ -1014,6 +1022,24 @@
         return mStatusBarView;
     }
 
+    private void initEmergencyCryptkeeperText() {
+        View emergencyViewStub = mStatusBarWindow.findViewById(R.id.emergency_cryptkeeper_text);
+        if (mNetworkController.hasEmergencyCryptKeeperText()) {
+            if (emergencyViewStub != null) {
+                ((ViewStub) emergencyViewStub).inflate();
+            }
+            mNetworkController.addSignalCallback(new NetworkController.SignalCallback() {
+                @Override
+                public void setIsAirplaneMode(NetworkController.IconState icon) {
+                    recomputeDisableFlags(true /* animate */);
+                }
+            });
+        } else if (emergencyViewStub != null) {
+            ViewGroup parent = (ViewGroup) emergencyViewStub.getParent();
+            parent.removeView(emergencyViewStub);
+        }
+    }
+
     protected BatteryController createBatteryController() {
         return new BatteryControllerImpl(mContext);
     }
@@ -1707,7 +1733,7 @@
     protected void performRemoveNotification(StatusBarNotification n, boolean removeView) {
         Entry entry = mNotificationData.get(n.getKey());
         if (mRemoteInputController.isRemoteInputActive(entry)) {
-            mRemoteInputController.removeRemoteInput(entry);
+            mRemoteInputController.removeRemoteInput(entry, null);
         }
         super.performRemoveNotification(n, removeView);
     }
@@ -2346,6 +2372,14 @@
             state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
             state |= StatusBarManager.DISABLE_SYSTEM_INFO;
         }
+        if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
+            if (mNetworkController.hasEmergencyCryptKeeperText()) {
+                state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
+            }
+            if (!mNetworkController.isRadioOn()) {
+                state |= StatusBarManager.DISABLE_SYSTEM_INFO;
+            }
+        }
         return state;
     }
 
@@ -2450,6 +2484,15 @@
         }
     }
 
+    /**
+     * Reapplies the disable flags as last requested by StatusBarManager.
+     *
+     * This needs to be called if state used by {@link #adjustDisableFlags} changes.
+     */
+    private void recomputeDisableFlags(boolean animate) {
+        disable(mDisabledUnmodified1, mDisabledUnmodified2, animate);
+    }
+
     @Override
     protected BaseStatusBar.H createHandler() {
         return new PhoneStatusBar.H();
@@ -2638,7 +2681,7 @@
     private void removeRemoteInputEntriesKeptUntilCollapsed() {
         for (int i = 0; i < mRemoteInputEntriesToRemoveOnCollapse.size(); i++) {
             Entry entry = mRemoteInputEntriesToRemoveOnCollapse.valueAt(i);
-            mRemoteInputController.removeRemoteInput(entry);
+            mRemoteInputController.removeRemoteInput(entry, null);
             removeNotification(entry.key, mLatestRankingMap);
         }
         mRemoteInputEntriesToRemoveOnCollapse.clear();
@@ -2743,7 +2786,7 @@
 
         visibilityChanged(true);
         mWaitingForKeyguardExit = false;
-        disable(mDisabledUnmodified1, mDisabledUnmodified2, !force /* animate */);
+        recomputeDisableFlags(!force /* animate */);
         setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true);
     }
 
@@ -2885,7 +2928,7 @@
         runPostCollapseRunnables();
         setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
         showBouncer();
-        disable(mDisabledUnmodified1, mDisabledUnmodified2, true /* animate */);
+        recomputeDisableFlags(true /* animate */);
 
         // Trimming will happen later if Keyguard is showing - doing it here might cause a jank in
         // the bouncer appear animation.
@@ -4270,7 +4313,7 @@
                 startTime + fadeoutDuration
                         - StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION,
                 StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION);
-        disable(mDisabledUnmodified1, mDisabledUnmodified2, fadeoutDuration > 0 /* animate */);
+        recomputeDisableFlags(fadeoutDuration > 0 /* animate */);
     }
 
     public boolean isKeyguardFadingAway() {
@@ -4762,7 +4805,7 @@
     public void setBouncerShowing(boolean bouncerShowing) {
         super.setBouncerShowing(bouncerShowing);
         mStatusBarView.setBouncerShowing(bouncerShowing);
-        disable(mDisabledUnmodified1, mDisabledUnmodified2, true /* animate */);
+        recomputeDisableFlags(true /* animate */);
     }
 
     public void onStartedGoingToSleep() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index 3ad09d1..b0b86be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -37,12 +37,15 @@
 import com.android.keyguard.KeyguardStatusView;
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
+import com.android.systemui.plugins.qs.QSContainer.ActivityStarter;
+import com.android.systemui.plugins.qs.QSContainer.BaseStatusBarHeader;
 import com.android.systemui.qs.QSPanel;
-import com.android.systemui.qs.QSPanel.Callback;
+import com.android.systemui.plugins.qs.QSContainer.Callback;
 import com.android.systemui.qs.QuickQSPanel;
 import com.android.systemui.qs.TouchAnimator;
 import com.android.systemui.qs.TouchAnimator.Builder;
 import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
 import com.android.systemui.statusbar.policy.UserInfoController;
@@ -50,7 +53,7 @@
 import com.android.systemui.tuner.TunerService;
 
 public class QuickStatusBarHeader extends BaseStatusBarHeader implements
-        NextAlarmChangeCallback, OnClickListener, OnUserInfoChangedListener {
+        NextAlarmChangeCallback, OnClickListener, OnUserInfoChangedListener, EmergencyListener {
 
     private static final String TAG = "QuickStatusBarHeader";
 
@@ -255,6 +258,11 @@
     }
 
     @Override
+    public View getExpandView() {
+        return findViewById(R.id.expand_indicator);
+    }
+
+    @Override
     public void updateEverything() {
         post(() -> {
             updateVisibilities();
@@ -293,7 +301,6 @@
         mActivityStarter = activityStarter;
     }
 
-    @Override
     public void setQSPanel(final QSPanel qsPanel) {
         mQsPanel = qsPanel;
         setupHost(qsPanel.getHost());
@@ -354,17 +361,14 @@
                 true /* dismissShade */);
     }
 
-    @Override
     public void setNextAlarmController(NextAlarmController nextAlarmController) {
         mNextAlarmController = nextAlarmController;
     }
 
-    @Override
     public void setBatteryController(BatteryController batteryController) {
         // Don't care
     }
 
-    @Override
     public void setUserInfoController(UserInfoController userInfoController) {
         userInfoController.addListener(this);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
new file mode 100644
index 0000000..8abfb89
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.provider.Settings;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionInfo;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.widget.TextView;
+
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+
+import java.util.List;
+
+public class EmergencyCryptkeeperText extends TextView {
+
+    private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    private KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
+        @Override
+        public void onPhoneStateChanged(int phoneState) {
+            update();
+        }
+    };
+
+    public EmergencyCryptkeeperText(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+        setVisibility(GONE);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+        mKeyguardUpdateMonitor.registerCallback(mCallback);
+        update();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        if (mKeyguardUpdateMonitor != null) {
+            mKeyguardUpdateMonitor.removeCallback(mCallback);
+        }
+    }
+
+    public void update() {
+        boolean hasMobile = ConnectivityManager.from(mContext)
+                .isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
+        boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
+
+        if (!hasMobile || airplaneMode) {
+            setText(null);
+            setVisibility(GONE);
+            return;
+        }
+
+        boolean allSimsMissing = true;
+        CharSequence displayText = null;
+
+        List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false);
+        final int N = subs.size();
+        for (int i = 0; i < N; i++) {
+            int subId = subs.get(i).getSubscriptionId();
+            IccCardConstants.State simState = mKeyguardUpdateMonitor.getSimState(subId);
+            CharSequence carrierName = subs.get(i).getCarrierName();
+            if (simState.iccCardExist() && !TextUtils.isEmpty(carrierName)) {
+                allSimsMissing = false;
+                displayText = carrierName;
+            }
+        }
+        if (allSimsMissing) {
+            if (N != 0) {
+                // Shows "Emergency calls only" on devices that are voice-capable.
+                // This depends on mPlmn containing the text "Emergency calls only" when the radio
+                // has some connectivity. Otherwise it should show "No service"
+                // Grab the first subscription, because they all should contain the emergency text,
+                // described above.
+                displayText = subs.get(0).getCarrierName();
+            } else {
+                // We don't have a SubscriptionInfo to get the emergency calls only from.
+                // Grab it from the old sticky broadcast if possible instead. We can use it
+                // here because no subscriptions are active, so we don't have
+                // to worry about MSIM clashing.
+                displayText = getContext().getText(
+                        com.android.internal.R.string.emergency_calls_only);
+                Intent i = getContext().registerReceiver(null,
+                        new IntentFilter(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION));
+                if (i != null) {
+                    displayText = i.getStringExtra(TelephonyIntents.EXTRA_PLMN);
+                }
+            }
+        }
+
+        setText(displayText);
+        setVisibility(TextUtils.isEmpty(displayText) ? GONE : VISIBLE);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EncryptionHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EncryptionHelper.java
new file mode 100644
index 0000000..639e50c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EncryptionHelper.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.os.SystemProperties;
+
+/**
+ * Helper for determining whether the phone is decrypted yet.
+ */
+public class EncryptionHelper {
+
+    public static final boolean IS_DATA_ENCRYPTED = isDataEncrypted();
+
+    private static boolean isDataEncrypted() {
+        String voldState = SystemProperties.get("vold.decrypt");
+        return "1".equals(voldState) || "trigger_restart_min_framework".equals(voldState);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index e6066aa..bcc5a3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -44,12 +44,12 @@
 import android.widget.ImageView;
 
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.ButtonDispatcher;
+import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
 
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
 
-public class KeyButtonView extends ImageView implements ButtonDispatcher.ButtonInterface {
+public class KeyButtonView extends ImageView implements ButtonInterface {
 
     private int mContentDescriptionRes;
     private long mDownTime;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 348e0b0..5f1b871 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -41,20 +41,20 @@
     void removeEmergencyListener(EmergencyListener listener);
 
     public interface SignalCallback {
-        void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
-                boolean activityIn, boolean activityOut, String description);
+        default void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
+                boolean activityIn, boolean activityOut, String description) {}
 
-        void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
+        default void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
                 int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
-                String description, boolean isWide, int subId);
-        void setSubs(List<SubscriptionInfo> subs);
-        void setNoSims(boolean show);
+                String description, boolean isWide, int subId) {}
+        default void setSubs(List<SubscriptionInfo> subs) {}
+        default void setNoSims(boolean show) {}
 
-        void setEthernetIndicators(IconState icon);
+        default void setEthernetIndicators(IconState icon) {}
 
-        void setIsAirplaneMode(IconState icon);
+        default void setIsAirplaneMode(IconState icon) {}
 
-        void setMobileDataEnabled(boolean enabled);
+        default void setMobileDataEnabled(boolean enabled) {}
     }
 
     public interface EmergencyListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 7893a1a..37e6a2a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -819,6 +819,14 @@
         return info;
     }
 
+    public boolean hasEmergencyCryptKeeperText() {
+        return EncryptionHelper.IS_DATA_ENCRYPTED;
+    }
+
+    public boolean isRadioOn() {
+        return !mAirplaneMode;
+    }
+
     private class SubListener extends OnSubscriptionsChangedListener {
         @Override
         public void onSubscriptionsChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index ab2a8bc..7b1f707 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -69,6 +69,8 @@
     // A marker object that let's us easily find views of this class.
     public static final Object VIEW_TAG = new Object();
 
+    public final Object mToken = new Object();
+
     private RemoteEditText mEditText;
     private ImageButton mSendButton;
     private ProgressBar mProgressBar;
@@ -140,8 +142,8 @@
         mSendButton.setVisibility(INVISIBLE);
         mProgressBar.setVisibility(VISIBLE);
         mEntry.remoteInputText = mEditText.getText();
-        mController.addSpinning(mEntry.key);
-        mController.removeRemoteInput(mEntry);
+        mController.addSpinning(mEntry.key, mToken);
+        mController.removeRemoteInput(mEntry, mToken);
         mEditText.mShowImeOnInputConnection = false;
         mController.remoteInputSent(mEntry);
 
@@ -193,7 +195,7 @@
     }
 
     private void onDefocus(boolean animate) {
-        mController.removeRemoteInput(mEntry);
+        mController.removeRemoteInput(mEntry, mToken);
         mEntry.remoteInputText = mEditText.getText();
 
         // During removal, we get reattached and lose focus. Not hiding in that
@@ -232,11 +234,11 @@
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
-        if (mEntry.row.isChangingPosition()) {
+        if (mEntry.row.isChangingPosition() || isTemporarilyDetached()) {
             return;
         }
-        mController.removeRemoteInput(mEntry);
-        mController.removeSpinning(mEntry.key);
+        mController.removeRemoteInput(mEntry, mToken);
+        mController.removeSpinning(mEntry.key, mToken);
     }
 
     public void setPendingIntent(PendingIntent pendingIntent) {
@@ -265,7 +267,7 @@
                 mEntry.notification.getPackageName());
 
         setVisibility(VISIBLE);
-        mController.addRemoteInput(mEntry);
+        mController.addRemoteInput(mEntry, mToken);
         mEditText.setInnerFocusable(true);
         mEditText.mShowImeOnInputConnection = true;
         mEditText.setText(mEntry.remoteInputText);
@@ -290,7 +292,7 @@
         mEditText.setEnabled(true);
         mSendButton.setVisibility(VISIBLE);
         mProgressBar.setVisibility(INVISIBLE);
-        mController.removeSpinning(mEntry.key);
+        mController.removeSpinning(mEntry.key, mToken);
         updateSendButton();
         onDefocus(false /* animate */);
 
@@ -432,6 +434,24 @@
         mRevealR = r;
     }
 
+    @Override
+    public void dispatchStartTemporaryDetach() {
+        super.dispatchStartTemporaryDetach();
+        // Detach the EditText temporarily such that it doesn't get onDetachedFromWindow and
+        // won't lose IME focus.
+        detachViewFromParent(mEditText);
+    }
+
+    @Override
+    public void dispatchFinishTemporaryDetach() {
+        if (isAttachedToWindow()) {
+            attachViewToParent(mEditText, 0, mEditText.getLayoutParams());
+        } else {
+            removeDetachedView(mEditText, false /* animate */);
+        }
+        super.dispatchFinishTemporaryDetach();
+    }
+
     /**
      * An EditText that changes appearance based on whether it's focusable and becomes
      * un-focusable whenever the user navigates away from it or it becomes invisible.
@@ -448,7 +468,15 @@
         }
 
         private void defocusIfNeeded(boolean animate) {
-            if (mRemoteInputView != null && mRemoteInputView.mEntry.row.isChangingPosition()) {
+            if (mRemoteInputView != null && mRemoteInputView.mEntry.row.isChangingPosition()
+                    || isTemporarilyDetached()) {
+                if (isTemporarilyDetached()) {
+                    // We might get reattached but then the other one of HUN / expanded might steal
+                    // our focus, so we'll need to save our text here.
+                    if (mRemoteInputView != null) {
+                        mRemoteInputView.mEntry.remoteInputText = getText();
+                    }
+                }
                 return;
             }
             if (isFocusable() && isEnabled()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index c3becb0..30d1c54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -50,15 +50,14 @@
 
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.internal.util.UserIcons;
-import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.systemui.GuestResumeSessionReceiver;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 import com.android.systemui.SystemUISecondaryUserService;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
 import com.android.systemui.qs.tiles.UserDetailView;
-import com.android.systemui.statusbar.phone.ActivityStarter;
+import com.android.systemui.plugins.qs.QSContainer.ActivityStarter;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 
 import java.io.FileDescriptor;
@@ -793,7 +792,7 @@
         }
     }
 
-    public final QSTile.DetailAdapter userDetailAdapter = new QSTile.DetailAdapter() {
+    public final DetailAdapter userDetailAdapter = new DetailAdapter() {
         private final Intent USER_SETTINGS_INTENT = new Intent(Settings.ACTION_USER_SETTINGS);
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index 50e5b88..81da672 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -43,6 +43,7 @@
     private boolean mShadeExpanded;
     private float mMaxHeadsUpTranslation;
     private boolean mDismissAllInProgress;
+    private int mLayoutMinHeight;
 
     public int getScrollY() {
         return mScrollY;
@@ -137,10 +138,6 @@
         mStackTranslation = stackTranslation;
     }
 
-    public int getLayoutHeight() {
-        return mLayoutHeight;
-    }
-
     public void setLayoutHeight(int layoutHeight) {
         mLayoutHeight = layoutHeight;
     }
@@ -154,7 +151,7 @@
     }
 
     public int getInnerHeight() {
-        return mLayoutHeight - mTopPadding;
+        return Math.max(mLayoutHeight - mTopPadding, mLayoutMinHeight);
     }
 
     public boolean isShadeExpanded() {
@@ -180,4 +177,8 @@
     public boolean isDismissAllInProgress() {
         return mDismissAllInProgress;
     }
+
+    public void setLayoutMinHeight(int layoutMinHeight) {
+        mLayoutMinHeight = layoutMinHeight;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 38af030..a9dee13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -112,11 +112,7 @@
     private int mCurrentStackHeight = Integer.MAX_VALUE;
     private final Paint mBackgroundPaint = new Paint();
 
-    /**
-     * mCurrentStackHeight is the actual stack height, mLastSetStackHeight is the stack height set
-     * externally from {@link #setStackHeight}
-     */
-    private float mLastSetStackHeight;
+    private float mExpandedHeight;
     private int mOwnScrollY;
     private int mMaxLayoutHeight;
 
@@ -131,7 +127,7 @@
     private boolean mIsBeingDragged;
     private int mLastMotionY;
     private int mDownX;
-    private int mActivePointerId;
+    private int mActivePointerId = INVALID_POINTER;
     private boolean mTouchIsClick;
     private float mInitialTouchX;
     private float mInitialTouchY;
@@ -355,6 +351,7 @@
                     return object.getBackgroundFadeAmount();
                 }
             };
+    private boolean mQsExpanded;
 
     public NotificationStackScrollLayout(Context context) {
         this(context, null);
@@ -520,6 +517,7 @@
         clampScrollPosition();
         requestChildrenUpdate();
         updateFirstAndLastBackgroundViews();
+        updateAlgorithmLayoutMinHeight();
     }
 
     private void requestAnimationOnViewResize(ExpandableNotificationRow row) {
@@ -561,9 +559,14 @@
 
     private void updateAlgorithmHeightAndPadding() {
         mAmbientState.setLayoutHeight(getLayoutHeight());
+        updateAlgorithmLayoutMinHeight();
         mAmbientState.setTopPadding(mTopPadding);
     }
 
+    private void updateAlgorithmLayoutMinHeight() {
+        mAmbientState.setLayoutMinHeight(mQsExpanded && !onKeyguard() ? getLayoutMinHeight() : 0);
+    }
+
     /**
      * Updates the children views according to the stack scroll algorithm. Call this whenever
      * modifications to {@link #mOwnScrollY} are performed to reflect it in the view layout.
@@ -660,19 +663,19 @@
     }
 
     /**
-     * Update the height of the stack to a new height.
+     * Update the height of the panel.
      *
-     * @param height the new height of the stack
+     * @param height the expanded height of the panel
      */
-    public void setStackHeight(float height) {
-        mLastSetStackHeight = height;
+    public void setExpandedHeight(float height) {
+        mExpandedHeight = height;
         setIsExpanded(height > 0.0f);
         int stackHeight;
         float translationY;
         float appearEndPosition = getAppearEndPosition();
         float appearStartPosition = getAppearStartPosition();
         if (height >= appearEndPosition) {
-            translationY = mTopPaddingOverflow;
+            translationY = 0;
             stackHeight = (int) height;
         } else {
             float appearFraction = getAppearFraction(height);
@@ -699,8 +702,12 @@
      *         Measured relative to the resting position.
      */
     private float getExpandTranslationStart() {
-        int startPosition = mTrackingHeadsUp || mHeadsUpManager.hasPinnedHeadsUp()
-                ? 0 : -getFirstChildIntrinsicHeight();
+        int startPosition = 0;
+        if (!mTrackingHeadsUp && !mHeadsUpManager.hasPinnedHeadsUp()) {
+            startPosition = - Math.min(getFirstChildIntrinsicHeight(),
+                    mMaxLayoutHeight - mIntrinsicPadding - mBottomStackSlowDownHeight
+                            - mBottomStackPeekSize);
+        }
         return startPosition - mTopPadding;
     }
 
@@ -723,7 +730,7 @@
                 ? mHeadsUpManager.getTopHeadsUpPinnedHeight() + mBottomStackPeekSize
                         + mBottomStackSlowDownHeight
                 : getLayoutMinHeight();
-        return firstItemHeight + mTopPadding + mTopPaddingOverflow;
+        return firstItemHeight + (onKeyguard() ? mTopPadding : mIntrinsicPadding);
     }
 
     /**
@@ -1153,6 +1160,10 @@
 
     @Override
     public boolean isAntiFalsingNeeded() {
+        return onKeyguard();
+    }
+
+    private boolean onKeyguard() {
         return mPhoneStatusBar.getBarState() == StatusBarState.KEYGUARD;
     }
 
@@ -1262,7 +1273,7 @@
         if (!isScrollingEnabled()) {
             return false;
         }
-        if (isInsideQsContainer(ev)) {
+        if (isInsideQsContainer(ev) && !mIsBeingDragged) {
             return false;
         }
         mForcedScroll = null;
@@ -2158,26 +2169,22 @@
      */
     public void updateTopPadding(float qsHeight, boolean animate,
             boolean ignoreIntrinsicPadding) {
-        float start = qsHeight;
-        float stackHeight = getHeight() - start;
+        int topPadding = (int) qsHeight;
         int minStackHeight = getLayoutMinHeight();
-        if (stackHeight <= minStackHeight) {
-            float overflow = minStackHeight - stackHeight;
-            stackHeight = minStackHeight;
-            start = getHeight() - stackHeight;
-            mTopPaddingOverflow = overflow;
+        if (topPadding + minStackHeight > getHeight()) {
+            mTopPaddingOverflow = topPadding + minStackHeight - getHeight();
         } else {
             mTopPaddingOverflow = 0;
         }
-        setTopPadding(ignoreIntrinsicPadding ? (int) start : clampPadding((int) start),
+        setTopPadding(ignoreIntrinsicPadding ? topPadding : clampPadding(topPadding),
                 animate);
-        setStackHeight(mLastSetStackHeight);
+        setExpandedHeight(mExpandedHeight);
     }
 
     public int getLayoutMinHeight() {
         int firstChildMinHeight = getFirstChildIntrinsicHeight();
         return Math.min(firstChildMinHeight + mBottomStackPeekSize + mBottomStackSlowDownHeight,
-                mMaxLayoutHeight - mTopPadding);
+                mMaxLayoutHeight - mIntrinsicPadding);
     }
 
     public int getFirstChildIntrinsicHeight() {
@@ -3128,10 +3135,14 @@
         updateScrollPositionOnExpandInBottom(view);
         clampScrollPosition();
         notifyHeightChangeListener(view);
+        ExpandableNotificationRow row = view instanceof ExpandableNotificationRow
+                ? (ExpandableNotificationRow) view
+                : null;
+        if (row != null && (row == mFirstVisibleBackgroundChild
+                || row.getNotificationParent() == mFirstVisibleBackgroundChild)) {
+            updateAlgorithmLayoutMinHeight();
+        }
         if (needsAnimation) {
-            ExpandableNotificationRow row = view instanceof ExpandableNotificationRow
-                    ? (ExpandableNotificationRow) view
-                    : null;
             requestAnimationOnViewResize(row);
         }
         requestChildrenUpdate();
@@ -3414,7 +3425,7 @@
     }
 
     private int findDarkAnimationOriginIndex(@Nullable PointF screenLocation) {
-        if (screenLocation == null || screenLocation.y < mTopPadding + mTopPaddingOverflow) {
+        if (screenLocation == null || screenLocation.y < mTopPadding) {
             return AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_ABOVE;
         }
         if (screenLocation.y > getBottomMostNotificationBottom()) {
@@ -3898,6 +3909,11 @@
         mCurrentStackScrollState.removeViewStateForView(view);
     }
 
+    public void setQsExpanded(boolean qsExpanded) {
+        mQsExpanded = qsExpanded;
+        updateAlgorithmLayoutMinHeight();
+    }
+
     /**
      * A listener that is notified when some child locations might have changed.
      */
@@ -4121,7 +4137,7 @@
             onDragCancelled(animView);
 
             // If we're on the lockscreen we want to false this.
-            if (mPhoneStatusBar.getBarState() == StatusBarState.KEYGUARD) {
+            if (isAntiFalsingNeeded()) {
                 mHandler.removeCallbacks(mFalsingCheck);
                 mHandler.postDelayed(mFalsingCheck, COVER_GEAR_DELAY);
             }
@@ -4180,13 +4196,11 @@
                 final int rx = (int) ev.getRawX();
                 final int ry = (int) ev.getRawY();
 
-                getLocationOnScreen(mTempInt2);
-                int[] location = new int[2];
-                view.getLocationOnScreen(location);
-                final int x = location[0] - mTempInt2[0];
-                final int y = location[1] - mTempInt2[1];
+                view.getLocationOnScreen(mTempInt2);
+                final int x = mTempInt2[0];
+                final int y = mTempInt2[1];
                 Rect rect = new Rect(x, y, x + view.getWidth(), y + height);
-                if (!rect.contains((int) rx, (int) ry)) {
+                if (!rect.contains(rx, ry)) {
                     // Touch was outside visible guts / gear notification, close what's visible
                     mPhoneStatusBar.dismissPopups(-1, -1, true /* resetGear */, true /* animate */);
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
new file mode 100644
index 0000000..132a6dd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.tuner;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.PreferenceCategory;
+import android.support.v7.preference.PreferenceScreen;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.view.View;
+
+import com.android.systemui.plugins.PluginPrefs;
+import com.android.systemui.R;
+
+import java.util.List;
+import java.util.Set;
+
+public class PluginFragment extends PreferenceFragment {
+
+    public static final String ACTION_PLUGIN_SETTINGS
+            = "com.android.systemui.action.PLUGIN_SETTINGS";
+
+    private PluginPrefs mPluginPrefs;
+
+    @Override
+    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+        PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(getContext());
+        screen.setOrderingAsAdded(false);
+        Context prefContext = getPreferenceManager().getContext();
+        mPluginPrefs = new PluginPrefs(getContext());
+        Set<String> pluginActions = mPluginPrefs.getPluginList();
+        for (String action : pluginActions) {
+            String name = action.replace("com.android.systemui.action.PLUGIN_", "");
+            PreferenceCategory category = new PreferenceCategory(prefContext);
+            category.setTitle(name);
+
+            List<ResolveInfo> result = getContext().getPackageManager().queryIntentServices(
+                    new Intent(action), PackageManager.MATCH_DISABLED_COMPONENTS);
+            if (result.size() > 0) {
+                screen.addPreference(category);
+            }
+            for (ResolveInfo info : result) {
+                category.addPreference(new PluginPreference(prefContext, info));
+            }
+        }
+        setPreferenceScreen(screen);
+    }
+
+    private static class PluginPreference extends SwitchPreference {
+        private final ComponentName mComponent;
+        private final boolean mHasSettings;
+
+        public PluginPreference(Context prefContext, ResolveInfo info) {
+            super(prefContext);
+            mComponent = new ComponentName(info.serviceInfo.packageName, info.serviceInfo.name);
+            PackageManager pm = prefContext.getPackageManager();
+            mHasSettings = pm.resolveActivity(new Intent(ACTION_PLUGIN_SETTINGS)
+                    .setPackage(mComponent.getPackageName()), 0) != null;
+            setTitle(info.serviceInfo.loadLabel(pm));
+            setChecked(pm.getComponentEnabledSetting(mComponent)
+                    != PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
+            setWidgetLayoutResource(R.layout.tuner_widget_settings_switch);
+        }
+
+        @Override
+        protected boolean persistBoolean(boolean value) {
+            getContext().getPackageManager().setComponentEnabledSetting(mComponent,
+                    value ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+                            : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                    PackageManager.DONT_KILL_APP);
+            return true;
+        }
+
+        @Override
+        public void onBindViewHolder(PreferenceViewHolder holder) {
+            super.onBindViewHolder(holder);
+            holder.findViewById(R.id.settings).setVisibility(mHasSettings ? View.VISIBLE
+                    : View.GONE);
+            holder.findViewById(R.id.divider).setVisibility(mHasSettings ? View.VISIBLE
+                    : View.GONE);
+            holder.findViewById(R.id.settings).setOnClickListener(v -> {
+                ResolveInfo result = v.getContext().getPackageManager().resolveActivity(
+                        new Intent(ACTION_PLUGIN_SETTINGS).setPackage(
+                                mComponent.getPackageName()), 0);
+                if (result != null) {
+                    v.getContext().startActivity(new Intent().setComponent(
+                            new ComponentName(result.activityInfo.packageName,
+                                    result.activityInfo.name)));
+                }
+            });
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 70f2fdc..7f63418 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -19,16 +19,9 @@
 import android.app.Dialog;
 import android.app.DialogFragment;
 import android.content.DialogInterface;
-import android.database.ContentObserver;
-import android.net.Uri;
 import android.os.Bundle;
-import android.os.Handler;
 import android.provider.Settings;
-import android.provider.Settings.System;
 import android.support.v14.preference.PreferenceFragment;
-import android.support.v14.preference.SwitchPreference;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.Preference.OnPreferenceChangeListener;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
@@ -36,12 +29,14 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
+import com.android.systemui.plugins.PluginPrefs;
 
 public class TunerFragment extends PreferenceFragment {
 
     private static final String TAG = "TunerFragment";
 
     private static final String KEY_BATTERY_PCT = "battery_pct";
+    private static final String KEY_PLUGINS = "plugins";
 
     public static final String SETTING_SEEN_TUNER_WARNING = "seen_tuner_warning";
 
@@ -65,6 +60,9 @@
     @Override
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         addPreferencesFromResource(R.xml.tuner_prefs);
+        if (!PluginPrefs.hasPlugins(getContext())) {
+            getPreferenceScreen().removePreference(findPreference(KEY_PLUGINS));
+        }
 
         if (Settings.Secure.getInt(getContext().getContentResolver(), SETTING_SEEN_TUNER_WARNING,
                 0) == 0) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconListTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconListTest.java
new file mode 100644
index 0000000..2792d8c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconListTest.java
@@ -0,0 +1,85 @@
+package com.android.systemui.statusbar;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+
+import static org.mockito.Mockito.mock;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.phone.StatusBarIconList;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class StatusBarIconListTest extends SysuiTestCase {
+
+    private final static String[] STATUS_BAR_SLOTS = {"aaa", "bbb", "ccc"};
+
+    @Test
+    public void testGetExistingSlot() {
+        StatusBarIconList statusBarIconList = new StatusBarIconList(STATUS_BAR_SLOTS);
+        assertEquals(1, statusBarIconList.getSlotIndex("bbb"));
+        assertEquals(2, statusBarIconList.getSlotIndex("ccc"));
+    }
+
+    @Test
+    public void testGetNonexistingSlot() {
+        StatusBarIconList statusBarIconList = new StatusBarIconList(STATUS_BAR_SLOTS);
+        assertEquals(0, statusBarIconList.getSlotIndex("aaa"));
+        assertEquals(3, statusBarIconList.size());
+        assertEquals(0, statusBarIconList.getSlotIndex("zzz")); // new content added in front
+        assertEquals(1, statusBarIconList.getSlotIndex("aaa")); // slid back
+        assertEquals(4, statusBarIconList.size());
+    }
+
+    @Test
+    public void testAddSlotSlidesIcons() {
+        StatusBarIconList statusBarIconList = new StatusBarIconList(STATUS_BAR_SLOTS);
+        StatusBarIcon sbIcon = mock(StatusBarIcon.class);
+        statusBarIconList.setIcon(0, sbIcon);
+        statusBarIconList.getSlotIndex("zzz"); // new content added in front
+        assertNull(statusBarIconList.getIcon(0));
+        assertEquals(sbIcon, statusBarIconList.getIcon(1));
+    }
+
+    @Test
+    public void testGetAndSetIcon() {
+        StatusBarIconList statusBarIconList = new StatusBarIconList(STATUS_BAR_SLOTS);
+        StatusBarIcon sbIconA = mock(StatusBarIcon.class);
+        StatusBarIcon sbIconB = mock(StatusBarIcon.class);
+        statusBarIconList.setIcon(0, sbIconA);
+        statusBarIconList.setIcon(1, sbIconB);
+        assertEquals(sbIconA, statusBarIconList.getIcon(0));
+        assertEquals(sbIconB, statusBarIconList.getIcon(1));
+        assertNull(statusBarIconList.getIcon(2)); // icon not set
+    }
+
+    @Test
+    public void testRemoveIcon() {
+        StatusBarIconList statusBarIconList = new StatusBarIconList(STATUS_BAR_SLOTS);
+        StatusBarIcon sbIconA = mock(StatusBarIcon.class);
+        StatusBarIcon sbIconB = mock(StatusBarIcon.class);
+        statusBarIconList.setIcon(0, sbIconA);
+        statusBarIconList.setIcon(1, sbIconB);
+        statusBarIconList.removeIcon(0);
+        assertNull(statusBarIconList.getIcon(0)); // icon not set
+    }
+
+    @Test
+    public void testGetViewIndex() {
+        StatusBarIconList statusBarIconList = new StatusBarIconList(STATUS_BAR_SLOTS);
+        StatusBarIcon sbIcon = mock(StatusBarIcon.class);
+        statusBarIconList.setIcon(2, sbIcon);
+        assertEquals(0, statusBarIconList.getViewIndex(2)); // Icon for item 2 is 0th child view.
+        statusBarIconList.setIcon(0, sbIcon);
+        assertEquals(0, statusBarIconList.getViewIndex(0)); // Icon for item 0 is 0th child view,
+        assertEquals(1, statusBarIconList.getViewIndex(2)); // and item 2 is now 1st child view.
+    }
+
+}
\ No newline at end of file
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index b953302..da041da 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2557,6 +2557,14 @@
 
     // OPEN: Settings > Wifi > Write config to NFC dialog
     DIALOG_WIFI_WRITE_NFC = 606;
+    // OPEN: Settings > Date > Date picker dialog
+    DIALOG_DATE_PICKER = 607;
+
+    // OPEN: Settings > Date > Time picker dialog
+    DIALOG_TIME_PICKER = 608;
+
+    // OPEN: Settings > Wireless > Manage wireless plan dialog
+    DIALOG_MANAGE_MOBILE_PLAN = 609;
 
     // ---- End O Constants, all O constants go above this line ----
 
diff --git a/services/core/Android.mk b/services/core/Android.mk
index a5b1069..58f2074 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -8,6 +8,7 @@
 
 LOCAL_SRC_FILES += \
     $(call all-java-files-under,java) \
+    $(call all-proto-files-under, proto) \
     java/com/android/server/EventLogTags.logtags \
     java/com/android/server/am/EventLogTags.logtags \
     ../../../../system/netd/server/binder/android/net/INetd.aidl \
@@ -18,6 +19,7 @@
 
 LOCAL_JAVA_LIBRARIES := services.net telephony-common
 LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update
+LOCAL_PROTOC_OPTIMIZE_TYPE := nano
 
 ifneq ($(INCREMENTAL_BUILDS),)
     LOCAL_PROGUARD_ENABLED := disabled
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 4caeba8..7c2eea3f 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -51,6 +51,7 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
+import android.os.ShellCallback;
 import android.os.ShellCommand;
 import android.os.UserHandle;
 import android.os.storage.MountServiceInternal;
@@ -1787,8 +1788,9 @@
     }
 
     @Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
-            FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
-        (new Shell(this, this)).exec(this, in, out, err, args, resultReceiver);
+            FileDescriptor err, String[] args, ShellCallback callback,
+            ResultReceiver resultReceiver) {
+        (new Shell(this, this)).exec(this, in, out, err, args, callback, resultReceiver);
     }
 
     static void dumpCommandHelp(PrintWriter pw) {
@@ -2277,6 +2279,16 @@
                 ClientRestrictionState opRestrictions = mOpUserRestrictions.valueAt(i);
                 opRestrictions.removeUser(userHandle);
             }
+            removeUidsForUserLocked(userHandle);
+        }
+    }
+
+    private void removeUidsForUserLocked(int userHandle) {
+        for (int i = mUidStates.size() - 1; i >= 0; --i) {
+            final int uid = mUidStates.keyAt(i);
+            if (UserHandle.getUserId(uid) == userHandle) {
+                mUidStates.removeAt(i);
+            }
         }
     }
 
@@ -2396,6 +2408,12 @@
                     perUserExcludedPackages = null;
                 }
             }
+            if (perUserRestrictions != null) {
+                perUserRestrictions.remove(userId);
+                if (perUserRestrictions.size() <= 0) {
+                    perUserRestrictions = null;
+                }
+            }
         }
 
         public boolean isDefault() {
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 6b51721..d2cfb6d 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -20,6 +20,7 @@
 import android.os.BatteryStats;
 
 import android.os.ResultReceiver;
+import android.os.ShellCallback;
 import android.os.ShellCommand;
 import com.android.internal.app.IBatteryStats;
 import com.android.server.am.BatteryStatsService;
@@ -789,7 +790,7 @@
                 pw.println("  technology: " + mBatteryProps.batteryTechnology);
             } else {
                 Shell shell = new Shell();
-                shell.exec(mBinderService, null, fd, null, args, new ResultReceiver(null));
+                shell.exec(mBinderService, null, fd, null, args, null, new ResultReceiver(null));
             }
         }
     }
@@ -875,8 +876,9 @@
         }
 
         @Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
-                FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
-            (new Shell()).exec(this, in, out, err, args, resultReceiver);
+                FileDescriptor err, String[] args, ShellCallback callback,
+                ResultReceiver resultReceiver) {
+            (new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
         }
     }
 
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index d1a1bd4..3ad71ea 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -771,6 +771,7 @@
             if (mUnbinding) return;
             mUnbinding = true;
             mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
+            mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE);
             if (mBluetooth != null) {
                 //Unregister callback object
                 try {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 0100bff..fa2f6ac 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -816,7 +816,7 @@
         mTestMode = SystemProperties.get("cm.test.mode").equals("true")
                 && SystemProperties.get("ro.build.type").equals("eng");
 
-        mTethering = new Tethering(mContext, mNetd, statsService);
+        mTethering = new Tethering(mContext, mNetd, statsService, mPolicyManager);
 
         mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
 
@@ -3049,12 +3049,6 @@
         ConnectivityManager.enforceTetherChangePermission(mContext);
         if (isTetheringSupported()) {
             final int status = mTethering.tether(iface);
-            if (status == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
-                try {
-                    mPolicyManager.onTetheringChanged(iface, true);
-                } catch (RemoteException e) {
-                }
-            }
             return status;
         } else {
             return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
@@ -3068,12 +3062,6 @@
 
         if (isTetheringSupported()) {
             final int status = mTethering.untether(iface);
-            if (status == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
-                try {
-                    mPolicyManager.onTetheringChanged(iface, false);
-                } catch (RemoteException e) {
-                }
-            }
             return status;
         } else {
             return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
@@ -4343,8 +4331,17 @@
             enforceAccessPermission();
         }
 
-        NetworkRequest networkRequest = new NetworkRequest(
-                new NetworkCapabilities(networkCapabilities), TYPE_NONE, nextNetworkRequestId(),
+        NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
+        if (!ConnectivityManager.checkChangePermission(mContext)) {
+            // Apps without the CHANGE_NETWORK_STATE permission can't use background networks, so
+            // make all their listens include NET_CAPABILITY_FOREGROUND. That way, they will get
+            // onLost and onAvailable callbacks when networks move in and out of the background.
+            // There is no need to do this for requests because an app without CHANGE_NETWORK_STATE
+            // can't request networks.
+            nc.addCapability(NET_CAPABILITY_FOREGROUND);
+        }
+
+        NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
                 NetworkRequest.Type.LISTEN);
         NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder);
         if (VDBG) log("listenForNetwork for " + nri);
@@ -4659,6 +4656,17 @@
         mNumDnsEntries = last;
     }
 
+    private String getNetworkPermission(NetworkCapabilities nc) {
+        // TODO: make these permission strings AIDL constants instead.
+        if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
+            return NetworkManagementService.PERMISSION_SYSTEM;
+        }
+        if (!nc.hasCapability(NET_CAPABILITY_FOREGROUND)) {
+            return NetworkManagementService.PERMISSION_NETWORK;
+        }
+        return null;
+    }
+
     /**
      * Update the NetworkCapabilities for {@code networkAgent} to {@code networkCapabilities}
      * augmented with any stateful capabilities implied from {@code networkAgent}
@@ -4697,12 +4705,11 @@
 
         if (Objects.equals(nai.networkCapabilities, networkCapabilities)) return;
 
-        if (nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) !=
-                networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
+        final String oldPermission = getNetworkPermission(nai.networkCapabilities);
+        final String newPermission = getNetworkPermission(networkCapabilities);
+        if (!Objects.equals(oldPermission, newPermission) && nai.created && !nai.isVPN()) {
             try {
-                mNetd.setNetworkPermission(nai.network.netId,
-                        networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) ?
-                                null : NetworkManagementService.PERMISSION_SYSTEM);
+                mNetd.setNetworkPermission(nai.network.netId, newPermission);
             } catch (RemoteException e) {
                 loge("Exception in setNetworkPermission: " + e);
             }
@@ -5272,9 +5279,7 @@
                                 !networkAgent.networkMisc.allowBypass));
                 } else {
                     mNetd.createPhysicalNetwork(networkAgent.network.netId,
-                            networkAgent.networkCapabilities.hasCapability(
-                                    NET_CAPABILITY_NOT_RESTRICTED) ?
-                                    null : NetworkManagementService.PERMISSION_SYSTEM);
+                            getNetworkPermission(networkAgent.networkCapabilities));
                 }
             } catch (Exception e) {
                 loge("Error creating network " + networkAgent.network.netId + ": "
@@ -5497,7 +5502,7 @@
 
     @Override
     public String getCaptivePortalServerUrl() {
-        return NetworkMonitor.getCaptivePortalServerUrl(mContext);
+        return NetworkMonitor.getCaptivePortalServerHttpUrl(mContext);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 6b73fec..dbc1f31 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -60,6 +60,7 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
+import android.os.ShellCallback;
 import android.os.ShellCommand;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -1232,8 +1233,8 @@
         }
 
         @Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
-                FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
-            (new Shell()).exec(this, in, out, err, args, resultReceiver);
+                FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
+            (new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
         }
     }
 
@@ -2838,7 +2839,8 @@
                     shell.userId = userId;
                     String[] newArgs = new String[args.length-i];
                     System.arraycopy(args, i, newArgs, 0, args.length-i);
-                    shell.exec(mBinderService, null, fd, null, newArgs, new ResultReceiver(null));
+                    shell.exec(mBinderService, null, fd, null, newArgs, null,
+                            new ResultReceiver(null));
                     return;
                 }
             }
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 35ddc9b..575018d 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -26,7 +26,6 @@
 import android.accounts.AuthenticatorDescription;
 import android.accounts.CantAddAccountActivity;
 import android.accounts.GrantCredentialsPermissionActivity;
-import android.accounts.IAccountAccessTracker;
 import android.accounts.IAccountAuthenticator;
 import android.accounts.IAccountAuthenticatorResponse;
 import android.accounts.IAccountManager;
@@ -78,14 +77,12 @@
 import android.os.Process;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.StorageManager;
 import android.text.TextUtils;
 import android.util.Log;
-import android.util.PackageUtils;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -125,7 +122,9 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
 import java.util.Set;
+import java.util.UUID;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
@@ -152,7 +151,7 @@
 
         @Override
         public void onStart() {
-            mService = new AccountManagerService(getContext());
+            mService = new AccountManagerService(new Injector(getContext()));
             publishBinderService(Context.ACCOUNT_SERVICE, mService);
         }
 
@@ -169,6 +168,7 @@
     private final PackageManager mPackageManager;
     private final AppOpsManager mAppOpsManager;
     private UserManager mUserManager;
+    private final Injector mInjector;
 
     final MessageHandler mHandler;
 
@@ -272,22 +272,13 @@
         return sThis.get();
     }
 
-    public AccountManagerService(Context context) {
-        this(context, context.getPackageManager(), new AccountAuthenticatorCache(context));
-    }
-
-    public AccountManagerService(Context context, PackageManager packageManager,
-            IAccountAuthenticatorCache authenticatorCache) {
-        mContext = context;
-        mPackageManager = packageManager;
+    public AccountManagerService(Injector injector) {
+        mInjector = injector;
+        mContext = injector.getContext();
+        mPackageManager = mContext.getPackageManager();
         mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
-
-        ServiceThread serviceThread = new ServiceThread(TAG,
-                android.os.Process.THREAD_PRIORITY_FOREGROUND, true /* allowIo */);
-        serviceThread.start();
-        mHandler = new MessageHandler(serviceThread.getLooper());
-
-        mAuthenticatorCache = authenticatorCache;
+        mHandler = new MessageHandler(injector.getMessageHandlerLooper());
+        mAuthenticatorCache = mInjector.getAccountAuthenticatorCache();
         mAuthenticatorCache.setListener(this, null /* Handler */);
 
         sThis.set(this);
@@ -373,7 +364,7 @@
             }
         }, UserHandle.ALL, userFilter, null, null);
 
-        LocalServices.addService(AccountManagerInternal.class, new AccountManagerInternalImpl());
+        injector.addLocalService(new AccountManagerInternalImpl());
 
         // Need to cancel account request notifications if the update/install can access the account
         new PackageMonitor() {
@@ -424,7 +415,7 @@
                 final long identity = Binder.clearCallingIdentity();
                 try {
                     for (String packageName : packageNames) {
-                        if (mContext.getPackageManager().checkPermission(
+                        if (mPackageManager.checkPermission(
                                 Manifest.permission.GET_ACCOUNTS, packageName)
                                         != PackageManager.PERMISSION_GRANTED) {
                             continue;
@@ -710,8 +701,7 @@
      * installed on the device.
      */
     private void addRequestsForPreInstalledApplications() {
-        List<PackageInfo> allInstalledPackages = mContext.getPackageManager().
-                getInstalledPackages(0);
+        List<PackageInfo> allInstalledPackages = mPackageManager.getInstalledPackages(0);
         for(PackageInfo pi : allInstalledPackages) {
             int currentUid = pi.applicationInfo.uid;
             if(currentUid != -1) {
@@ -1115,7 +1105,7 @@
                     final Account[] accountsForType = new Account[accountNames.size()];
                     for (int i = 0; i < accountsForType.length; i++) {
                         accountsForType[i] = new Account(accountNames.get(i), accountType,
-                                new AccountAccessTracker());
+                                UUID.randomUUID().toString());
                     }
                     accounts.accountCache.put(accountType, accountsForType);
                 }
@@ -1170,8 +1160,8 @@
             UserAccounts accounts = mUsers.get(userId);
             boolean validateAccounts = false;
             if (accounts == null) {
-                File preNDbFile = new File(getPreNDatabaseName(userId));
-                File deDbFile = new File(getDeDatabaseName(userId));
+                File preNDbFile = new File(mInjector.getPreNDatabaseName(userId));
+                File deDbFile = new File(mInjector.getDeDatabaseName(userId));
                 accounts = new UserAccounts(mContext, userId, preNDbFile, deDbFile);
                 initializeDebugDbSizeAndCompileSqlStatementForLogging(
                         accounts.openHelper.getWritableDatabase(), accounts);
@@ -1183,8 +1173,8 @@
             if (!accounts.openHelper.isCeDatabaseAttached() && mLocalUnlockedUsers.get(userId)) {
                 Log.i(TAG, "User " + userId + " is unlocked - opening CE database");
                 synchronized (accounts.cacheLock) {
-                    File preNDatabaseFile = new File(getPreNDatabaseName(userId));
-                    File ceDatabaseFile = new File(getCeDatabaseName(userId));
+                    File preNDatabaseFile = new File(mInjector.getPreNDatabaseName(userId));
+                    File ceDatabaseFile = new File(mInjector.getCeDatabaseName(userId));
                     CeDatabaseHelper.create(mContext, userId, preNDatabaseFile, ceDatabaseFile);
                     accounts.openHelper.attachCeDatabase(ceDatabaseFile);
                 }
@@ -1255,13 +1245,13 @@
             }
         }
         Log.i(TAG, "Removing database files for user " + userId);
-        File dbFile = new File(getDeDatabaseName(userId));
+        File dbFile = new File(mInjector.getDeDatabaseName(userId));
 
         AccountsDb.deleteDbFileWarnIfFailed(dbFile);
         // Remove CE file if user is unlocked, or FBE is not enabled
         boolean fbeEnabled = StorageManager.isFileEncryptedNativeOrEmulated();
         if (!fbeEnabled || userUnlocked) {
-            File ceDb = new File(getCeDatabaseName(userId));
+            File ceDb = new File(mInjector.getCeDatabaseName(userId));
             if (ceDb.exists()) {
                 AccountsDb.deleteDbFileWarnIfFailed(ceDb);
             }
@@ -1865,8 +1855,8 @@
             Bundle result = new Bundle();
             result.putString(AccountManager.KEY_ACCOUNT_NAME, resultingAccount.name);
             result.putString(AccountManager.KEY_ACCOUNT_TYPE, resultingAccount.type);
-            result.putBinder(AccountManager.KEY_ACCOUNT_ACCESS_TRACKER,
-                    resultingAccount.getAccessTracker().asBinder());
+            result.putString(AccountManager.KEY_ACCOUNT_ACCESS_ID,
+                    resultingAccount.getAccessId());
             try {
                 response.onResult(result);
             } catch (RemoteException e) {
@@ -1918,7 +1908,7 @@
              * Database transaction was successful. Clean up cached
              * data associated with the account in the user profile.
              */
-            insertAccountIntoCacheLocked(accounts, renamedAccount);
+            renamedAccount = insertAccountIntoCacheLocked(accounts, renamedAccount);
             /*
              * Extract the data and token caches before removing the
              * old account to preserve the user data associated with
@@ -4330,6 +4320,30 @@
         }
     }
 
+    @Override
+    public void onAccountAccessed(String token) throws RemoteException {
+        final int uid = Binder.getCallingUid();
+        if (UserHandle.getAppId(uid) == Process.SYSTEM_UID) {
+            return;
+        }
+        final int userId = UserHandle.getCallingUserId();
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            for (Account account : getAccounts(userId, mContext.getOpPackageName())) {
+                if (Objects.equals(account.getAccessId(), token)) {
+                    // An app just accessed the account. At this point it knows about
+                    // it and there is not need to hide this account from the app.
+                    if (!hasAccountAccess(account, null, uid)) {
+                        updateAppPermission(account, AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE,
+                                uid, true);
+                    }
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
     private abstract class Session extends IAccountAuthenticatorResponse.Stub
             implements IBinder.DeathRecipient, ServiceConnection {
         IAccountManagerResponse mResponse;
@@ -4721,47 +4735,6 @@
         }
     }
 
-    @VisibleForTesting
-    String getPreNDatabaseName(int userId) {
-        File systemDir = Environment.getDataSystemDirectory();
-        File databaseFile = new File(Environment.getUserSystemDirectory(userId),
-                PRE_N_DATABASE_NAME);
-        if (userId == 0) {
-            // Migrate old file, if it exists, to the new location.
-            // Make sure the new file doesn't already exist. A dummy file could have been
-            // accidentally created in the old location, causing the new one to become corrupted
-            // as well.
-            File oldFile = new File(systemDir, PRE_N_DATABASE_NAME);
-            if (oldFile.exists() && !databaseFile.exists()) {
-                // Check for use directory; create if it doesn't exist, else renameTo will fail
-                File userDir = Environment.getUserSystemDirectory(userId);
-                if (!userDir.exists()) {
-                    if (!userDir.mkdirs()) {
-                        throw new IllegalStateException("User dir cannot be created: " + userDir);
-                    }
-                }
-                if (!oldFile.renameTo(databaseFile)) {
-                    throw new IllegalStateException("User dir cannot be migrated: " + databaseFile);
-                }
-            }
-        }
-        return databaseFile.getPath();
-    }
-
-    @VisibleForTesting
-    String getDeDatabaseName(int userId) {
-        File databaseFile = new File(Environment.getDataSystemDeDirectory(userId),
-                AccountsDb.DE_DATABASE_NAME);
-        return databaseFile.getPath();
-    }
-
-    @VisibleForTesting
-    String getCeDatabaseName(int userId) {
-        File databaseFile = new File(Environment.getDataSystemCeDirectory(userId),
-                AccountsDb.CE_DATABASE_NAME);
-        return databaseFile.getPath();
-    }
-
     private void logRecord(UserAccounts accounts, String action, String tableName) {
         logRecord(action, tableName, -1, accounts);
     }
@@ -4957,17 +4930,11 @@
         }
     }
 
-    @VisibleForTesting
-    protected void installNotification(int notificationId, final Notification notification,
-            UserHandle user) {
-        installNotification(notificationId, notification, "android", user.getIdentifier());
-    }
-
     private void installNotification(int notificationId, final Notification notification,
             String packageName, int userId) {
         final long token = clearCallingIdentity();
         try {
-            INotificationManager notificationManager = NotificationManager.getService();
+            INotificationManager notificationManager = mInjector.getNotificationManager();
             try {
                 notificationManager.enqueueNotificationWithTag(packageName, packageName, null,
                         notificationId, notification, new int[1], userId);
@@ -4979,16 +4946,14 @@
         }
     }
 
-    @VisibleForTesting
-    protected void cancelNotification(int id, UserHandle user) {
+    private void cancelNotification(int id, UserHandle user) {
         cancelNotification(id, mContext.getPackageName(), user);
     }
 
-    protected void cancelNotification(int id, String packageName, UserHandle user) {
+    private void cancelNotification(int id, String packageName, UserHandle user) {
         long identityToken = clearCallingIdentity();
         try {
-            INotificationManager service = INotificationManager.Stub.asInterface(
-                    ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+            INotificationManager service = mInjector.getNotificationManager();
             service.cancelNotificationWithTag(packageName, null, id, user.getIdentifier());
         } catch (RemoteException e) {
             /* ignore - local call */
@@ -5400,9 +5365,9 @@
         if (accountsForType != null) {
             System.arraycopy(accountsForType, 0, newAccountsForType, 0, oldLength);
         }
-        IAccountAccessTracker accessTracker = account.getAccessTracker() != null
-                ? account.getAccessTracker() : new AccountAccessTracker();
-        newAccountsForType[oldLength] = new Account(account, accessTracker);
+        String token = account.getAccessId() != null ? account.getAccessId()
+                : UUID.randomUUID().toString();
+        newAccountsForType[oldLength] = new Account(account, token);
         accounts.accountCache.put(account.type, newAccountsForType);
         return newAccountsForType[oldLength];
     }
@@ -5607,33 +5572,6 @@
         }
     }
 
-    private final class AccountAccessTracker extends IAccountAccessTracker.Stub {
-        @Override
-        public void onAccountAccessed() throws RemoteException {
-            final int uid = Binder.getCallingUid();
-            if (UserHandle.getAppId(uid) == Process.SYSTEM_UID) {
-                return;
-            }
-            final int userId = UserHandle.getCallingUserId();
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                for (Account account : getAccounts(userId, mContext.getOpPackageName())) {
-                    IAccountAccessTracker accountTracker = account.getAccessTracker();
-                    if (accountTracker != null && asBinder() == accountTracker.asBinder()) {
-                        // An app just accessed the account. At this point it knows about
-                        // it and there is not need to hide this account from the app.
-                        if (!hasAccountAccess(account, null, uid)) {
-                            updateAppPermission(account, AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE,
-                                    uid, true);
-                        }
-                    }
-                }
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-        }
-    }
-
     private final class AccountManagerInternalImpl extends AccountManagerInternal {
         private final Object mLock = new Object();
 
@@ -5717,4 +5655,74 @@
             }
         }
     }
+
+    @VisibleForTesting
+    static class Injector {
+        private final Context mContext;
+
+        public Injector(Context context) {
+            mContext = context;
+        }
+
+        Looper getMessageHandlerLooper() {
+            ServiceThread serviceThread = new ServiceThread(TAG,
+                    android.os.Process.THREAD_PRIORITY_FOREGROUND, true /* allowIo */);
+            serviceThread.start();
+            return serviceThread.getLooper();
+        }
+
+        Context getContext() {
+            return mContext;
+        }
+
+        void addLocalService(AccountManagerInternal service) {
+            LocalServices.addService(AccountManagerInternal.class, service);
+        }
+
+        String getDeDatabaseName(int userId) {
+            File databaseFile = new File(Environment.getDataSystemDeDirectory(userId),
+                    AccountsDb.DE_DATABASE_NAME);
+            return databaseFile.getPath();
+        }
+
+        String getCeDatabaseName(int userId) {
+            File databaseFile = new File(Environment.getDataSystemCeDirectory(userId),
+                    AccountsDb.CE_DATABASE_NAME);
+            return databaseFile.getPath();
+        }
+
+        String getPreNDatabaseName(int userId) {
+            File systemDir = Environment.getDataSystemDirectory();
+            File databaseFile = new File(Environment.getUserSystemDirectory(userId),
+                    PRE_N_DATABASE_NAME);
+            if (userId == 0) {
+                // Migrate old file, if it exists, to the new location.
+                // Make sure the new file doesn't already exist. A dummy file could have been
+                // accidentally created in the old location, causing the new one to become corrupted
+                // as well.
+                File oldFile = new File(systemDir, PRE_N_DATABASE_NAME);
+                if (oldFile.exists() && !databaseFile.exists()) {
+                    // Check for use directory; create if it doesn't exist, else renameTo will fail
+                    File userDir = Environment.getUserSystemDirectory(userId);
+                    if (!userDir.exists()) {
+                        if (!userDir.mkdirs()) {
+                            throw new IllegalStateException("User dir cannot be created: " + userDir);
+                        }
+                    }
+                    if (!oldFile.renameTo(databaseFile)) {
+                        throw new IllegalStateException("User dir cannot be migrated: " + databaseFile);
+                    }
+                }
+            }
+            return databaseFile.getPath();
+        }
+
+        IAccountAuthenticatorCache getAccountAuthenticatorCache() {
+            return new AccountAuthenticatorCache(mContext);
+        }
+
+        INotificationManager getNotificationManager() {
+            return NotificationManager.getService();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f9db14f..d4396a4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -182,6 +182,7 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
+import android.os.ShellCallback;
 import android.os.StrictMode;
 import android.os.SystemClock;
 import android.os.SystemProperties;
@@ -1526,6 +1527,7 @@
     static final int VR_MODE_APPLY_IF_NEEDED_MSG = 69;
     static final int SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG = 70;
     static final int HANDLE_TRUST_STORAGE_UPDATE_MSG = 71;
+    static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 72;
     static final int START_USER_SWITCH_FG_MSG = 712;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
@@ -2274,6 +2276,9 @@
             case REPORT_USER_SWITCH_COMPLETE_MSG: {
                 mUserController.dispatchUserSwitchComplete(msg.arg1);
             } break;
+            case REPORT_LOCKED_BOOT_COMPLETE_MSG: {
+                mUserController.dispatchLockedBootComplete(msg.arg1);
+            } break;
             case SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG: {
                 IUiAutomationConnection connection = (IUiAutomationConnection) msg.obj;
                 try {
@@ -4068,25 +4073,29 @@
     }
 
     @Override
-    public boolean setProcessMemoryTrimLevel(String process, int userId, int level) {
+    public boolean setProcessMemoryTrimLevel(String process, int userId, int level)
+            throws RemoteException {
         synchronized (this) {
             final ProcessRecord app = findProcessLocked(process, userId, "setProcessMemoryTrimLevel");
             if (app == null) {
-                return false;
+                throw new IllegalArgumentException("Unknown process: " + process);
             }
-            if (app.trimMemoryLevel < level && app.thread != null &&
-                    (level < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN ||
-                            app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND)) {
-                try {
-                    app.thread.scheduleTrimMemory(level);
-                    app.trimMemoryLevel = level;
-                    return true;
-                } catch (RemoteException e) {
-                    // Fallthrough to failure case.
-                }
+            if (app.thread == null) {
+                throw new IllegalArgumentException("Process has no app thread");
             }
+            if (app.trimMemoryLevel >= level) {
+                throw new IllegalArgumentException(
+                        "Unable to set a higher trim level than current level");
+            }
+            if (!(level < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN ||
+                    app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND)) {
+                throw new IllegalArgumentException("Unable to set a background trim level "
+                    + "on a foreground process");
+            }
+            app.thread.scheduleTrimMemory(level);
+            app.trimMemoryLevel = level;
+            return true;
         }
-        return false;
     }
 
     private void dispatchProcessesChanged() {
@@ -6118,6 +6127,8 @@
                 ProcessList.INVALID_ADJ, callerWillRestart, true, doit, evenPersistent,
                 packageName == null ? ("stop user " + userId) : ("stop " + packageName));
 
+        didSomething |= mActivityStarter.clearPendingActivityLaunchesLocked(packageName);
+
         if (mStackSupervisor.finishDisabledPackageActivitiesLocked(
                 packageName, null, doit, evenPersistent, userId)) {
             if (!doit) {
@@ -6450,6 +6461,8 @@
         app.debugging = false;
         app.cached = false;
         app.killedByAm = false;
+        app.killed = false;
+
 
         // We carefully use the same state that PackageManager uses for
         // filtering, since we use this flag to decide if we need to install
@@ -11462,6 +11475,7 @@
                 && userId == UserHandle.USER_SYSTEM
                 && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
             r.persistent = true;
+            r.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
         }
         addProcessNameLocked(r);
         return r;
@@ -12046,27 +12060,29 @@
     }
 
     public void requestBugReport(int bugreportType) {
-        String service = null;
+        String extraOptions = null;
         switch (bugreportType) {
             case ActivityManager.BUGREPORT_OPTION_FULL:
-                service = "bugreport";
+                // Default options.
                 break;
             case ActivityManager.BUGREPORT_OPTION_INTERACTIVE:
-                service = "bugreportplus";
+                extraOptions = "bugreportplus";
                 break;
             case ActivityManager.BUGREPORT_OPTION_REMOTE:
-                service = "bugreportremote";
+                extraOptions = "bugreportremote";
                 break;
             case ActivityManager.BUGREPORT_OPTION_WEAR:
-                service = "bugreportwear";
+                extraOptions = "bugreportwear";
                 break;
-        }
-        if (service == null) {
-            throw new IllegalArgumentException("Provided bugreport type is not correct, value: "
-                    + bugreportType);
+            default:
+                throw new IllegalArgumentException("Provided bugreport type is not correct, value: "
+                        + bugreportType);
         }
         enforceCallingPermission(android.Manifest.permission.DUMP, "requestBugReport");
-        SystemProperties.set("ctl.start", service);
+        if (extraOptions != null) {
+            SystemProperties.set("dumpstate.options", extraOptions);
+        }
+        SystemProperties.set("ctl.start", "bugreport");
     }
 
     public static long getInputDispatchingTimeoutLocked(ActivityRecord r) {
@@ -14011,9 +14027,10 @@
 
     @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out,
-            FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
+            FileDescriptor err, String[] args, ShellCallback callback,
+            ResultReceiver resultReceiver) {
         (new ActivityManagerShellCommand(this, false)).exec(
-                this, in, out, err, args, resultReceiver);
+                this, in, out, err, args, callback, resultReceiver);
     }
 
     @Override
@@ -14236,7 +14253,8 @@
                 // Dumping a single activity?
                 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll, dumpVisibleStacks)) {
                     ActivityManagerShellCommand shell = new ActivityManagerShellCommand(this, true);
-                    int res = shell.exec(this, null, fd, null, args, new ResultReceiver(null));
+                    int res = shell.exec(this, null, fd, null, args, null,
+                            new ResultReceiver(null));
                     if (res < 0) {
                         pw.println("Bad activity command, or no activities match: " + cmd);
                         pw.println("Use -h for help.");
@@ -19028,7 +19046,7 @@
         if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) {
             intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
             intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-            if (!mProcessesReady) {
+            if (initLocale || !mProcessesReady) {
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
             }
             broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
@@ -20666,8 +20684,11 @@
             final long now = SystemClock.elapsedRealtime();
             Long lastReported = userState.mProviderLastReportedFg.get(authority);
             if (lastReported == null || lastReported < now - 60 * 1000L) {
-                mUsageStatsService.reportContentProviderUsage(
-                        authority, providerPkgName, app.userId);
+                if (mSystemReady) {
+                    // Cannot touch the user stats if not system ready
+                    mUsageStatsService.reportContentProviderUsage(
+                            authority, providerPkgName, app.userId);
+                }
                 userState.mProviderLastReportedFg.put(authority, now);
             }
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index adf6d36..aed9fa4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -17,26 +17,57 @@
 package com.android.server.am;
 
 import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.app.AppGlobals;
 import android.app.IActivityManager;
+import android.app.ProfilerInfo;
+import android.content.Intent;
+import android.content.pm.IPackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ShellCommand;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.DebugUtils;
 
 import java.io.PrintWriter;
+import java.net.URISyntaxException;
+import java.util.List;
+
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 
 class ActivityManagerShellCommand extends ShellCommand {
+    public static final String NO_CLASS_ERROR_CODE = "Error type 3";
+
     // IPC interface to activity manager -- don't need to do additional security checks.
     final IActivityManager mInterface;
 
     // Internal service impl -- must perform security checks before touching.
     final ActivityManagerService mInternal;
 
+    // Convenience for interacting with package manager.
+    final IPackageManager mPm;
+
+    private int mStartFlags = 0;
+    private boolean mWaitOption = false;
+    private boolean mStopOption = false;
+
+    private int mRepeat = 0;
+    private int mUserId;
+    private String mReceiverPermission;
+
+    private String mProfileFile;
+    private int mSamplingInterval;
+    private boolean mAutoStop;
+    private int mStackId;
+
     final boolean mDumping;
 
     ActivityManagerShellCommand(ActivityManagerService service, boolean dumping) {
         mInterface = service;
         mInternal = service;
+        mPm = AppGlobals.getPackageManager();
         mDumping = dumping;
     }
 
@@ -48,6 +79,15 @@
         PrintWriter pw = getOutPrintWriter();
         try {
             switch (cmd) {
+                case "start":
+                case "start-activity":
+                    return runStartActivity(pw);
+                case "startservice":
+                case "start-service":
+                    return 1; //runStartService(pw);
+                case "stopservice":
+                case "stop-service":
+                    return 1; //runStopService(pw);
                 case "force-stop":
                     return runForceStop(pw);
                 case "kill":
@@ -75,6 +115,241 @@
         return -1;
     }
 
+    private Intent makeIntent(int defUser) throws URISyntaxException {
+        mStartFlags = 0;
+        mWaitOption = false;
+        mStopOption = false;
+        mRepeat = 0;
+        mProfileFile = null;
+        mSamplingInterval = 0;
+        mAutoStop = false;
+        mUserId = defUser;
+        mStackId = INVALID_STACK_ID;
+
+        return Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
+            @Override
+            public boolean handleOption(String opt, ShellCommand cmd) {
+                if (opt.equals("-D")) {
+                    mStartFlags |= ActivityManager.START_FLAG_DEBUG;
+                } else if (opt.equals("-N")) {
+                    mStartFlags |= ActivityManager.START_FLAG_NATIVE_DEBUGGING;
+                } else if (opt.equals("-W")) {
+                    mWaitOption = true;
+                } else if (opt.equals("-P")) {
+                    mProfileFile = getNextArgRequired();
+                    mAutoStop = true;
+                } else if (opt.equals("--start-profiler")) {
+                    mProfileFile = getNextArgRequired();
+                    mAutoStop = false;
+                } else if (opt.equals("--sampling")) {
+                    mSamplingInterval = Integer.parseInt(getNextArgRequired());
+                } else if (opt.equals("-R")) {
+                    mRepeat = Integer.parseInt(getNextArgRequired());
+                } else if (opt.equals("-S")) {
+                    mStopOption = true;
+                } else if (opt.equals("--track-allocation")) {
+                    mStartFlags |= ActivityManager.START_FLAG_TRACK_ALLOCATION;
+                } else if (opt.equals("--user")) {
+                    mUserId = UserHandle.parseUserArg(getNextArgRequired());
+                } else if (opt.equals("--receiver-permission")) {
+                    mReceiverPermission = getNextArgRequired();
+                } else if (opt.equals("--stack")) {
+                    mStackId = Integer.parseInt(getNextArgRequired());
+                } else {
+                    return false;
+                }
+                return true;
+            }
+        });
+    }
+
+    ParcelFileDescriptor openOutputFile(String path) {
+        try {
+            ParcelFileDescriptor pfd = getShellCallback().openOutputFile(path,
+                    "u:r:system_server:s0");
+            if (pfd != null) {
+                return pfd;
+            }
+        } catch (RuntimeException e) {
+            getErrPrintWriter().println("Failure opening file: " + e.getMessage());
+        }
+        getErrPrintWriter().println("Error: Unable to open file: " + path);
+        getErrPrintWriter().println("Consider using a file under /data/local/tmp/");
+        return null;
+    }
+
+    int runStartActivity(PrintWriter pw) throws RemoteException {
+        Intent intent;
+        try {
+            intent = makeIntent(UserHandle.USER_CURRENT);
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+
+        if (mUserId == UserHandle.USER_ALL) {
+            getErrPrintWriter().println("Error: Can't start service with user 'all'");
+            return 1;
+        }
+
+        String mimeType = intent.getType();
+        if (mimeType == null && intent.getData() != null
+                && "content".equals(intent.getData().getScheme())) {
+            mimeType = mInterface.getProviderMimeType(intent.getData(), mUserId);
+        }
+
+        do {
+            if (mStopOption) {
+                String packageName;
+                if (intent.getComponent() != null) {
+                    packageName = intent.getComponent().getPackageName();
+                } else {
+                    List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType, 0,
+                            mUserId).getList();
+                    if (activities == null || activities.size() <= 0) {
+                        getErrPrintWriter().println("Error: Intent does not match any activities: "
+                                + intent);
+                        return 1;
+                    } else if (activities.size() > 1) {
+                        getErrPrintWriter().println(
+                                "Error: Intent matches multiple activities; can't stop: "
+                                + intent);
+                        return 1;
+                    }
+                    packageName = activities.get(0).activityInfo.packageName;
+                }
+                pw.println("Stopping: " + packageName);
+                mInterface.forceStopPackage(packageName, mUserId);
+                try {
+                    Thread.sleep(250);
+                } catch (InterruptedException e) {
+                }
+            }
+
+            ProfilerInfo profilerInfo = null;
+
+            if (mProfileFile != null) {
+                ParcelFileDescriptor fd = openOutputFile(mProfileFile);
+                if (fd == null) {
+                    return 1;
+                }
+                profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop);
+            }
+
+            pw.println("Starting: " + intent);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            IActivityManager.WaitResult result = null;
+            int res;
+            final long startTime = SystemClock.uptimeMillis();
+            ActivityOptions options = null;
+            if (mStackId != INVALID_STACK_ID) {
+                options = ActivityOptions.makeBasic();
+                options.setLaunchStackId(mStackId);
+            }
+            if (mWaitOption) {
+                result = mInterface.startActivityAndWait(null, null, intent, mimeType,
+                        null, null, 0, mStartFlags, profilerInfo,
+                        options != null ? options.toBundle() : null, mUserId);
+                res = result.result;
+            } else {
+                res = mInterface.startActivityAsUser(null, null, intent, mimeType,
+                        null, null, 0, mStartFlags, profilerInfo,
+                        options != null ? options.toBundle() : null, mUserId);
+            }
+            final long endTime = SystemClock.uptimeMillis();
+            PrintWriter out = mWaitOption ? pw : getErrPrintWriter();
+            boolean launched = false;
+            switch (res) {
+                case ActivityManager.START_SUCCESS:
+                    launched = true;
+                    break;
+                case ActivityManager.START_SWITCHES_CANCELED:
+                    launched = true;
+                    out.println(
+                            "Warning: Activity not started because the "
+                                    + " current activity is being kept for the user.");
+                    break;
+                case ActivityManager.START_DELIVERED_TO_TOP:
+                    launched = true;
+                    out.println(
+                            "Warning: Activity not started, intent has "
+                                    + "been delivered to currently running "
+                                    + "top-most instance.");
+                    break;
+                case ActivityManager.START_RETURN_INTENT_TO_CALLER:
+                    launched = true;
+                    out.println(
+                            "Warning: Activity not started because intent "
+                                    + "should be handled by the caller");
+                    break;
+                case ActivityManager.START_TASK_TO_FRONT:
+                    launched = true;
+                    out.println(
+                            "Warning: Activity not started, its current "
+                                    + "task has been brought to the front");
+                    break;
+                case ActivityManager.START_INTENT_NOT_RESOLVED:
+                    out.println(
+                            "Error: Activity not started, unable to "
+                                    + "resolve " + intent.toString());
+                    break;
+                case ActivityManager.START_CLASS_NOT_FOUND:
+                    out.println(NO_CLASS_ERROR_CODE);
+                    out.println("Error: Activity class " +
+                            intent.getComponent().toShortString()
+                            + " does not exist.");
+                    break;
+                case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
+                    out.println(
+                            "Error: Activity not started, you requested to "
+                                    + "both forward and receive its result");
+                    break;
+                case ActivityManager.START_PERMISSION_DENIED:
+                    out.println(
+                            "Error: Activity not started, you do not "
+                                    + "have permission to access it.");
+                    break;
+                case ActivityManager.START_NOT_VOICE_COMPATIBLE:
+                    out.println(
+                            "Error: Activity not started, voice control not allowed for: "
+                                    + intent);
+                    break;
+                case ActivityManager.START_NOT_CURRENT_USER_ACTIVITY:
+                    out.println(
+                            "Error: Not allowed to start background user activity"
+                                    + " that shouldn't be displayed for all users.");
+                    break;
+                default:
+                    out.println(
+                            "Error: Activity not started, unknown error code " + res);
+                    break;
+            }
+            if (mWaitOption && launched) {
+                if (result == null) {
+                    result = new IActivityManager.WaitResult();
+                    result.who = intent.getComponent();
+                }
+                pw.println("Status: " + (result.timeout ? "timeout" : "ok"));
+                if (result.who != null) {
+                    pw.println("Activity: " + result.who.flattenToShortString());
+                }
+                if (result.thisTime >= 0) {
+                    pw.println("ThisTime: " + result.thisTime);
+                }
+                if (result.totalTime >= 0) {
+                    pw.println("TotalTime: " + result.totalTime);
+                }
+                pw.println("WaitTime: " + (endTime-startTime));
+                pw.println("Complete");
+            }
+            mRepeat--;
+            if (mRepeat > 0) {
+                mInterface.unhandledBack();
+            }
+        } while (mRepeat > 0);
+        return 0;
+    }
+
     int runIsUserStopped(PrintWriter pw) {
         int userId = UserHandle.parseUserArg(getNextArgRequired());
         boolean stopped = mInternal.isUserStopped(userId);
@@ -223,6 +498,24 @@
             pw.println("Activity manager (activity) commands:");
             pw.println("  help");
             pw.println("    Print this help text.");
+            pw.println("  start-activity [-D] [-N] [-W] [-P <FILE>] [--start-profiler <FILE>]");
+            pw.println("          [--sampling INTERVAL] [-R COUNT] [-S]");
+            pw.println("          [--track-allocation] [--user <USER_ID> | current] <INTENT>");
+            pw.println("    Start an Activity.  Options are:");
+            pw.println("    -D: enable debugging");
+            pw.println("    -N: enable native debugging");
+            pw.println("    -W: wait for launch to complete");
+            pw.println("    --start-profiler <FILE>: start profiler and send results to <FILE>");
+            pw.println("    --sampling INTERVAL: use sample profiling with INTERVAL microseconds");
+            pw.println("        between samples (use with --start-profiler)");
+            pw.println("    -P <FILE>: like above, but profiling stops when app goes idle");
+            pw.println("    -R: repeat the activity launch <COUNT> times.  Prior to each repeat,");
+            pw.println("        the top activity will be finished.");
+            pw.println("    -S: force stop the target app before starting the activity");
+            pw.println("    --track-allocation: enable tracking of object allocations");
+            pw.println("    --user <USER_ID> | current: Specify which user to run as; if not");
+            pw.println("        specified then run as the current user.");
+            pw.println("    --stack <STACK_ID>: Specify into which stack should the activity be put.");
             pw.println("  force-stop [--user <USER_ID> | all | current] <PACKAGE>");
             pw.println("    Completely stop the given application package.");
             pw.println("  kill [--user <USER_ID> | all | current] <PACKAGE>");
@@ -241,6 +534,8 @@
             pw.println("    Optionally controls lenient background check mode, returns current mode.");
             pw.println("  get-uid-state <UID>");
             pw.println("    Gets the process state of an app given its <UID>.");
+            pw.println();
+            Intent.printIntentArgsHelp(pw, "");
         }
     }
 }
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index caaa77a..e52671f 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -953,22 +953,18 @@
                 stack != null && stack.topRunningActivityLocked() == this;
         final boolean isTopActivityWhileSleeping =
                 service.isSleepingLocked() && isTopActivityInStack;
-        final boolean isTopActivityInMinimizedDockedStack = isTopActivityInStack
-                && stack.mStackId == DOCKED_STACK_ID && mStackSupervisor.mIsDockMinimized
-                && state == ActivityState.PAUSED;
 
         // We want to immediately deliver the intent to the activity if:
-        // - It is the resumed activity.
+        // - It is currently resumed or paused. i.e. it is currently visible to the user and we want
+        //   the user to see the visual effects caused by the intent delivery now.
         // - The device is sleeping and it is the top activity behind the lock screen (b/6700897).
-        // - It is the top activity in a minimized docked stack. In this case the activity will be
-        //   temporarily resumed then paused again on the client side.
-        if ((state == ActivityState.RESUMED || isTopActivityWhileSleeping
-                || isTopActivityInMinimizedDockedStack) && app != null && app.thread != null) {
+        if ((state == ActivityState.RESUMED || state == ActivityState.PAUSED
+                || isTopActivityWhileSleeping) && app != null && app.thread != null) {
             try {
                 ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
                 ar.add(rintent);
                 app.thread.scheduleNewIntent(
-                        ar, appToken, isTopActivityInMinimizedDockedStack /* andPause */);
+                        ar, appToken, state == ActivityState.PAUSED /* andPause */);
                 unsent = false;
             } catch (RemoteException e) {
                 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index b82e28d..d820627 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -29,6 +29,7 @@
 import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
 import static android.content.res.Configuration.SCREENLAYOUT_UNDEFINED;
+import static android.view.Display.DEFAULT_DISPLAY;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_APP;
@@ -68,6 +69,7 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.ActivityManagerService.LOCK_SCREEN_SHOWN;
+import static com.android.server.am.ActivityManagerService.TAKE_FULLSCREEN_SCREENSHOTS;
 import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.STARTING_WINDOW_REMOVED;
@@ -671,7 +673,7 @@
 
     final boolean isOnHomeDisplay() {
         return isAttached() &&
-                mActivityContainer.mActivityDisplay.mDisplayId == Display.DEFAULT_DISPLAY;
+                mActivityContainer.mActivityDisplay.mDisplayId == DEFAULT_DISPLAY;
     }
 
     void moveToFront(String reason) {
@@ -706,9 +708,10 @@
         }
         if (task != null) {
             insertTaskAtTop(task, null);
-        } else {
-            task = topTask();
+            return;
         }
+
+        task = topTask();
         if (task != null) {
             mWindowManager.moveTaskToTop(task.taskId);
         }
@@ -1050,22 +1053,32 @@
 
         int w = mService.mThumbnailWidth;
         int h = mService.mThumbnailHeight;
-        float scale = 1f;
-        if (w > 0) {
-            if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tTaking screenshot");
 
-            // When this flag is set, we currently take the fullscreen screenshot of the activity
-            // but scaled to half the size.  This gives us a "good-enough" fullscreen thumbnail to
-            // use within SystemUI while keeping memory usage low.
-            if (ActivityManagerService.TAKE_FULLSCREEN_SCREENSHOTS) {
-                w = h = -1;
-                scale = mService.mFullscreenThumbnailScale;
-            }
-            return mWindowManager.screenshotApplications(who.appToken, Display.DEFAULT_DISPLAY,
-                    w, h, scale);
+        if (w <= 0) {
+            Slog.e(TAG, "\tInvalid thumbnail dimensions: " + w + "x" + h);
+            return null;
         }
-        Slog.e(TAG, "Invalid thumbnail dimensions: " + w + "x" + h);
-        return null;
+
+        if (mStackId == DOCKED_STACK_ID && mStackSupervisor.mIsDockMinimized) {
+            // When the docked stack is minimized its app windows are cropped significantly so any
+            // screenshot taken will not display the apps contain. So, we avoid taking a screenshot
+            // in that case.
+            if (DEBUG_SCREENSHOTS) Slog.e(TAG, "\tIn minimized docked stack");
+            return null;
+        }
+
+        float scale = 1f;
+        if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tTaking screenshot");
+
+        // When this flag is set, we currently take the fullscreen screenshot of the activity but
+        // scaled to half the size. This gives us a "good-enough" fullscreen thumbnail to use within
+        // SystemUI while keeping memory usage low.
+        if (TAKE_FULLSCREEN_SCREENSHOTS) {
+            w = h = -1;
+            scale = mService.mFullscreenThumbnailScale;
+        }
+
+        return mWindowManager.screenshotApplications(who.appToken, DEFAULT_DISPLAY, w, h, scale);
     }
 
     /**
@@ -1401,7 +1414,12 @@
      * this function updates the rest of our state to match that fact.
      */
     private void completeResumeLocked(ActivityRecord next) {
+        boolean wasVisible = next.visible;
         next.visible = true;
+        if (!wasVisible) {
+            // Visibility has changed, so take a note of it so we call the TaskStackChangedListener
+            mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
+        }
         next.idle = false;
         next.results = null;
         next.newIntents = null;
@@ -2735,6 +2753,7 @@
         }
         mTaskHistory.add(taskNdx, task);
         updateTaskMovement(task, true);
+        mWindowManager.moveTaskToTop(task.taskId);
     }
 
     final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
@@ -2747,7 +2766,6 @@
             // Insert or replace.
             // Might not even be in.
             insertTaskAtTop(rTask, r);
-            mWindowManager.moveTaskToTop(taskId);
         }
         TaskRecord task = null;
         if (!newTask) {
@@ -5016,7 +5034,7 @@
         if (top >= 0) {
             final ArrayList<ActivityRecord> activities = mTaskHistory.get(top).mActivities;
             int activityTop = activities.size() - 1;
-            if (activityTop > 0) {
+            if (activityTop >= 0) {
                 finishActivityLocked(activities.get(activityTop), Activity.RESULT_CANCELED, null,
                         "unhandled-back", true);
             }
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 975b23e1..028c6ac 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -542,9 +542,7 @@
             ephemeralIntent.setPackage(ephemeralPackage);
         } else {
             // Success intent goes back to the installer
-            // TODO; do we need any extras for the installer?
             ephemeralIntent = new Intent(launchIntent);
-            ephemeralIntent.setData(null);
         }
 
         // Intent that is eventually launched if the ephemeral package was
@@ -569,7 +567,7 @@
         intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureIntentTarget));
         intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(successIntentTarget));
         // TODO: Remove when the platform has fully implemented ephemeral apps
-        intent.setData(origIntent.getData());
+        intent.setData(origIntent.getData().buildUpon().clearQuery().build());
         return intent;
     }
 
@@ -2093,4 +2091,18 @@
         return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
                 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
     }
+
+    boolean clearPendingActivityLaunchesLocked(String packageName) {
+        boolean didSomething = false;
+
+        for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
+            PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
+            ActivityRecord r = pal.r;
+            if (r != null && r.packageName.equals(packageName)) {
+                mPendingActivityLaunches.remove(palNdx);
+                didSomething = true;
+            }
+        }
+        return didSomething;
+    }
 }
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 73cd668..9697855 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -32,6 +32,7 @@
 import static com.android.server.am.ActivityManagerService.ALLOW_NON_FULL;
 import static com.android.server.am.ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE;
 import static com.android.server.am.ActivityManagerService.MY_PID;
+import static com.android.server.am.ActivityManagerService.REPORT_LOCKED_BOOT_COMPLETE_MSG;
 import static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_COMPLETE_MSG;
 import static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_MSG;
 import static com.android.server.am.ActivityManagerService.SYSTEM_USER_CURRENT_MSG;
@@ -259,6 +260,8 @@
                 MetricsLogger.histogram(mInjector.getContext(), "framework_locked_boot_completed",
                     uptimeSeconds);
 
+                mHandler.sendMessage(mHandler.obtainMessage(REPORT_LOCKED_BOOT_COMPLETE_MSG,
+                        userId, 0));
                 Intent intent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED, null);
                 intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
                 intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
@@ -1053,6 +1056,18 @@
         mUserSwitchObservers.finishBroadcast();
     }
 
+    void dispatchLockedBootComplete(int userId) {
+        final int observerCount = mUserSwitchObservers.beginBroadcast();
+        for (int i = 0; i < observerCount; i++) {
+            try {
+                mUserSwitchObservers.getBroadcastItem(i).onLockedBootComplete(userId);
+            } catch (RemoteException e) {
+                // Ignore
+            }
+        }
+        mUserSwitchObservers.finishBroadcast();
+    }
+
     private void stopBackgroundUsersIfEnforced(int oldUserId) {
         // Never stop system user
         if (oldUserId == UserHandle.USER_SYSTEM) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 96ba259..0f351f6 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -209,6 +209,7 @@
     private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
     private static final int MSG_SET_ALL_VOLUMES = 10;
     private static final int MSG_REPORT_NEW_ROUTES = 12;
+    private static final int MSG_SET_FORCE_BT_A2DP_USE = 13;
     private static final int MSG_CHECK_MUSIC_ACTIVE = 14;
     private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 15;
     private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 16;
@@ -514,10 +515,6 @@
 
     // Request to override default use of A2DP for media.
     private boolean mBluetoothA2dpEnabled;
-    // FIXME: remove when MediaRouter does not use setBluetoothA2dpOn() anymore
-    // state of bluetooth A2DP enable request sen by deprecated APIs setBluetoothA2dpOn() and
-    // isBluettohA2dpOn()
-    private boolean mBluetoothA2dpEnabledExternal;
     private final Object mBluetoothA2dpEnabledLock = new Object();
 
     // Monitoring of audio routes.  Protected by mCurAudioRoutes.
@@ -2718,23 +2715,22 @@
         return (mForcedUseForComm == AudioSystem.FORCE_BT_SCO);
     }
 
-    /**
-     * Deprecated.
-     * Keep stub implementation until MediaRouter stops using it.
-     * @deprecated
-     * */
+    /** @see AudioManager#setBluetoothA2dpOn(boolean) */
     public void setBluetoothA2dpOn(boolean on) {
-        mBluetoothA2dpEnabledExternal = on;
-        Log.e(TAG, "setBluetoothA2dpOn() is deprecated, now a no-op",
-                new Exception("Deprecated use of setBluetoothA2dpOn()"));
+        synchronized (mBluetoothA2dpEnabledLock) {
+            mBluetoothA2dpEnabled = on;
+            sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE,
+                    AudioSystem.FOR_MEDIA,
+                    mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
+                    null, 0);
+        }
     }
 
-    /** Deprecated.
-     * Keep stub implementation until MediaRouter stops using it
-     * @deprecated
-     * */
+    /** @see AudioManager#isBluetoothA2dpOn() */
     public boolean isBluetoothA2dpOn() {
-        return mBluetoothA2dpEnabledExternal;
+        synchronized (mBluetoothA2dpEnabledLock) {
+            return mBluetoothA2dpEnabled;
+        }
     }
 
     /** @see AudioManager#startBluetoothSco() */
@@ -3807,11 +3803,6 @@
                 Slog.i(TAG, "setWiredDeviceConnectionState(" + state + " nm: " + name + " addr:"
                         + address + ")");
             }
-            if ((state == 0) && ((type == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
-                    (type == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) ||
-                    (type == AudioSystem.DEVICE_OUT_LINE))) {
-                setBluetoothA2dpOnInt(true);
-            }
             int delay = checkSendBecomingNoisyIntent(type, state);
             queueMsgUnderWakeLock(mAudioHandler,
                     MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
@@ -4623,6 +4614,7 @@
                     break;
 
                 case MSG_SET_FORCE_USE:
+                case MSG_SET_FORCE_BT_A2DP_USE:
                     setForceUse(msg.arg1, msg.arg2);
                     break;
 
@@ -5030,7 +5022,6 @@
                     devices |= dev;
                 }
             }
-
             if (devices == device) {
                 sendMsg(mAudioHandler,
                         MSG_BROADCAST_AUDIO_BECOMING_NOISY,
@@ -5126,6 +5117,11 @@
         }
 
         synchronized (mConnectedDevices) {
+            if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
+                    (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) ||
+                    (device == AudioSystem.DEVICE_OUT_LINE))) {
+                setBluetoothA2dpOnInt(true);
+            }
             boolean isUsb = ((device & ~AudioSystem.DEVICE_OUT_ALL_USB) == 0) ||
                             (((device & AudioSystem.DEVICE_BIT_IN) != 0) &&
                              ((device & ~AudioSystem.DEVICE_IN_ALL_USB) == 0));
@@ -5609,6 +5605,7 @@
     public void setBluetoothA2dpOnInt(boolean on) {
         synchronized (mBluetoothA2dpEnabledLock) {
             mBluetoothA2dpEnabled = on;
+            mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE);
             setForceUseInt_SyncDevices(AudioSystem.FOR_MEDIA,
                     mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP);
         }
@@ -5623,6 +5620,8 @@
                 } else { // config == AudioSystem.FORCE_NONE
                     mBecomingNoisyIntentDevices |= AudioSystem.DEVICE_OUT_ALL_A2DP;
                 }
+                sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
+                        SENDMSG_NOOP, 0, 0, null, 0);
                 break;
             case AudioSystem.FOR_DOCK:
                 if (config == AudioSystem.FORCE_ANALOG_DOCK) {
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
new file mode 100644
index 0000000..f1ef947
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity;
+
+import android.net.ConnectivityMetricsEvent;
+import android.net.metrics.ApfProgramEvent;
+import android.net.metrics.ApfStats;
+import android.net.metrics.DefaultNetworkEvent;
+import android.net.metrics.DhcpClientEvent;
+import android.net.metrics.DhcpErrorEvent;
+import android.net.metrics.DnsEvent;
+import android.net.metrics.IpManagerEvent;
+import android.net.metrics.IpReachabilityEvent;
+import android.net.metrics.NetworkEvent;
+import android.net.metrics.RaEvent;
+import android.net.metrics.ValidationProbeEvent;
+import android.os.Parcelable;
+import com.android.server.connectivity.metrics.IpConnectivityLogClass;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.android.server.connectivity.metrics.IpConnectivityLogClass.IpConnectivityEvent;
+import static com.android.server.connectivity.metrics.IpConnectivityLogClass.IpConnectivityLog;
+import static com.android.server.connectivity.metrics.IpConnectivityLogClass.NetworkId;
+
+/** {@hide} */
+final public class IpConnectivityEventBuilder {
+    private IpConnectivityEventBuilder() {
+    }
+
+    public static byte[] serialize(int dropped, List<ConnectivityMetricsEvent> events)
+            throws IOException {
+        final IpConnectivityLog log = new IpConnectivityLog();
+        log.events = toProto(events);
+        log.droppedEvents = dropped;
+        return IpConnectivityLog.toByteArray(log);
+    }
+
+    public static IpConnectivityEvent[] toProto(List<ConnectivityMetricsEvent> eventsIn) {
+        final ArrayList<IpConnectivityEvent> eventsOut = new ArrayList<>(eventsIn.size());
+        for (ConnectivityMetricsEvent in : eventsIn) {
+            final IpConnectivityEvent out = toProto(in);
+            if (out == null) {
+                continue;
+            }
+            eventsOut.add(out);
+        }
+        return eventsOut.toArray(new IpConnectivityEvent[eventsOut.size()]);
+    }
+
+    public static IpConnectivityEvent toProto(ConnectivityMetricsEvent ev) {
+        final IpConnectivityEvent out = new IpConnectivityEvent();
+        if (!setEvent(out, ev.data)) {
+            return null;
+        }
+        out.timeMs = ev.timestamp;
+        return out;
+    }
+
+    private static boolean setEvent(IpConnectivityEvent out, Parcelable in) {
+        if (in instanceof DhcpErrorEvent) {
+            setDhcpErrorEvent(out, (DhcpErrorEvent) in);
+            return true;
+        }
+
+        if (in instanceof DhcpClientEvent) {
+            setDhcpClientEvent(out, (DhcpClientEvent) in);
+            return true;
+        }
+
+        if (in instanceof DnsEvent) {
+            setDnsEvent(out, (DnsEvent) in);
+            return true;
+        }
+
+        if (in instanceof IpManagerEvent) {
+            setIpManagerEvent(out, (IpManagerEvent) in);
+            return true;
+        }
+
+        if (in instanceof IpReachabilityEvent) {
+            setIpReachabilityEvent(out, (IpReachabilityEvent) in);
+            return true;
+        }
+
+        if (in instanceof DefaultNetworkEvent) {
+            setDefaultNetworkEvent(out, (DefaultNetworkEvent) in);
+            return true;
+        }
+
+        if (in instanceof NetworkEvent) {
+            setNetworkEvent(out, (NetworkEvent) in);
+            return true;
+        }
+
+        if (in instanceof ValidationProbeEvent) {
+            setValidationProbeEvent(out, (ValidationProbeEvent) in);
+            return true;
+        }
+
+        if (in instanceof ApfProgramEvent) {
+            setApfProgramEvent(out, (ApfProgramEvent) in);
+            return true;
+        }
+
+        if (in instanceof ApfStats) {
+            setApfStats(out, (ApfStats) in);
+            return true;
+        }
+
+        if (in instanceof RaEvent) {
+            setRaEvent(out, (RaEvent) in);
+            return true;
+        }
+
+        return false;
+    }
+
+    private static void setDhcpErrorEvent(IpConnectivityEvent out, DhcpErrorEvent in) {
+        out.dhcpEvent = new IpConnectivityLogClass.DHCPEvent();
+        out.dhcpEvent.ifName = in.ifName;
+        out.dhcpEvent.errorCode = in.errorCode;
+    }
+
+    private static void setDhcpClientEvent(IpConnectivityEvent out, DhcpClientEvent in) {
+        out.dhcpEvent = new IpConnectivityLogClass.DHCPEvent();
+        out.dhcpEvent.ifName = in.ifName;
+        out.dhcpEvent.stateTransition = in.msg;
+        out.dhcpEvent.durationMs = in.durationMs;
+    }
+
+    private static void setDnsEvent(IpConnectivityEvent out, DnsEvent in) {
+        out.dnsLookupBatch = new IpConnectivityLogClass.DNSLookupBatch();
+        out.dnsLookupBatch.networkId = netIdOf(in.netId);
+        out.dnsLookupBatch.eventTypes = bytesToInts(in.eventTypes);
+        out.dnsLookupBatch.returnCodes = bytesToInts(in.returnCodes);
+        out.dnsLookupBatch.latenciesMs = in.latenciesMs;
+    }
+
+    private static void setIpManagerEvent(IpConnectivityEvent out, IpManagerEvent in) {
+        out.ipProvisioningEvent = new IpConnectivityLogClass.IpProvisioningEvent();
+        out.ipProvisioningEvent.ifName = in.ifName;
+        out.ipProvisioningEvent.eventType = in.eventType;
+        out.ipProvisioningEvent.latencyMs = (int) in.durationMs;
+    }
+
+    private static void setIpReachabilityEvent(IpConnectivityEvent out, IpReachabilityEvent in) {
+        out.ipReachabilityEvent = new IpConnectivityLogClass.IpReachabilityEvent();
+        out.ipReachabilityEvent.ifName = in.ifName;
+        out.ipReachabilityEvent.eventType = in.eventType;
+    }
+
+    private static void setDefaultNetworkEvent(IpConnectivityEvent out, DefaultNetworkEvent in) {
+        out.defaultNetworkEvent = new IpConnectivityLogClass.DefaultNetworkEvent();
+        out.defaultNetworkEvent.networkId = netIdOf(in.netId);
+        out.defaultNetworkEvent.previousNetworkId = netIdOf(in.prevNetId);
+        out.defaultNetworkEvent.transportTypes = in.transportTypes;
+        out.defaultNetworkEvent.previousNetworkIpSupport = ipSupportOf(in);
+    }
+
+    private static void setNetworkEvent(IpConnectivityEvent out, NetworkEvent in) {
+        out.networkEvent = new IpConnectivityLogClass.NetworkEvent();
+        out.networkEvent.networkId = netIdOf(in.netId);
+        out.networkEvent.eventType = in.eventType;
+        out.networkEvent.latencyMs = (int) in.durationMs;
+    }
+
+    private static void setValidationProbeEvent(IpConnectivityEvent out, ValidationProbeEvent in) {
+        out.validationProbeEvent = new IpConnectivityLogClass.ValidationProbeEvent();
+        out.validationProbeEvent.networkId = netIdOf(in.netId);
+        out.validationProbeEvent.latencyMs = (int) in.durationMs;
+        out.validationProbeEvent.probeType = in.probeType;
+        out.validationProbeEvent.probeResult = in.returnCode;
+    }
+
+    private static void setApfProgramEvent(IpConnectivityEvent out, ApfProgramEvent in) {
+        out.apfProgramEvent = new IpConnectivityLogClass.ApfProgramEvent();
+        out.apfProgramEvent.lifetime = in.lifetime;
+        out.apfProgramEvent.filteredRas = in.filteredRas;
+        out.apfProgramEvent.currentRas = in.currentRas;
+        out.apfProgramEvent.programLength = in.programLength;
+        if (isBitSet(in.flags, ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)) {
+            out.apfProgramEvent.dropMulticast = true;
+        }
+        if (isBitSet(in.flags, ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)) {
+            out.apfProgramEvent.hasIpv4Addr = true;
+        }
+    }
+
+    private static void setApfStats(IpConnectivityEvent out, ApfStats in) {
+        out.apfStatistics = new IpConnectivityLogClass.ApfStatistics();
+        out.apfStatistics.durationMs = in.durationMs;
+        out.apfStatistics.receivedRas = in.receivedRas;
+        out.apfStatistics.matchingRas = in.matchingRas;
+        out.apfStatistics.droppedRas = in.droppedRas;
+        out.apfStatistics.zeroLifetimeRas = in.zeroLifetimeRas;
+        out.apfStatistics.parseErrors = in.parseErrors;
+        out.apfStatistics.programUpdates = in.programUpdates;
+        out.apfStatistics.maxProgramSize = in.maxProgramSize;
+    }
+
+    private static void setRaEvent(IpConnectivityEvent out, RaEvent in) {
+        out.raEvent = new IpConnectivityLogClass.RaEvent();
+        out.raEvent.routerLifetime = in.routerLifetime;
+        out.raEvent.prefixValidLifetime = in.prefixValidLifetime;
+        out.raEvent.prefixPreferredLifetime = in.prefixPreferredLifetime;
+        out.raEvent.routeInfoLifetime = in.routeInfoLifetime;
+        out.raEvent.rdnssLifetime = in.rdnssLifetime;
+        out.raEvent.dnsslLifetime = in.dnsslLifetime;
+    }
+
+    private static int[] bytesToInts(byte[] in) {
+        final int[] out = new int[in.length];
+        for (int i = 0; i < in.length; i++) {
+            out[i] = in[i] & 0xFF;
+        }
+        return out;
+    }
+
+    private static NetworkId netIdOf(int netid) {
+        final NetworkId ni = new NetworkId();
+        ni.networkId = netid;
+        return ni;
+    }
+
+    private static int ipSupportOf(DefaultNetworkEvent in) {
+        if (in.prevIPv4 && in.prevIPv6) {
+            return IpConnectivityLogClass.DefaultNetworkEvent.DUAL;
+        }
+        if (in.prevIPv6) {
+            return IpConnectivityLogClass.DefaultNetworkEvent.IPV6;
+        }
+        if (in.prevIPv4) {
+            return IpConnectivityLogClass.DefaultNetworkEvent.IPV4;
+        }
+        return IpConnectivityLogClass.DefaultNetworkEvent.NONE;
+    }
+
+    private static boolean isBitSet(int flags, int bit) {
+        return (flags & (1 << bit)) != 0;
+    }
+}
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
new file mode 100644
index 0000000..28e724c
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity;
+
+import android.content.Context;
+import android.net.ConnectivityMetricsEvent;
+import android.net.IIpConnectivityMetrics;
+import android.net.metrics.IpConnectivityLog;
+import android.os.IBinder;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Base64;
+import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.SystemService;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+import static com.android.server.connectivity.metrics.IpConnectivityLogClass.IpConnectivityEvent;
+
+/** {@hide} */
+final public class IpConnectivityMetrics extends SystemService {
+    private static final String TAG = IpConnectivityMetrics.class.getSimpleName();
+    private static final boolean DBG = false;
+
+    private static final String SERVICE_NAME = IpConnectivityLog.SERVICE_NAME;
+
+    // Default size of the event buffer. Once the buffer is full, incoming events are dropped.
+    private static final int DEFAULT_BUFFER_SIZE = 2000;
+
+    // Lock ensuring that concurrent manipulations of the event buffer are correct.
+    // There are three concurrent operations to synchronize:
+    //  - appending events to the buffer.
+    //  - iterating throught the buffer.
+    //  - flushing the buffer content and replacing it by a new buffer.
+    private final Object mLock = new Object();
+
+    @VisibleForTesting
+    public final Impl impl = new Impl();
+    private NetdEventListenerService mNetdListener;
+
+    @GuardedBy("mLock")
+    private ArrayList<ConnectivityMetricsEvent> mBuffer;
+    @GuardedBy("mLock")
+    private int mDropped;
+    @GuardedBy("mLock")
+    private int mCapacity;
+
+    public IpConnectivityMetrics(Context ctx) {
+        super(ctx);
+        initBuffer();
+    }
+
+    @Override
+    public void onStart() {
+        if (DBG) Log.d(TAG, "onStart");
+    }
+
+    @Override
+    public void onBootPhase(int phase) {
+        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+            if (DBG) Log.d(TAG, "onBootPhase");
+            mNetdListener = new NetdEventListenerService(getContext());
+
+            publishBinderService(SERVICE_NAME, impl);
+            publishBinderService(mNetdListener.SERVICE_NAME, mNetdListener);
+        }
+    }
+
+    @VisibleForTesting
+    public int bufferCapacity() {
+        return DEFAULT_BUFFER_SIZE; // TODO: read from config
+    }
+
+    private void initBuffer() {
+        synchronized (mLock) {
+            mDropped = 0;
+            mCapacity = bufferCapacity();
+            mBuffer = new ArrayList<>(mCapacity);
+        }
+    }
+
+    private int append(ConnectivityMetricsEvent event) {
+        if (DBG) Log.d(TAG, "logEvent: " + event);
+        synchronized (mLock) {
+            final int left = mCapacity - mBuffer.size();
+            if (event == null) {
+                return left;
+            }
+            if (left == 0) {
+                mDropped++;
+                return 0;
+            }
+            mBuffer.add(event);
+            return left - 1;
+        }
+    }
+
+    private String flushEncodedOutput() {
+        final ArrayList<ConnectivityMetricsEvent> events;
+        final int dropped;
+        synchronized (mLock) {
+            events = mBuffer;
+            dropped = mDropped;
+            initBuffer();
+        }
+
+        final byte[] data;
+        try {
+            data = IpConnectivityEventBuilder.serialize(dropped, events);
+        } catch (IOException e) {
+            Log.e(TAG, "could not serialize events", e);
+            return "";
+        }
+
+        return Base64.encodeToString(data, Base64.DEFAULT);
+    }
+
+    /**
+     * Clears the event buffer and prints its content as a protobuf serialized byte array
+     * inside a base64 encoded string.
+     */
+    private void cmdFlush(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.print(flushEncodedOutput());
+    }
+
+    /**
+     * Prints the content of the event buffer, either using the events ASCII representation
+     * or using protobuf text format.
+     */
+    private void cmdList(FileDescriptor fd, PrintWriter pw, String[] args) {
+        final ArrayList<ConnectivityMetricsEvent> events;
+        synchronized (mLock) {
+            events = new ArrayList(mBuffer);
+        }
+
+        if (args.length > 1 && args[1].equals("proto")) {
+            for (IpConnectivityEvent ev : IpConnectivityEventBuilder.toProto(events)) {
+                pw.print(ev.toString());
+            }
+            return;
+        }
+
+        for (ConnectivityMetricsEvent ev : events) {
+            pw.println(ev.toString());
+        }
+    }
+
+    private void cmdStats(FileDescriptor fd, PrintWriter pw, String[] args) {
+        synchronized (mLock) {
+            pw.println("Buffered events: " + mBuffer.size());
+            pw.println("Buffer capacity: " + mCapacity);
+            pw.println("Dropped events: " + mDropped);
+        }
+        if (mNetdListener != null) {
+            mNetdListener.dump(pw);
+        }
+    }
+
+    private void cmdDefault(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (args.length == 0) {
+            pw.println("No command");
+            return;
+        }
+        pw.println("Unknown command " + TextUtils.join(" ", args));
+    }
+
+    public final class Impl extends IIpConnectivityMetrics.Stub {
+        static final String CMD_FLUSH   = "flush";
+        static final String CMD_LIST    = "list";
+        static final String CMD_STATS   = "stats";
+        static final String CMD_DEFAULT = CMD_STATS;
+
+        @Override
+        public int logEvent(ConnectivityMetricsEvent event) {
+            enforceConnectivityInternalPermission();
+            return append(event);
+        }
+
+        @Override
+        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            enforceDumpPermission();
+            if (DBG) Log.d(TAG, "dumpsys " + TextUtils.join(" ", args));
+            final String cmd = (args.length > 0) ? args[0] : CMD_DEFAULT;
+            switch (cmd) {
+                case CMD_FLUSH:
+                    cmdFlush(fd, pw, args);
+                    return;
+                case CMD_LIST:
+                    cmdList(fd, pw, args);
+                    return;
+                case CMD_STATS:
+                    cmdStats(fd, pw, args);
+                    return;
+                default:
+                    cmdDefault(fd, pw, args);
+            }
+        }
+
+        private void enforceConnectivityInternalPermission() {
+            enforcePermission(android.Manifest.permission.CONNECTIVITY_INTERNAL);
+        }
+
+        private void enforceDumpPermission() {
+            enforcePermission(android.Manifest.permission.DUMP);
+        }
+
+        private void enforcePermission(String what) {
+            getContext().enforceCallingOrSelfPermission(what, "IpConnectivityMetrics");
+        }
+    };
+}
diff --git a/services/core/java/com/android/server/connectivity/MetricsLoggerService.java b/services/core/java/com/android/server/connectivity/MetricsLoggerService.java
index 168ce85..1c9feb2 100644
--- a/services/core/java/com/android/server/connectivity/MetricsLoggerService.java
+++ b/services/core/java/com/android/server/connectivity/MetricsLoggerService.java
@@ -56,8 +56,6 @@
             if (DBG) Log.d(TAG, "onBootPhase: PHASE_SYSTEM_SERVICES_READY");
             publishBinderService(ConnectivityMetricsLogger.CONNECTIVITY_METRICS_LOGGER_SERVICE,
                     mBinder);
-            mNetdListener = new NetdEventListenerService(getContext());
-            publishBinderService(mNetdListener.SERVICE_NAME, mNetdListener);
         }
     }
 
@@ -86,8 +84,6 @@
 
     private final ArrayDeque<ConnectivityMetricsEvent> mEvents = new ArrayDeque<>();
 
-    private NetdEventListenerService mNetdListener;
-
     private void enforceConnectivityInternalPermission() {
         getContext().enforceCallingOrSelfPermission(
                 android.Manifest.permission.CONNECTIVITY_INTERNAL,
@@ -219,11 +215,6 @@
                     }
                 }
             }
-
-            pw.println();
-            if (mNetdListener != null) {
-                mNetdListener.dump(pw);
-            }
         }
 
         public long logEvent(ConnectivityMetricsEvent event) {
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 42d80fc..6eb89fa 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -23,7 +23,6 @@
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -37,14 +36,12 @@
 import android.net.metrics.IpConnectivityLog;
 import android.net.metrics.NetworkEvent;
 import android.net.metrics.ValidationProbeEvent;
+import android.net.util.Stopwatch;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
-import android.net.util.Stopwatch;
 import android.os.Handler;
 import android.os.Message;
-import android.os.Process;
 import android.os.SystemClock;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.telephony.CellIdentityCdma;
@@ -66,27 +63,39 @@
 import com.android.internal.util.Protocol;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
-import com.android.internal.util.WakeupMessage;
 
 import java.io.IOException;
 import java.net.HttpURLConnection;
 import java.net.InetAddress;
 import java.net.MalformedURLException;
-import java.net.UnknownHostException;
 import java.net.URL;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicReference;
+import java.net.UnknownHostException;
 import java.util.List;
 import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /**
  * {@hide}
  */
 public class NetworkMonitor extends StateMachine {
-    private static final boolean DBG = false;
     private static final String TAG = NetworkMonitor.class.getSimpleName();
-    private static final String DEFAULT_SERVER = "connectivitycheck.gstatic.com";
+    private static final boolean DBG = false;
+
+    // Default configuration values for captive portal detection probes.
+    // TODO: append a random length parameter to the default HTTPS url.
+    // TODO: randomize browser version ids in the default User-Agent String.
+    private static final String DEFAULT_HTTPS_URL     = "https://www.google.com/generate_204";
+    private static final String DEFAULT_HTTP_URL      =
+            "http://connectivitycheck.gstatic.com/generate_204";
+    private static final String DEFAULT_FALLBACK_URL  = "http://www.google.com/gen_204";
+    private static final String DEFAULT_USER_AGENT    = "Mozilla/5.0 (X11; Linux x86_64) "
+                                                      + "AppleWebKit/537.36 (KHTML, like Gecko) "
+                                                      + "Chrome/52.0.2743.82 Safari/537.36";
+
     private static final int SOCKET_TIMEOUT_MS = 10000;
+    private static final int PROBE_TIMEOUT_MS  = 3000;
+
     public static final String ACTION_NETWORK_CONDITIONS_MEASURED =
             "android.net.conn.NETWORK_CONDITIONS_MEASURED";
     public static final String EXTRA_CONNECTIVITY_TYPE = "extra_connectivity_type";
@@ -224,6 +233,9 @@
 
     private final Stopwatch mEvaluationTimer = new Stopwatch();
 
+    // This variable is set before transitioning to the mCaptivePortalState.
+    private CaptivePortalProbeResult mLastPortalProbeResult = CaptivePortalProbeResult.FAILED;
+
     public NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo,
             NetworkRequest defaultRequest) {
         this(context, handler, networkAgentInfo, defaultRequest, new IpConnectivityLog());
@@ -389,6 +401,8 @@
                                     sendMessage(CMD_CAPTIVE_PORTAL_APP_FINISHED, response);
                                 }
                             }));
+                    intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL,
+                            mLastPortalProbeResult.detectUrl);
                     intent.setFlags(
                             Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
                     mContext.startActivityAsUser(intent, UserHandle.CURRENT);
@@ -412,14 +426,22 @@
      */
     @VisibleForTesting
     public static final class CaptivePortalProbeResult {
-        static final CaptivePortalProbeResult FAILED = new CaptivePortalProbeResult(599, null);
+        static final CaptivePortalProbeResult FAILED = new CaptivePortalProbeResult(599);
 
-        final int mHttpResponseCode; // HTTP response code returned from Internet probe.
-        final String mRedirectUrl;   // Redirect destination returned from Internet probe.
+        private final int mHttpResponseCode;  // HTTP response code returned from Internet probe.
+        final String redirectUrl;             // Redirect destination returned from Internet probe.
+        final String detectUrl;               // URL where a 204 response code indicates
+                                              // captive portal has been appeased.
 
-        public CaptivePortalProbeResult(int httpResponseCode, String redirectUrl) {
+        public CaptivePortalProbeResult(
+                int httpResponseCode, String redirectUrl, String detectUrl) {
             mHttpResponseCode = httpResponseCode;
-            mRedirectUrl = redirectUrl;
+            this.redirectUrl = redirectUrl;
+            this.detectUrl = detectUrl;
+        }
+
+        public CaptivePortalProbeResult(int httpResponseCode) {
+            this(httpResponseCode, null, null);
         }
 
         boolean isSuccessful() { return mHttpResponseCode == 204; }
@@ -492,7 +514,8 @@
                         transitionTo(mValidatedState);
                     } else if (probeResult.isPortal()) {
                         mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
-                                NETWORK_TEST_RESULT_INVALID, mNetId, probeResult.mRedirectUrl));
+                                NETWORK_TEST_RESULT_INVALID, mNetId, probeResult.redirectUrl));
+                        mLastPortalProbeResult = probeResult;
                         transitionTo(mCaptivePortalState);
                     } else {
                         final Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
@@ -500,7 +523,7 @@
                         logNetworkEvent(NetworkEvent.NETWORK_VALIDATION_FAILED);
                         mConnectivityServiceHandler.sendMessage(obtainMessage(
                                 EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID, mNetId,
-                                probeResult.mRedirectUrl));
+                                probeResult.redirectUrl));
                         if (mAttempts >= BLAME_FOR_EVALUATION_ATTEMPTS) {
                             // Don't continue to blame UID forever.
                             TrafficStats.clearThreadStatsUid();
@@ -585,22 +608,33 @@
         }
     }
 
-    private static String getCaptivePortalServerUrl(Context context, boolean isHttps) {
-        String server = Settings.Global.getString(context.getContentResolver(),
-                Settings.Global.CAPTIVE_PORTAL_SERVER);
-        if (server == null) server = DEFAULT_SERVER;
-        return (isHttps ? "https" : "http") + "://" + server + "/generate_204";
+    private static String getCaptivePortalServerHttpsUrl(Context context) {
+        return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTPS_URL, DEFAULT_HTTPS_URL);
     }
 
-    public static String getCaptivePortalServerUrl(Context context) {
-        return getCaptivePortalServerUrl(context, false);
+    public static String getCaptivePortalServerHttpUrl(Context context) {
+        return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTP_URL, DEFAULT_HTTP_URL);
+    }
+
+    private static String getCaptivePortalFallbackUrl(Context context) {
+        return getSetting(context,
+                Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL, DEFAULT_FALLBACK_URL);
+    }
+
+    private static String getCaptivePortalUserAgent(Context context) {
+        return getSetting(context, Settings.Global.CAPTIVE_PORTAL_USER_AGENT, DEFAULT_USER_AGENT);
+    }
+
+    private static String getSetting(Context context, String symbol, String defaultValue) {
+        final String value = Settings.Global.getString(context.getContentResolver(), symbol);
+        return value != null ? value : defaultValue;
     }
 
     @VisibleForTesting
     protected CaptivePortalProbeResult isCaptivePortal() {
-        if (!mIsCaptivePortalCheckEnabled) return new CaptivePortalProbeResult(204, null);
+        if (!mIsCaptivePortalCheckEnabled) return new CaptivePortalProbeResult(204);
 
-        URL pacUrl = null, httpUrl = null, httpsUrl = null;
+        URL pacUrl = null, httpsUrl = null, httpUrl = null, fallbackUrl = null;
 
         // On networks with a PAC instead of fetching a URL that should result in a 204
         // response, we instead simply fetch the PAC script.  This is done for a few reasons:
@@ -621,20 +655,17 @@
         //    results for network validation.
         final ProxyInfo proxyInfo = mNetworkAgentInfo.linkProperties.getHttpProxy();
         if (proxyInfo != null && !Uri.EMPTY.equals(proxyInfo.getPacFileUrl())) {
-            try {
-                pacUrl = new URL(proxyInfo.getPacFileUrl().toString());
-            } catch (MalformedURLException e) {
-                validationLog("Invalid PAC URL: " + proxyInfo.getPacFileUrl().toString());
+            pacUrl = makeURL(proxyInfo.getPacFileUrl().toString());
+            if (pacUrl == null) {
                 return CaptivePortalProbeResult.FAILED;
             }
         }
 
         if (pacUrl == null) {
-            try {
-                httpUrl = new URL(getCaptivePortalServerUrl(mContext, false));
-                httpsUrl = new URL(getCaptivePortalServerUrl(mContext, true));
-            } catch (MalformedURLException e) {
-                validationLog("Bad validation URL: " + getCaptivePortalServerUrl(mContext, false));
+            httpsUrl = makeURL(getCaptivePortalServerHttpsUrl(mContext));
+            httpUrl = makeURL(getCaptivePortalServerHttpUrl(mContext));
+            fallbackUrl = makeURL(getCaptivePortalFallbackUrl(mContext));
+            if (httpUrl == null || httpsUrl == null) {
                 return CaptivePortalProbeResult.FAILED;
             }
         }
@@ -680,7 +711,7 @@
         if (pacUrl != null) {
             result = sendHttpProbe(pacUrl, ValidationProbeEvent.PROBE_PAC);
         } else if (mUseHttps) {
-            result = sendParallelHttpProbes(httpsUrl, httpUrl);
+            result = sendParallelHttpProbes(httpsUrl, httpUrl, fallbackUrl);
         } else {
             result = sendHttpProbe(httpUrl, ValidationProbeEvent.PROBE_HTTP);
         }
@@ -710,6 +741,10 @@
             urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
             urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
             urlConnection.setUseCaches(false);
+            final String userAgent = getCaptivePortalUserAgent(mContext);
+            if (userAgent != null) {
+               urlConnection.setRequestProperty("User-Agent", userAgent);
+            }
 
             // Time how long it takes to get a response to our request
             long requestTimestamp = SystemClock.elapsedRealtime();
@@ -755,28 +790,24 @@
             }
         }
         logValidationProbe(probeTimer.stop(), probeType, httpResponseCode);
-        return new CaptivePortalProbeResult(httpResponseCode, redirectUrl);
+        return new CaptivePortalProbeResult(httpResponseCode, redirectUrl, url.toString());
     }
 
-    private CaptivePortalProbeResult sendParallelHttpProbes(URL httpsUrl, URL httpUrl) {
-        // Number of probes to wait for. We might wait for all of them, but we might also return if
-        // only one of them has replied. For example, we immediately return if the HTTP probe finds
-        // a captive portal, even if the HTTPS probe is timing out.
+    private CaptivePortalProbeResult sendParallelHttpProbes(
+            URL httpsUrl, URL httpUrl, URL fallbackUrl) {
+        // Number of probes to wait for. If a probe completes with a conclusive answer
+        // it shortcuts the latch immediately by forcing the count to 0.
         final CountDownLatch latch = new CountDownLatch(2);
 
-        // Which probe result we're going to use. This doesn't need to be atomic, but it does need
-        // to be final because otherwise we can't set it from the ProbeThreads.
-        final AtomicReference<CaptivePortalProbeResult> finalResult = new AtomicReference<>();
-
         final class ProbeThread extends Thread {
             private final boolean mIsHttps;
-            private volatile CaptivePortalProbeResult mResult;
+            private volatile CaptivePortalProbeResult mResult = CaptivePortalProbeResult.FAILED;
 
             public ProbeThread(boolean isHttps) {
                 mIsHttps = isHttps;
             }
 
-            public CaptivePortalProbeResult getResult() {
+            public CaptivePortalProbeResult result() {
                 return mResult;
             }
 
@@ -788,32 +819,66 @@
                     mResult = sendHttpProbe(httpUrl, ValidationProbeEvent.PROBE_HTTP);
                 }
                 if ((mIsHttps && mResult.isSuccessful()) || (!mIsHttps && mResult.isPortal())) {
-                    // HTTPS succeeded, or HTTP found a portal. Don't wait for the other probe.
-                    finalResult.compareAndSet(null, mResult);
-                    latch.countDown();
+                    // Stop waiting immediately if https succeeds or if http finds a portal.
+                    while (latch.getCount() > 0) {
+                        latch.countDown();
+                    }
                 }
-                // Signal that one probe has completed. If we've already made a decision, or if this
-                // is the second probe, the latch will be at zero and we'll return a result.
+                // Signal this probe has completed.
                 latch.countDown();
             }
         }
 
-        ProbeThread httpsProbe = new ProbeThread(true);
-        ProbeThread httpProbe = new ProbeThread(false);
-        httpsProbe.start();
-        httpProbe.start();
+        final ProbeThread httpsProbe = new ProbeThread(true);
+        final ProbeThread httpProbe = new ProbeThread(false);
 
         try {
-            latch.await();
+            httpsProbe.start();
+            httpProbe.start();
+            latch.await(PROBE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
         } catch (InterruptedException e) {
-            validationLog("Error: probe wait interrupted!");
+            validationLog("Error: probes wait interrupted!");
             return CaptivePortalProbeResult.FAILED;
         }
 
-        // If there was no deciding probe, that means that both probes completed. Return HTTPS.
-        finalResult.compareAndSet(null, httpsProbe.getResult());
+        final CaptivePortalProbeResult httpsResult = httpsProbe.result();
+        final CaptivePortalProbeResult httpResult = httpProbe.result();
 
-        return finalResult.get();
+        // Look for a conclusive probe result first.
+        if (httpResult.isPortal()) {
+            return httpResult;
+        }
+        // httpsResult.isPortal() is not expected, but check it nonetheless.
+        if (httpsResult.isPortal() || httpsResult.isSuccessful()) {
+            return httpsResult;
+        }
+        // If a fallback url is specified, use a fallback probe to try again portal detection.
+        if (fallbackUrl != null) {
+            CaptivePortalProbeResult result =
+                    sendHttpProbe(fallbackUrl, ValidationProbeEvent.PROBE_FALLBACK);
+            if (result.isPortal()) {
+                return result;
+            }
+        }
+        // Otherwise wait until https probe completes and use its result.
+        try {
+            httpsProbe.join();
+        } catch (InterruptedException e) {
+            validationLog("Error: https probe wait interrupted!");
+            return CaptivePortalProbeResult.FAILED;
+        }
+        return httpsProbe.result();
+    }
+
+    private URL makeURL(String url) {
+        if (url != null) {
+            try {
+                return new URL(url);
+            } catch (MalformedURLException e) {
+                validationLog("Bad URL: " + url);
+            }
+        }
+        return null;
     }
 
     /**
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 927f8f9..50faf3b 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -33,6 +33,7 @@
 import android.hardware.usb.UsbManager;
 import android.net.ConnectivityManager;
 import android.net.ConnectivityManager.NetworkCallback;
+import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
 import android.net.LinkProperties;
 import android.net.Network;
@@ -49,6 +50,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
+import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -123,6 +125,7 @@
 
     private final INetworkManagementService mNMService;
     private final INetworkStatsService mStatsService;
+    private final INetworkPolicyManager mPolicyManager;
     private final Looper mLooper;
 
     private static class TetherState {
@@ -177,10 +180,11 @@
     private boolean mWifiTetherRequested;
 
     public Tethering(Context context, INetworkManagementService nmService,
-            INetworkStatsService statsService) {
+            INetworkStatsService statsService, INetworkPolicyManager policyManager) {
         mContext = context;
         mNMService = nmService;
         mStatsService = statsService;
+        mPolicyManager = policyManager;
 
         mPublicSync = new Object();
 
@@ -622,12 +626,9 @@
     }
 
     public void untetherAll() {
-        synchronized (mPublicSync) {
-            if (DBG) Log.d(TAG, "Untethering " + mTetherStates.keySet());
-            for (int i = 0; i < mTetherStates.size(); i++) {
-                untether(mTetherStates.keyAt(i));
-            }
-        }
+        stopTethering(ConnectivityManager.TETHERING_WIFI);
+        stopTethering(ConnectivityManager.TETHERING_USB);
+        stopTethering(ConnectivityManager.TETHERING_BLUETOOTH);
     }
 
     public int getLastTetherError(String iface) {
@@ -1908,6 +1909,15 @@
                     " with error " + error);
         }
 
+        try {
+            // Notify that we're tethering (or not) this interface.
+            // This is how data saver for instance knows if the user explicitly
+            // turned on tethering (thus keeping us from being in data saver mode).
+            mPolicyManager.onTetheringChanged(iface, state == IControlsTethering.STATE_TETHERED);
+        } catch (RemoteException e) {
+            // Not really very much we can do here.
+        }
+
         switch (state) {
             case IControlsTethering.STATE_UNAVAILABLE:
             case IControlsTethering.STATE_AVAILABLE:
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index 9fa93f4..3072f43 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -24,8 +24,10 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.IRemoteCallback;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.IBinder.DeathRecipient;
@@ -253,7 +255,8 @@
     private void attach(IDreamService service) {
         try {
             service.asBinder().linkToDeath(mCurrentDream, 0);
-            service.attach(mCurrentDream.mToken, mCurrentDream.mCanDoze);
+            service.attach(mCurrentDream.mToken, mCurrentDream.mCanDoze,
+                    mCurrentDream.mDreamingStartedCallback);
         } catch (RemoteException ex) {
             Slog.e(TAG, "The dream service died unexpectedly.", ex);
             stopDream(true /*immediate*/);
@@ -298,10 +301,10 @@
             mCanDoze = canDoze;
             mUserId  = userId;
             mWakeLock = wakeLock;
-            // Hold the lock while we're waiting for the service to connect. Released either when
-            // DreamService connects (and is then responsible for keeping the device awake) or
-            // dreaming stops.
+            // Hold the lock while we're waiting for the service to connect and start dreaming.
+            // Released after the service has started dreaming, we stop dreaming, or it timed out.
             mWakeLock.acquire();
+            mHandler.postDelayed(mReleaseWakeLockIfNeeded, 10000);
         }
 
         // May be called on any thread.
@@ -324,25 +327,17 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    try {
-                        mConnected = true;
-                        if (mCurrentDream == DreamRecord.this && mService == null) {
-                            attach(IDreamService.Stub.asInterface(service));
-                        }
-                    } finally {
+                    mConnected = true;
+                    if (mCurrentDream == DreamRecord.this && mService == null) {
+                        attach(IDreamService.Stub.asInterface(service));
+                        // Wake lock will be released once dreaming starts.
+                    } else {
                         releaseWakeLockIfNeeded();
                     }
                 }
             });
         }
 
-        private void releaseWakeLockIfNeeded() {
-            if (mWakeLock != null) {
-                mWakeLock.release();
-                mWakeLock = null;
-            }
-        }
-
         // May be called on any thread.
         @Override
         public void onServiceDisconnected(ComponentName name) {
@@ -356,5 +351,23 @@
                 }
             });
         }
+
+        void releaseWakeLockIfNeeded() {
+            if (mWakeLock != null) {
+                mWakeLock.release();
+                mWakeLock = null;
+                mHandler.removeCallbacks(mReleaseWakeLockIfNeeded);
+            }
+        }
+
+        final Runnable mReleaseWakeLockIfNeeded = this::releaseWakeLockIfNeeded;
+
+        final IRemoteCallback mDreamingStartedCallback = new IRemoteCallback.Stub() {
+            // May be called on any thread.
+            @Override
+            public void sendResult(Bundle data) throws RemoteException {
+                mHandler.post(mReleaseWakeLockIfNeeded);
+            }
+        };
     }
 }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java b/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
new file mode 100644
index 0000000..cca9f10
--- /dev/null
+++ b/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.emergency;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings;
+import android.telephony.CellInfo;
+import android.telephony.CellInfoGsm;
+import android.telephony.CellInfoLte;
+import android.telephony.CellInfoWcdma;
+import android.telephony.CellLocation;
+import android.telephony.PhoneStateListener;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import com.android.server.SystemService;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A service that listens to connectivity and SIM card changes and determines if the emergency mode
+ * should be enabled
+ */
+public class EmergencyAffordanceService extends SystemService {
+
+    private static final String TAG = "EmergencyAffordanceService";
+
+    private static final int NUM_SCANS_UNTIL_ABORT = 4;
+
+    private static final int INITIALIZE_STATE = 1;
+    private static final int CELL_INFO_STATE_CHANGED = 2;
+    private static final int SUBSCRIPTION_CHANGED = 3;
+
+    /**
+     * Global setting, whether the last scan of the sim cards reveal that a sim was inserted that
+     * requires the emergency affordance. The value is a boolean (1 or 0).
+     * @hide
+     */
+    private static final String EMERGENCY_SIM_INSERTED_SETTING = "emergency_sim_inserted_before";
+
+    private final Context mContext;
+    private final ArrayList<Integer> mEmergencyCallMccNumbers;
+
+    private final Object mLock = new Object();
+
+    private TelephonyManager mTelephonyManager;
+    private SubscriptionManager mSubscriptionManager;
+    private boolean mEmergencyAffordanceNeeded;
+    private MyHandler mHandler;
+    private int mScansCompleted;
+    private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+        @Override
+        public void onCellInfoChanged(List<CellInfo> cellInfo) {
+            if (!isEmergencyAffordanceNeeded()) {
+                requestCellScan();
+            }
+        }
+
+        @Override
+        public void onCellLocationChanged(CellLocation location) {
+            if (!isEmergencyAffordanceNeeded()) {
+                requestCellScan();
+            }
+        }
+    };
+    private BroadcastReceiver mAirplaneModeReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (Settings.Global.getInt(context.getContentResolver(),
+                    Settings.Global.AIRPLANE_MODE_ON, 0) == 0) {
+                startScanning();
+                requestCellScan();
+            }
+        }
+    };
+    private boolean mSimNeedsEmergencyAffordance;
+    private boolean mNetworkNeedsEmergencyAffordance;
+
+    private void requestCellScan() {
+        mHandler.obtainMessage(CELL_INFO_STATE_CHANGED).sendToTarget();
+    }
+
+    private SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionChangedListener
+            = new SubscriptionManager.OnSubscriptionsChangedListener() {
+        @Override
+        public void onSubscriptionsChanged() {
+            mHandler.obtainMessage(SUBSCRIPTION_CHANGED).sendToTarget();
+        }
+    };
+
+    public EmergencyAffordanceService(Context context) {
+        super(context);
+        mContext = context;
+        int[] numbers = context.getResources().getIntArray(
+                com.android.internal.R.array.config_emergency_mcc_codes);
+        mEmergencyCallMccNumbers = new ArrayList<>(numbers.length);
+        for (int i = 0; i < numbers.length; i++) {
+            mEmergencyCallMccNumbers.add(numbers[i]);
+        }
+    }
+
+    private void updateEmergencyAffordanceNeeded() {
+        synchronized (mLock) {
+            mEmergencyAffordanceNeeded = mSimNeedsEmergencyAffordance ||
+                    mNetworkNeedsEmergencyAffordance;
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    Settings.Global.EMERGENCY_AFFORDANCE_NEEDED,
+                    mEmergencyAffordanceNeeded ? 1 : 0);
+            if (mEmergencyAffordanceNeeded) {
+                stopScanning();
+            }
+        }
+    }
+
+    private void stopScanning() {
+        synchronized (mLock) {
+            mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+            mScansCompleted = 0;
+        }
+    }
+
+    private boolean isEmergencyAffordanceNeeded() {
+        synchronized (mLock) {
+            return mEmergencyAffordanceNeeded;
+        }
+    }
+
+    @Override
+    public void onStart() {
+    }
+
+    @Override
+    public void onBootPhase(int phase) {
+        if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+            mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+            mSubscriptionManager = SubscriptionManager.from(mContext);
+            HandlerThread thread = new HandlerThread(TAG);
+            thread.start();
+            mHandler = new MyHandler(thread.getLooper());
+            mHandler.obtainMessage(INITIALIZE_STATE).sendToTarget();
+            startScanning();
+            IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+            mContext.registerReceiver(mAirplaneModeReceiver, filter);
+            mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionChangedListener);
+        }
+    }
+
+    private void startScanning() {
+        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CELL_INFO
+                | PhoneStateListener.LISTEN_CELL_LOCATION);
+    }
+
+    /** Handler to do the heavier work on */
+    private class MyHandler extends Handler {
+
+        public MyHandler(Looper l) {
+            super(l);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case INITIALIZE_STATE:
+                    handleInitializeState();
+                    break;
+                case CELL_INFO_STATE_CHANGED:
+                    handleUpdateCellInfo();
+                    break;
+                case SUBSCRIPTION_CHANGED:
+                    handleUpdateSimSubscriptionInfo();
+                    break;
+            }
+        }
+    }
+
+    private void handleInitializeState() {
+        if (handleUpdateSimSubscriptionInfo()) {
+            return;
+        }
+        if (handleUpdateCellInfo()) {
+            return;
+        }
+        updateEmergencyAffordanceNeeded();
+    }
+
+    private boolean handleUpdateSimSubscriptionInfo() {
+        boolean neededBefore = simNeededAffordanceBefore();
+        boolean neededNow = neededBefore;
+        List<SubscriptionInfo> activeSubscriptionInfoList =
+                mSubscriptionManager.getActiveSubscriptionInfoList();
+        if (activeSubscriptionInfoList == null) {
+            return neededNow;
+        }
+        for (SubscriptionInfo info : activeSubscriptionInfoList) {
+            int mcc = info.getMcc();
+            if (mccRequiresEmergencyAffordance(mcc)) {
+                neededNow = true;
+                break;
+            } else if (mcc != 0 && mcc != Integer.MAX_VALUE){
+                // a Sim with a different mcc code was found
+                neededNow = false;
+            }
+            String simOperator  = mTelephonyManager.getSimOperator(info.getSubscriptionId());
+            mcc = 0;
+            if (simOperator != null && simOperator.length() >= 3) {
+                mcc = Integer.parseInt(simOperator.substring(0, 3));
+            }
+            if (mcc != 0) {
+                if (mccRequiresEmergencyAffordance(mcc)) {
+                    neededNow = true;
+                    break;
+                } else {
+                    // a Sim with a different mcc code was found
+                    neededNow = false;
+                }
+            }
+        }
+        if (neededNow != neededBefore) {
+            setSimNeedsEmergencyAffordance(neededNow);
+        }
+        return neededNow;
+    }
+
+    private void setSimNeedsEmergencyAffordance(boolean simNeedsEmergencyAffordance) {
+        mSimNeedsEmergencyAffordance = simNeedsEmergencyAffordance;
+        Settings.Global.putInt(mContext.getContentResolver(),
+                EMERGENCY_SIM_INSERTED_SETTING,
+                simNeedsEmergencyAffordance ? 1 : 0);
+        updateEmergencyAffordanceNeeded();
+    }
+
+    private boolean simNeededAffordanceBefore() {
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                "emergency_sim_inserted_before", 0) != 0;
+    }
+
+    private boolean handleUpdateCellInfo() {
+        List<CellInfo> cellInfos = mTelephonyManager.getAllCellInfo();
+        if (cellInfos == null) {
+            return false;
+        }
+        boolean stopScanningAfterScan = false;
+        for (CellInfo cellInfo : cellInfos) {
+            int mcc = 0;
+            if (cellInfo instanceof CellInfoGsm) {
+                mcc = ((CellInfoGsm) cellInfo).getCellIdentity().getMcc();
+            } else if (cellInfo instanceof CellInfoLte) {
+                mcc = ((CellInfoLte) cellInfo).getCellIdentity().getMcc();
+            } else if (cellInfo instanceof CellInfoWcdma) {
+                mcc = ((CellInfoWcdma) cellInfo).getCellIdentity().getMcc();
+            }
+            if (mccRequiresEmergencyAffordance(mcc)) {
+                setNetworkNeedsEmergencyAffordance(true);
+                return true;
+            } else if (mcc != 0 && mcc != Integer.MAX_VALUE) {
+                // we found an mcc that isn't in the list, abort
+                stopScanningAfterScan = true;
+            }
+        }
+        if (stopScanningAfterScan) {
+            stopScanning();
+        } else {
+            onCellScanFinishedUnsuccessful();
+        }
+        setNetworkNeedsEmergencyAffordance(false);
+        return false;
+    }
+
+    private void setNetworkNeedsEmergencyAffordance(boolean needsAffordance) {
+        synchronized (mLock) {
+            mNetworkNeedsEmergencyAffordance = needsAffordance;
+            updateEmergencyAffordanceNeeded();
+        }
+    }
+
+    private void onCellScanFinishedUnsuccessful() {
+        synchronized (mLock) {
+            mScansCompleted++;
+            if (mScansCompleted >= NUM_SCANS_UNTIL_ABORT) {
+                stopScanning();
+            }
+        }
+    }
+
+    private boolean mccRequiresEmergencyAffordance(int mcc) {
+        return mEmergencyCallMccNumbers.contains(mcc);
+    }
+}
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 73c8469..9523a1c 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -195,6 +195,7 @@
     public void binderDied() {
         Slog.v(TAG, "fingerprintd died");
         mDaemon = null;
+        mCurrentUserId = UserHandle.USER_CURRENT;
         handleError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
     }
 
@@ -1068,14 +1069,6 @@
                         mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */)
                                 .sendToTarget();
                     }
-                    @Override
-                    public void onUserSwitchComplete(int newUserId) throws RemoteException {
-                        // Ignore.
-                    }
-                    @Override
-                    public void onForegroundProfileSwitch(int newProfileId) {
-                        // Ignore.
-                    }
                 }, TAG);
         } catch (RemoteException e) {
             Slog.w(TAG, "Failed to listen for user switching event" ,e);
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 74095ac..87f4030 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -18,8 +18,8 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.os.Build;
 import android.os.LocaleList;
+import android.os.ShellCallback;
 import android.util.Log;
 import android.view.Display;
 import com.android.internal.inputmethod.InputMethodSubtypeHandle;
@@ -91,10 +91,8 @@
 import android.view.Surface;
 import android.view.ViewConfiguration;
 import android.view.WindowManagerPolicy;
-import android.view.inputmethod.InputMethod;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
-import android.widget.Toast;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -103,11 +101,8 @@
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -1739,8 +1734,9 @@
 
     @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out,
-            FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
-        (new Shell()).exec(this, in, out, err, args, resultReceiver);
+            FileDescriptor err, String[] args, ShellCallback callback,
+            ResultReceiver resultReceiver) {
+        (new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
     }
 
     public int onShellCommand(Shell shell, String cmd) {
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 9d93146..fe3a02d 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -44,9 +44,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -62,6 +60,7 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
+import android.os.ShellCallback;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -1718,9 +1717,9 @@
 
         @Override
         public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
-                String[] args, ResultReceiver resultReceiver) throws RemoteException {
+                String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
                 (new JobSchedulerShellCommand(JobSchedulerService.this)).exec(
-                        this, in, out, err, args, resultReceiver);
+                        this, in, out, err, args, callback, resultReceiver);
         }
     };
 
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 8303d5c..27f397d 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -307,10 +307,24 @@
         this.service = IJobService.Stub.asInterface(service);
         final PowerManager pm =
                 (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, runningJob.getTag());
-        mWakeLock.setWorkSource(new WorkSource(runningJob.getSourceUid()));
-        mWakeLock.setReferenceCounted(false);
-        mWakeLock.acquire();
+        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+                runningJob.getTag());
+        wl.setWorkSource(new WorkSource(runningJob.getSourceUid()));
+        wl.setReferenceCounted(false);
+        wl.acquire();
+        synchronized (mLock) {
+            // We use a new wakelock instance per job.  In rare cases there is a race between
+            // teardown following job completion/cancellation and new job service spin-up
+            // such that if we simply assign mWakeLock to be the new instance, we orphan
+            // the currently-live lock instead of cleanly replacing it.  Watch for this and
+            // explicitly fast-forward the release if we're in that situation.
+            if (mWakeLock != null) {
+                Slog.w(TAG, "Bound new job " + runningJob + " but live wakelock " + mWakeLock
+                        + " tag=" + mWakeLock.getTag());
+                mWakeLock.release();
+            }
+            mWakeLock = wl;
+        }
         mCallbackHandler.obtainMessage(MSG_SERVICE_BOUND).sendToTarget();
     }
 
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 2fd9fe1..547cc51 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -123,7 +123,6 @@
 import android.net.NetworkIdentity;
 import android.net.NetworkInfo;
 import android.net.NetworkPolicy;
-import android.net.NetworkPolicyManager;
 import android.net.NetworkQuotaInfo;
 import android.net.NetworkState;
 import android.net.NetworkTemplate;
@@ -144,6 +143,7 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
+import android.os.ShellCallback;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -292,6 +292,7 @@
     private static final int MSG_REMOVE_INTERFACE_QUOTA = 11;
     private static final int MSG_POLICIES_CHANGED = 13;
     private static final int MSG_SET_FIREWALL_RULES = 14;
+    private static final int MSG_RESET_FIREWALL_RULES_BY_UID = 15;
 
     private final Context mContext;
     private final IActivityManager mActivityManager;
@@ -737,7 +738,7 @@
                 // global background data policy
                 if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
                 synchronized (mUidRulesFirstLock) {
-                    updateRestrictionRulesForUidUL(uid, false);
+                    updateRestrictionRulesForUidUL(uid);
                 }
             }
         }
@@ -754,11 +755,7 @@
             // remove any policy and update rules to clean up
             if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
             synchronized (mUidRulesFirstLock) {
-                mUidRules.delete(uid);
-                mUidPolicy.delete(uid);
-                // TODO: rather than passing onUidDeleted=true, it would be clearner to have a
-                // method that reset all firewall rules for an UID....
-                updateRestrictionRulesForUidUL(uid, true);
+                onUidDeletedUL(uid);
                 synchronized (mNetworkPoliciesSecondLock) {
                     writePolicyAL();
                 }
@@ -2389,9 +2386,9 @@
 
     @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
-            String[] args, ResultReceiver resultReceiver) throws RemoteException {
+            String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
         (new NetworkPolicyManagerShellCommand(mContext, this)).exec(
-                this, in, out, err, args, resultReceiver);
+                this, in, out, err, args, callback, resultReceiver);
     }
 
     @Override
@@ -2811,6 +2808,24 @@
     }
 
     /**
+     * Clears all state - internal and external - associated with an UID.
+     */
+    private void onUidDeletedUL(int uid) {
+        // First cleanup in-memory state synchronously...
+        mUidRules.delete(uid);
+        mUidPolicy.delete(uid);
+        mUidFirewallStandbyRules.delete(uid);
+        mUidFirewallDozableRules.delete(uid);
+        mUidFirewallPowerSaveRules.delete(uid);
+        mPowerSaveWhitelistExceptIdleAppIds.delete(uid);
+        mPowerSaveWhitelistAppIds.delete(uid);
+        mPowerSaveTempWhitelistAppIds.delete(uid);
+
+        // ...then update iptables asynchronously.
+        mHandler.obtainMessage(MSG_RESET_FIREWALL_RULES_BY_UID, uid, 0).sendToTarget();
+    }
+
+    /**
      * Applies network rules to bandwidth and firewall controllers based on uid policy.
      *
      * <p>There are currently 4 types of restriction rules:
@@ -2823,7 +2838,7 @@
      *
      * <p>This method changes both the external firewall rules and the internal state.
      */
-    private void updateRestrictionRulesForUidUL(int uid, boolean onUidDeleted) {
+    private void updateRestrictionRulesForUidUL(int uid) {
         // Methods below only changes the firewall rules for the power-related modes.
         updateRuleForDeviceIdleUL(uid);
         updateRuleForAppIdleUL(uid);
@@ -2833,7 +2848,7 @@
         updateRulesForPowerRestrictionsUL(uid);
 
         // Update firewall and internal rules for Data Saver Mode.
-        updateRulesForDataUsageRestrictionsUL(uid, onUidDeleted);
+        updateRulesForDataUsageRestrictionsUL(uid);
     }
 
     /**
@@ -2876,15 +2891,7 @@
      *
      */
     private void updateRulesForDataUsageRestrictionsUL(int uid) {
-        updateRulesForDataUsageRestrictionsUL(uid, false);
-    }
-
-    /**
-     * Overloaded version of {@link #updateRulesForDataUsageRestrictionsUL(int)} called when an
-     * app is removed - it ignores the UID validity check.
-     */
-    private void updateRulesForDataUsageRestrictionsUL(int uid, boolean onUidDeleted) {
-        if (!onUidDeleted && !isUidValidForWhitelistRules(uid)) {
+        if (!isUidValidForWhitelistRules(uid)) {
             if (LOGD) Slog.d(TAG, "no need to update restrict data rules for uid " + uid);
             return;
         }
@@ -3265,6 +3272,10 @@
                     }
                     return true;
                 }
+                case MSG_RESET_FIREWALL_RULES_BY_UID: {
+                    resetUidFirewallRules(msg.arg1);
+                    return true;
+                }
                 default: {
                     return false;
                 }
@@ -3417,6 +3428,24 @@
         }
     }
 
+    /**
+     * Resets all firewall rules associated with an UID.
+     */
+    private void resetUidFirewallRules(int uid) {
+        try {
+            mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_DOZABLE, uid, FIREWALL_RULE_DEFAULT);
+            mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
+            mNetworkManager
+                    .setFirewallUidRule(FIREWALL_CHAIN_POWERSAVE, uid, FIREWALL_RULE_DEFAULT);
+            mNetworkManager.setUidMeteredNetworkWhitelist(uid, false);
+            mNetworkManager.setUidMeteredNetworkBlacklist(uid, false);
+        } catch (IllegalStateException e) {
+            Log.wtf(TAG, "problem resetting firewall uid rules for " + uid, e);
+        } catch (RemoteException e) {
+            // ignored; service lives in system_server
+        }
+    }
+
     private long getTotalBytes(NetworkTemplate template, long start, long end) {
         try {
             return mNetworkStats.getNetworkTotalBytes(template, start, end);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
index 4ca69dc..8ced1c2 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
@@ -333,9 +333,11 @@
                 System.arraycopy(policies, 0, newPolicies, 0, policies.length);
                 newPolicies[newPolicies.length - 1] = policy;
                 mInterface.setNetworkPolicies(newPolicies);
+                return 0;
             }
         }
-        return 0;
+        pw.print("Error: didn't find network with SSID "); pw.println(id);
+        return -1;
     }
 
     private List<NetworkPolicy> getWifiPolicies() throws RemoteException {
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 689917c..f777aae 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -28,6 +28,7 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
+import android.os.ShellCallback;
 import android.os.storage.StorageManager;
 import android.util.Log;
 import android.util.Slog;
@@ -107,9 +108,9 @@
 
     @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
-            String[] args, ResultReceiver resultReceiver) throws RemoteException {
+            String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
         (new OtaDexoptShellCommand(this)).exec(
-                this, in, out, err, args, resultReceiver);
+                this, in, out, err, args, callback, resultReceiver);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2d7b70d..13428b2 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -109,6 +109,7 @@
 import android.app.backup.IBackupManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.IIntentReceiver;
 import android.content.Intent;
@@ -184,6 +185,7 @@
 import android.os.ResultReceiver;
 import android.os.SELinux;
 import android.os.ServiceManager;
+import android.os.ShellCallback;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.Trace;
@@ -4645,6 +4647,7 @@
 
     @Override
     public String[] getPackagesForUid(int uid) {
+        final int userId = UserHandle.getUserId(uid);
         uid = UserHandle.getAppId(uid);
         // reader
         synchronized (mPackages) {
@@ -4652,9 +4655,16 @@
             if (obj instanceof SharedUserSetting) {
                 final SharedUserSetting sus = (SharedUserSetting) obj;
                 final int N = sus.packages.size();
-                final String[] res = new String[N];
-                for (int i = 0; i < N; i++) {
-                    res[i] = sus.packages.valueAt(i).name;
+                String[] res = new String[N];
+                final Iterator<PackageSetting> it = sus.packages.iterator();
+                int i = 0;
+                while (it.hasNext()) {
+                    PackageSetting ps = it.next();
+                    if (ps.getInstalled(userId)) {
+                        res[i++] = ps.name;
+                    } else {
+                        res = ArrayUtils.removeElement(String.class, res, res[i]);
+                    }
                 }
                 return res;
             } else if (obj instanceof PackageSetting) {
@@ -4826,7 +4836,12 @@
         if (!mSystemReady) {
             return true;
         }
-        return Secure.getInt(mContext.getContentResolver(), Secure.WEB_ACTION_ENABLED, 1) == 0;
+        // we can't get a content resolver until the system is ready; these checks must happen last
+        final ContentResolver resolver = mContext.getContentResolver();
+        if (Global.getInt(resolver, Global.ENABLE_EPHEMERAL_FEATURE, 1) == 0) {
+            return true;
+        }
+        return Secure.getInt(resolver, Secure.WEB_ACTION_ENABLED, 1) == 0;
     }
 
     private boolean isEphemeralAllowed(
@@ -18383,9 +18398,10 @@
 
     @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out,
-            FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
+            FileDescriptor err, String[] args, ShellCallback callback,
+            ResultReceiver resultReceiver) {
         (new PackageManagerShellCommand(this)).exec(
-                this, in, out, err, args, resultReceiver);
+                this, in, out, err, args, callback, resultReceiver);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 61374f3..1d3471a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -1160,14 +1160,15 @@
     private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
             boolean logSuccess) throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
-        if ("-".equals(inPath)) {
-            inPath = null;
-        } else if (inPath != null) {
-            final File file = new File(inPath);
-            if (file.isFile()) {
-                sizeBytes = file.length();
-            }
+        if (sizeBytes <= 0) {
+            pw.println("Error: must specify a APK size");
+            return 1;
         }
+        if (inPath != null && !"-".equals(inPath)) {
+            pw.println("Error: APK content must be streamed");
+            return 1;
+        }
+        inPath = null;
 
         final SessionInfo info = mInterface.getPackageInstaller().getSessionInfo(sessionId);
 
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 13f558e..19bf751 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -67,6 +67,7 @@
 import android.os.ResultReceiver;
 import android.os.SELinux;
 import android.os.ServiceManager;
+import android.os.ShellCallback;
 import android.os.ShellCommand;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -3366,13 +3367,14 @@
 
     @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
-            String[] args, ResultReceiver resultReceiver) throws RemoteException {
+            String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
 
         enforceShell();
 
         final long token = injectClearCallingIdentity();
         try {
-            final int status = (new MyShellCommand()).exec(this, in, out, err, args, resultReceiver);
+            final int status = (new MyShellCommand()).exec(this, in, out, err, args, callback,
+                    resultReceiver);
             resultReceiver.send(status, null);
         } finally {
             injectRestoreCallingIdentity(token);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index c1cb032..c6b09d1 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -62,6 +62,7 @@
 import android.os.ResultReceiver;
 import android.os.SELinux;
 import android.os.ServiceManager;
+import android.os.ShellCallback;
 import android.os.ShellCommand;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -3209,8 +3210,9 @@
 
     @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out,
-            FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
-        (new Shell()).exec(this, in, out, err, args, resultReceiver);
+            FileDescriptor err, String[] args, ShellCallback callback,
+            ResultReceiver resultReceiver) {
+        (new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
     }
 
     int onShellCommand(Shell shell, String cmd) {
diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java
index bb91f76..a8bd4d2 100644
--- a/services/core/java/com/android/server/policy/GlobalActions.java
+++ b/services/core/java/com/android/server/policy/GlobalActions.java
@@ -20,6 +20,7 @@
 import com.android.internal.app.AlertController.AlertParams;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.policy.EmergencyAffordanceManager;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.R;
@@ -27,7 +28,6 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
-import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -125,6 +125,7 @@
     private boolean mHasTelephony;
     private boolean mHasVibrator;
     private final boolean mShowSilentToggle;
+    private final EmergencyAffordanceManager mEmergencyAffordanceManager;
 
     /**
      * @param context everything needs a context :(
@@ -159,6 +160,8 @@
 
         mShowSilentToggle = SHOW_SILENT_TOGGLE && !mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_useFixedVolume);
+
+        mEmergencyAffordanceManager = new EmergencyAffordanceManager(context);
     }
 
     /**
@@ -308,6 +311,10 @@
             addedKeys.add(actionKey);
         }
 
+        if (mEmergencyAffordanceManager.needsEmergencyAffordance()) {
+            mItems.add(getEmergencyAction());
+        }
+
         mAdapter = new MyAdapter();
 
         AlertParams params = new AlertParams(mContext);
@@ -493,6 +500,26 @@
         };
     }
 
+    private Action getEmergencyAction() {
+        return new SinglePressAction(com.android.internal.R.drawable.emergency_icon,
+                R.string.global_action_emergency) {
+            @Override
+            public void onPress() {
+                mEmergencyAffordanceManager.performEmergencyCall();
+            }
+
+            @Override
+            public boolean showDuringKeyguard() {
+                return true;
+            }
+
+            @Override
+            public boolean showBeforeProvisioning() {
+                return true;
+            }
+        };
+    }
+
     private Action getAssistAction() {
         return new SinglePressAction(com.android.internal.R.drawable.ic_action_assist_focused,
                 R.string.global_action_assist) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b555938..2f25971 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1373,8 +1373,13 @@
             case LONG_PRESS_BACK_NOTHING:
                 break;
             case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST:
-                Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST);
-                startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
+                final boolean keyguardActive = mKeyguardDelegate == null
+                        ? false
+                        : mKeyguardDelegate.isShowing();
+                if (!keyguardActive) {
+                    Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST);
+                    startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
+                }
                 break;
         }
     }
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 3f58c95..7576cddad 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -810,9 +810,10 @@
     }
 
     private void updateLowPowerModeLocked() {
-        if (mIsPowered && mLowPowerModeSetting) {
+        if ((mIsPowered || !mBatteryLevelLow && !mBootCompleted) && mLowPowerModeSetting) {
             if (DEBUG_SPEW) {
-                Slog.d(TAG, "updateLowPowerModeLocked: powered, turning setting off");
+                Slog.d(TAG, "updateLowPowerModeLocked: powered or booting with sufficient battery,"
+                        + " turning setting off");
             }
             // Turn setting off if powered
             Settings.Global.putInt(mContext.getContentResolver(),
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 1dbc6d9..badee82 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -717,6 +717,14 @@
         }
         if (!done[0]) {
             Log.w(TAG, "Timed out waiting for uncrypt.");
+            final int uncryptTimeoutError = 100;
+            String timeoutMessage = String.format("uncrypt_time: %d\n" + "uncrypt_error: %d\n",
+                    MAX_UNCRYPT_WAIT_TIME / 1000, uncryptTimeoutError);
+            try {
+                FileUtils.stringToFile(RecoverySystem.UNCRYPT_STATUS_FILE, timeoutMessage);
+            } catch (IOException e) {
+                Log.e(TAG, "Failed to write timeout message to uncrypt status", e);
+            }
         }
     }
 }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 552803f..7b7db0e 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -28,23 +28,21 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
+import android.os.ShellCallback;
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Slog;
-import android.view.KeyEvent;
 
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.statusbar.StatusBarIcon;
-import com.android.internal.util.FastPrintWriter;
 import com.android.server.LocalServices;
 import com.android.server.notification.NotificationDelegate;
 import com.android.server.wm.WindowManagerService;
 
 import java.io.FileDescriptor;
-import java.io.FileOutputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
@@ -849,9 +847,9 @@
 
     @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
-            String[] args, ResultReceiver resultReceiver) throws RemoteException {
+            String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
         (new StatusBarShellCommand(this)).exec(
-                this, in, out, err, args, resultReceiver);
+                this, in, out, err, args, callback, resultReceiver);
     }
 
     // ================================================================================
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 3b20fb1..5514551 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -27,10 +27,10 @@
 import android.app.ActivityManagerNative;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
-import android.app.IUserSwitchObserver;
 import android.app.IWallpaperManager;
 import android.app.IWallpaperManagerCallback;
 import android.app.PendingIntent;
+import android.app.UserSwitchObserver;
 import android.app.WallpaperInfo;
 import android.app.WallpaperManager;
 import android.app.admin.DevicePolicyManager;
@@ -933,20 +933,11 @@
 
         try {
             ActivityManagerNative.getDefault().registerUserSwitchObserver(
-                    new IUserSwitchObserver.Stub() {
+                    new UserSwitchObserver() {
                         @Override
                         public void onUserSwitching(int newUserId, IRemoteCallback reply) {
                             switchUser(newUserId, reply);
                         }
-
-                        @Override
-                        public void onUserSwitchComplete(int newUserId) throws RemoteException {
-                        }
-
-                        @Override
-                        public void onForegroundProfileSwitch(int newProfileId) {
-                            // Ignore.
-                        }
                     }, TAG);
         } catch (RemoteException e) {
             e.rethrowAsRuntimeException();
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index 846169c..43cdf59 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -25,10 +25,10 @@
 import android.os.PatternMatcher;
 import android.os.Process;
 import android.os.ResultReceiver;
+import android.os.ShellCallback;
 import android.os.UserHandle;
 import android.util.Slog;
 import android.webkit.IWebViewUpdateService;
-import android.webkit.WebViewFactory;
 import android.webkit.WebViewProviderInfo;
 import android.webkit.WebViewProviderResponse;
 
@@ -140,9 +140,10 @@
 
         @Override
         public void onShellCommand(FileDescriptor in, FileDescriptor out,
-                FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
+                FileDescriptor err, String[] args, ShellCallback callback,
+                ResultReceiver resultReceiver) {
             (new WebViewUpdateServiceShellCommand(this)).exec(
-                    this, in, out, err, args, resultReceiver);
+                    this, in, out, err, args, callback, resultReceiver);
         }
 
 
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 4d12ba9..9c5392e 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -429,7 +429,7 @@
         for (int i = 0; i < displayList.size(); i++) {
             final DisplayContent displayContent = displayList.get(i);
             mService.mLayersController.assignLayersLocked(displayContent.getWindowList());
-            displayContent.layoutNeeded = true;
+            displayContent.setLayoutNeeded();
         }
     }
 
@@ -729,9 +729,7 @@
 
         if (mTask.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
             // We didn't call prepareFreezingBounds on the task, so use the current value.
-            final Configuration config = new Configuration(mService.mGlobalConfiguration);
-            config.updateFrom(mTask.mOverrideConfig);
-            mFrozenMergedConfig.offer(config);
+            mFrozenMergedConfig.offer(new Configuration(mTask.getConfiguration()));
         } else {
             mFrozenMergedConfig.offer(new Configuration(mTask.mPreparedFrozenMergedConfig));
         }
@@ -957,7 +955,7 @@
 
             mService.updateFocusedWindowLocked(
                     UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
-            mService.getDefaultDisplayContentLocked().layoutNeeded = true;
+            mService.getDefaultDisplayContentLocked().setLayoutNeeded();
             mService.mWindowPlacerLocked.performSurfacePlacement();
             Binder.restoreCallingIdentity(origId);
             return true;
@@ -1055,7 +1053,7 @@
 
     @Override
     void updateAllDrawn(int displayId) {
-        final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
+        final DisplayContent displayContent = mService.mRoot.getDisplayContentOrCreate(displayId);
 
         if (!allDrawn) {
             final int numInteresting = numInterestingWindows;
@@ -1065,7 +1063,7 @@
                 allDrawn = true;
                 // Force an additional layout pass where
                 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
-                displayContent.layoutNeeded = true;
+                displayContent.setLayoutNeeded();
                 mService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
             }
         }
@@ -1076,7 +1074,7 @@
                         + " interesting=" + numInteresting
                         + " drawn=" + numDrawnWindowsExcludingSaved);
                 allDrawnExcludingSaved = true;
-                displayContent.layoutNeeded = true;
+                displayContent.setLayoutNeeded();
                 if (isAnimatingInvisibleWithSavedSurface()
                         && !mService.mFinishedEarlyAnim.contains(this)) {
                     mService.mFinishedEarlyAnim.add(this);
@@ -1100,12 +1098,16 @@
         }
     }
 
+    int rebuildWindowListUnchecked(DisplayContent dc, int addIndex) {
+        return super.rebuildWindowList(dc, addIndex);
+    }
+
     @Override
     int rebuildWindowList(DisplayContent dc, int addIndex) {
         if (mIsExiting && !waitingForReplacement()) {
             return addIndex;
         }
-        return super.rebuildWindowList(dc, addIndex);
+        return rebuildWindowListUnchecked(dc, addIndex);
     }
 
     @Override
@@ -1187,6 +1189,6 @@
             sb.append(" token="); sb.append(token); sb.append('}');
             stringName = sb.toString();
         }
-        return stringName;
+        return stringName + ((mIsExiting) ? " mIsExiting=" : "");
     }
 }
diff --git a/services/core/java/com/android/server/wm/DimLayerController.java b/services/core/java/com/android/server/wm/DimLayerController.java
index 7f97c46..da2c6a7 100644
--- a/services/core/java/com/android/server/wm/DimLayerController.java
+++ b/services/core/java/com/android/server/wm/DimLayerController.java
@@ -256,7 +256,7 @@
                 // on whether a dim layer is showing or not.
                 if (targetAlpha == 0) {
                     mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
-                    mDisplayContent.layoutNeeded = true;
+                    mDisplayContent.setLayoutNeeded();
                 }
             }
         } else if (state.dimLayer.getLayer() != dimLayer) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 4fc3ab0..34a7390 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -23,6 +23,9 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.view.WindowManager.DOCKED_BOTTOM;
+import static android.view.WindowManager.DOCKED_INVALID;
+import static android.view.WindowManager.DOCKED_TOP;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -32,8 +35,10 @@
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -42,6 +47,7 @@
 
 import android.annotation.NonNull;
 import android.app.ActivityManager.StackId;
+import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.graphics.Region.Op;
@@ -53,7 +59,6 @@
 import android.view.DisplayInfo;
 import android.view.IWindow;
 import android.view.Surface;
-import android.view.animation.Animation;
 import com.android.internal.util.FastPrintWriter;
 
 import java.io.FileDescriptor;
@@ -73,7 +78,7 @@
  * IMPORTANT: No method from this class should ever be used without holding
  * WindowManagerService.mWindowMap.
  */
-class DisplayContent {
+class DisplayContent extends WindowContainer<TaskStack> {
 
     /** Unique identifier of this stack. */
     private final int mDisplayId;
@@ -97,17 +102,13 @@
     private Rect mContentRect = new Rect();
 
     // Accessed directly by all users.
-    boolean layoutNeeded;
+    private boolean mLayoutNeeded;
     int pendingLayoutChanges;
     final boolean isDefaultDisplay;
 
     /** Window tokens that are in the process of exiting, but still on screen for animations. */
     final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
 
-    /** Array containing all TaskStacks on this display.  Array
-     * is stored in display order with the current bottom stack at 0. */
-    private final ArrayList<TaskStack> mStacks = new ArrayList<>();
-
     /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack
      * (except a future lockscreen TaskStack) moves to the top. */
     private TaskStack mHomeStack = null;
@@ -185,18 +186,14 @@
     /**
      * Returns true if the specified UID has access to this display.
      */
-    public boolean hasAccess(int uid) {
+    boolean hasAccess(int uid) {
         return mDisplay.hasAccess(uid);
     }
 
-    public boolean isPrivate() {
+    boolean isPrivate() {
         return (mDisplay.getFlags() & Display.FLAG_PRIVATE) != 0;
     }
 
-    ArrayList<TaskStack> getStacks() {
-        return mStacks;
-    }
-
     TaskStack getHomeStack() {
         if (mHomeStack == null && mDisplayId == Display.DEFAULT_DISPLAY) {
             Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this);
@@ -205,8 +202,8 @@
     }
 
     TaskStack getStackById(int stackId) {
-        for (int i = mStacks.size() - 1; i >= 0; --i) {
-            final TaskStack stack = mStacks.get(i);
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mChildren.get(i);
             if (stack.mStackId == stackId) {
                 return stack;
             }
@@ -214,57 +211,61 @@
         return null;
     }
 
-    /** Callback used to notify about configuration changes. */
-    void onConfigurationChanged(@NonNull List<Integer> changedStackList) {
+    @Override
+    void onConfigurationChanged(Configuration newParentConfig) {
+        super.onConfigurationChanged(newParentConfig);
+
         // The display size information is heavily dependent on the resources in the current
         // configuration, so we need to reconfigure it every time the configuration changes.
         // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh...
         mService.reconfigureDisplayLocked(this);
 
         getDockedDividerController().onConfigurationChanged();
+    }
 
-        for (int i = 0; i < mStacks.size(); i++) {
-            final TaskStack stack = mStacks.get(i);
-            if (stack.onConfigurationChanged()) {
+    /**
+     * Callback used to trigger bounds update after configuration change and get ids of stacks whose
+     * bounds were updated.
+     */
+    void updateStackBoundsAfterConfigChange(@NonNull List<Integer> changedStackList) {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mChildren.get(i);
+            if (stack.updateBoundsAfterConfigChange()) {
                 changedStackList.add(stack.mStackId);
             }
         }
     }
 
     void checkAppWindowsReadyToShow() {
-        for (int i = mStacks.size() - 1; i >= 0; --i) {
-            final TaskStack stack = mStacks.get(i);
-            stack.checkAppWindowsReadyToShow(mDisplayId);
-        }
+        super.checkAppWindowsReadyToShow(mDisplayId);
     }
 
     void updateAllDrawn() {
-        for (int i = mStacks.size() - 1; i >= 0; --i) {
-            final TaskStack stack = mStacks.get(i);
-            stack.updateAllDrawn(mDisplayId);
-        }
+        super.updateAllDrawn(mDisplayId);
     }
 
     void stepAppWindowsAnimation(long currentTime) {
-        for (int i = mStacks.size() - 1; i >= 0; --i) {
-            final TaskStack stack = mStacks.get(i);
-            stack.stepAppWindowsAnimation(currentTime, mDisplayId);
-        }
+        super.stepAppWindowsAnimation(currentTime, mDisplayId);
     }
 
-    void onAppTransitionDone() {
-        for (int i = mStacks.size() - 1; i >= 0; --i) {
-            final TaskStack stack = mStacks.get(i);
-            stack.onAppTransitionDone();
-        }
+    @Override
+    boolean fillsParent() {
+        return true;
+    }
 
+    @Override
+    boolean isVisible() {
+        return true;
+    }
+
+    @Override
+    void onAppTransitionDone() {
+        super.onAppTransitionDone();
         rebuildAppWindowList();
     }
 
+    @Override
     int getOrientation() {
-        // TODO: Most of the logic here can be removed once this class is converted to use
-        // WindowContainer which has an abstract implementation of getOrientation that
-        // should cover this.
         if (mService.isStackVisibleLocked(DOCKED_STACK_ID)
                 || mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) {
             // Apps and their containers are not allowed to specify an orientation while the docked
@@ -280,23 +281,11 @@
             return SCREEN_ORIENTATION_UNSPECIFIED;
         }
 
-        for (int i = mStacks.size() - 1; i >= 0; --i) {
-            final TaskStack stack = mStacks.get(i);
-            if (!stack.isVisible()) {
-                continue;
-            }
-
-            final int orientation = stack.getOrientation();
-
-            if (orientation == SCREEN_ORIENTATION_BEHIND) {
-                continue;
-            }
-
-            if (orientation != SCREEN_ORIENTATION_UNSET) {
-                if (stack.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
-                    return orientation;
-                }
-            }
+        final int orientation = super.getOrientation();
+        if (orientation != SCREEN_ORIENTATION_UNSET && orientation != SCREEN_ORIENTATION_BEHIND) {
+            if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
+                    "App is requesting an orientation, return " + orientation);
+            return orientation;
         }
 
         if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
@@ -309,8 +298,8 @@
     void updateDisplayInfo() {
         mDisplay.getDisplayInfo(mDisplayInfo);
         mDisplay.getMetrics(mDisplayMetrics);
-        for (int i = mStacks.size() - 1; i >= 0; --i) {
-            mStacks.get(i).updateDisplayInfo(null);
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            mChildren.get(i).updateDisplayInfo(null);
         }
     }
 
@@ -356,12 +345,7 @@
             }
             mHomeStack = stack;
         }
-        if (onTop) {
-            mStacks.add(stack);
-        } else {
-            mStacks.add(0, stack);
-        }
-        layoutNeeded = true;
+        addChild(stack, onTop);
     }
 
     void moveStack(TaskStack stack, boolean toTop) {
@@ -371,11 +355,15 @@
             return;
         }
 
-        if (!mStacks.remove(stack)) {
+        if (!mChildren.contains(stack)) {
             Slog.wtf(TAG_WM, "moving stack that was not added: " + stack, new Throwable());
         }
+        removeChild(stack);
+        addChild(stack, toTop);
+    }
 
-        int addIndex = toTop ? mStacks.size() : 0;
+    private void addChild(TaskStack stack, boolean toTop) {
+        int addIndex = toTop ? mChildren.size() : 0;
 
         if (toTop
                 && mService.isStackVisibleLocked(PINNED_STACK_ID)
@@ -383,30 +371,13 @@
             // The pinned stack is always the top most stack (always-on-top) when it is visible.
             // So, stack is moved just below the pinned stack.
             addIndex--;
-            TaskStack topStack = mStacks.get(addIndex);
+            TaskStack topStack = mChildren.get(addIndex);
             if (topStack.mStackId != PINNED_STACK_ID) {
-                throw new IllegalStateException("Pinned stack isn't top stack??? " + mStacks);
+                throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
             }
         }
-        mStacks.add(addIndex, stack);
-    }
-
-    // TODO: Don't forget to switch to WC.removeChild
-    void detachChild(TaskStack stack) {
-        detachStack(stack);
-        if (stack.detachFromDisplay()) {
-            mService.mWindowPlacerLocked.requestTraversal();
-        }
-        if (stack.mStackId == DOCKED_STACK_ID) {
-            mService.getDefaultDisplayContentLocked().mDividerControllerLocked
-                    .notifyDockedStackExistsChanged(false);
-        }
-    }
-
-    // TODO: See about removing this by untangling the use case in WMS.attachStack()
-    void detachStack(TaskStack stack) {
-        mDimLayerController.removeDimLayerUser(stack);
-        mStacks.remove(stack);
+        addChild(stack, addIndex);
+        setLayoutNeeded();
     }
 
     /**
@@ -418,8 +389,8 @@
     }
 
     int taskIdFromPoint(int x, int y) {
-        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
-            final TaskStack stack = mStacks.get(stackNdx);
+        for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) {
+            final TaskStack stack = mChildren.get(stackNdx);
             final int taskId = stack.taskIdFromPoint(x, y);
             if (taskId != -1) {
                 return taskId;
@@ -435,8 +406,8 @@
     Task findTaskForResizePoint(int x, int y) {
         final int delta = mService.dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
         mTmpTaskForResizePointSearchResult.reset();
-        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
-            TaskStack stack = mStacks.get(stackNdx);
+        for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) {
+            TaskStack stack = mChildren.get(stackNdx);
             if (!StackId.isTaskResizeAllowed(stack.mStackId)) {
                 return null;
             }
@@ -453,8 +424,8 @@
         mTouchExcludeRegion.set(mBaseDisplayRect);
         final int delta = mService.dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
         mTmpRect2.setEmpty();
-        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
-            final TaskStack stack = mStacks.get(stackNdx);
+        for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) {
+            final TaskStack stack = mChildren.get(stackNdx);
             stack.setTouchExcludeRegion(
                     focusedTask, delta, mTouchExcludeRegion, mContentRect, mTmpRect2);
         }
@@ -487,7 +458,7 @@
         }
     }
 
-    void switchUserStacks() {
+    void switchUser() {
         final WindowList windows = getWindowList();
         for (int i = 0; i < windows.size(); i++) {
             final WindowState win = windows.get(i);
@@ -498,16 +469,16 @@
             }
         }
 
-        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
-            mStacks.get(stackNdx).switchUser();
+        for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) {
+            mChildren.get(stackNdx).switchUser();
         }
 
         rebuildAppWindowList();
     }
 
     void resetAnimationBackgroundAnimator() {
-        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
-            mStacks.get(stackNdx).resetAnimationBackgroundAnimator();
+        for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) {
+            mChildren.get(stackNdx).resetAnimationBackgroundAnimator();
         }
     }
 
@@ -527,37 +498,141 @@
         mDimLayerController.stopDimmingIfNeeded();
     }
 
-    void close() {
-        mDimLayerController.close();
-        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
-            mStacks.get(stackNdx).close();
+    @Override
+    void removeIfPossible() {
+        if (isAnimating()) {
+            mDeferredRemoval = true;
+            return;
         }
+        removeImmediately();
     }
 
-    boolean isAnimating() {
-        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
-            final TaskStack stack = mStacks.get(stackNdx);
-            if (stack.isAnimating()) {
-                return true;
-            }
+    @Override
+    void removeImmediately() {
+        super.removeImmediately();
+        if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
+        mDimLayerController.close();
+        if (mDisplayId == Display.DEFAULT_DISPLAY) {
+            mService.unregisterPointerEventListener(mTapDetector);
+            mService.unregisterPointerEventListener(mService.mMousePositionTracker);
         }
-        return false;
     }
 
     /** Returns true if a removal action is still being deferred. */
+    @Override
     boolean checkCompleteDeferredRemoval() {
-        boolean stillDeferringRemoval = false;
-        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
-            final TaskStack stack = mStacks.get(stackNdx);
-            stillDeferringRemoval |= stack.checkCompleteDeferredRemoval();
-        }
+        final boolean stillDeferringRemoval = super.checkCompleteDeferredRemoval();
+
         if (!stillDeferringRemoval && mDeferredRemoval) {
+            removeImmediately();
             mService.onDisplayRemoved(mDisplayId);
             return false;
         }
         return true;
     }
 
+    boolean animateForIme(float interpolatedValue, float animationTarget,
+            float dividerAnimationTarget) {
+        boolean updated = false;
+
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mChildren.get(i);
+            if (stack == null || !stack.isAdjustedForIme()) {
+                continue;
+            }
+
+            if (interpolatedValue >= 1f && animationTarget == 0f && dividerAnimationTarget == 0f) {
+                stack.resetAdjustedForIme(true /* adjustBoundsNow */);
+                updated = true;
+            } else {
+                mDividerControllerLocked.mLastAnimationProgress =
+                        mDividerControllerLocked.getInterpolatedAnimationValue(interpolatedValue);
+                mDividerControllerLocked.mLastDividerProgress =
+                        mDividerControllerLocked.getInterpolatedDividerValue(interpolatedValue);
+                updated |= stack.updateAdjustForIme(
+                        mDividerControllerLocked.mLastAnimationProgress,
+                        mDividerControllerLocked.mLastDividerProgress,
+                        false /* force */);
+            }
+            if (interpolatedValue >= 1f) {
+                stack.endImeAdjustAnimation();
+            }
+        }
+
+        return updated;
+    }
+
+    boolean clearImeAdjustAnimation() {
+        boolean changed = false;
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mChildren.get(i);
+            if (stack != null && stack.isAdjustedForIme()) {
+                stack.resetAdjustedForIme(true /* adjustBoundsNow */);
+                changed  = true;
+            }
+        }
+        return changed;
+    }
+
+    void beginImeAdjustAnimation() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mChildren.get(i);
+            if (stack.isVisible() && stack.isAdjustedForIme()) {
+                stack.beginImeAdjustAnimation();
+            }
+        }
+    }
+
+    void adjustForImeIfNeeded() {
+        final WindowState imeWin = mService.mInputMethodWindow;
+        final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
+                && !mDividerControllerLocked.isImeHideRequested();
+        final boolean dockVisible = mService.isStackVisibleLocked(DOCKED_STACK_ID);
+        final TaskStack imeTargetStack = mService.getImeFocusStackLocked();
+        final int imeDockSide = (dockVisible && imeTargetStack != null) ?
+                imeTargetStack.getDockSide() : DOCKED_INVALID;
+        final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
+        final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM);
+        final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock();
+        final int imeHeight = mService.mPolicy.getInputMethodWindowVisibleHeightLw();
+        final boolean imeHeightChanged = imeVisible &&
+                imeHeight != mDividerControllerLocked.getImeHeightAdjustedFor();
+
+        // The divider could be adjusted for IME position, or be thinner than usual,
+        // or both. There are three possible cases:
+        // - If IME is visible, and focus is on top, divider is not moved for IME but thinner.
+        // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner.
+        // - If IME is not visible, divider is not moved and is normal width.
+
+        if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
+            for (int i = mChildren.size() - 1; i >= 0; --i) {
+                final TaskStack stack = mChildren.get(i);
+                final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
+                if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)) {
+                    stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
+                } else {
+                    stack.resetAdjustedForIme(false);
+                }
+            }
+            mDividerControllerLocked.setAdjustedForIme(
+                    imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
+        } else {
+            for (int i = mChildren.size() - 1; i >= 0; --i) {
+                final TaskStack stack = mChildren.get(i);
+                stack.resetAdjustedForIme(!dockVisible);
+            }
+            mDividerControllerLocked.setAdjustedForIme(
+                    false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight);
+        }
+    }
+
+    void prepareFreezingTaskBounds() {
+        for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) {
+            final TaskStack stack = mChildren.get(stackNdx);
+            stack.prepareFreezingTaskBounds();
+        }
+    }
+
     void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
         final int rotationDelta = DisplayContent.deltaRotation(oldRotation, newRotation);
         getLogicalDisplayRect(mTmpRect);
@@ -619,13 +694,13 @@
             pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
             pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
             pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
-            pw.print(subPrefix); pw.print("deferred="); pw.print(mDeferredRemoval);
-                pw.print(" layoutNeeded="); pw.println(layoutNeeded);
+            pw.println(subPrefix + "deferred=" + mDeferredRemoval
+                    + " mLayoutNeeded=" + mLayoutNeeded);
 
         pw.println();
         pw.println("  Application tokens in top down Z order:");
-        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
-            final TaskStack stack = mStacks.get(stackNdx);
+        for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) {
+            final TaskStack stack = mChildren.get(stackNdx);
             stack.dump(prefix + "  ", pw);
         }
 
@@ -649,7 +724,7 @@
 
     @Override
     public String toString() {
-        return getName() + " stacks=" + mStacks;
+        return getName() + " stacks=" + mChildren;
     }
 
     String getName() {
@@ -706,15 +781,6 @@
         return touchedWin;
     }
 
-    /**
-     * See {@link WindowManagerService#overridePlayingAppAnimationsLw}.
-     */
-    void overridePlayingAppAnimationsLw(Animation a) {
-        for (int i = mStacks.size() - 1; i >= 0; i--) {
-            mStacks.get(i).overridePlayingAppAnimations(a);
-        }
-    }
-
     boolean canAddToastWindowForUid(int uid) {
         // We allow one toast window per UID being shown at a time.
         WindowList windows = getWindowList();
@@ -722,7 +788,8 @@
         for (int i = 0; i < windowCount; i++) {
             WindowState window = windows.get(i);
             if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == uid
-                    && !window.mPermanentlyHidden && !window.mAnimatingExit) {
+                    && !window.mPermanentlyHidden && !window.mAnimatingExit
+                    && !window.mRemoveOnExit) {
                 return false;
             }
         }
@@ -788,12 +855,7 @@
             // Descend through all of the app tokens and find the first that either matches
             // win.mAppToken (return win) or mFocusedApp (return null).
             if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
-                final TaskStack focusedAppStack = focusedApp.mTask.mStack;
-                final TaskStack appStack = wtoken.mTask.mStack;
-
-                // TODO: Use WindowContainer.compareTo() once everything is using WindowContainer
-                if ((focusedAppStack == appStack && focusedApp.compareTo(wtoken) > 0)
-                        || mStacks.indexOf(focusedAppStack) > mStacks.indexOf(appStack)) {
+                if (focusedApp.compareTo(wtoken) > 0) {
                     // App stack below focused app stack. No focus for you!!!
                     if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
                             "findFocusedWindow: Reached focused app=" + focusedApp);
@@ -826,8 +888,8 @@
 
         // Figure out where the window should go, based on the order of applications.
         mTmpGetWindowOnDisplaySearchResult.reset();
-        for (int i = mStacks.size() - 1; i >= 0; --i) {
-            final TaskStack stack = mStacks.get(i);
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mChildren.get(i);
             stack.getWindowOnDisplayBeforeToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
             if (mTmpGetWindowOnDisplaySearchResult.reachedToken) {
                 // We have reach the token we are interested in. End search.
@@ -858,8 +920,8 @@
 
         // Continue looking down until we find the first token that has windows on this display.
         mTmpGetWindowOnDisplaySearchResult.reset();
-        for (int i = mStacks.size() - 1; i >= 0; --i) {
-            final TaskStack stack = mStacks.get(i);
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mChildren.get(i);
             stack.getWindowOnDisplayAfterToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
             if (mTmpGetWindowOnDisplaySearchResult.foundWindow != null) {
                 // We have found a window after the token. End search.
@@ -1023,23 +1085,23 @@
         // First add all of the exiting app tokens...  these are no longer in the main app list,
         // but still have windows shown. We put them in the back because now that the animation is
         // over we no longer will care about them.
-        final int numStacks = mStacks.size();
+        final int numStacks = mChildren.size();
         for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
-            AppTokenList exitingAppTokens = mStacks.get(stackNdx).mExitingAppTokens;
+            AppTokenList exitingAppTokens = mChildren.get(stackNdx).mExitingAppTokens;
             int NT = exitingAppTokens.size();
             for (int j = 0; j < NT; j++) {
-                i = exitingAppTokens.get(j).rebuildWindowList(this, i);
+                i = exitingAppTokens.get(j).rebuildWindowListUnchecked(this, i);
             }
         }
 
         // And add in the still active app tokens in Z order.
         for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
-            i = mStacks.get(stackNdx).rebuildWindowList(this, i);
+            i = mChildren.get(stackNdx).rebuildWindowList(this, i);
         }
 
         i -= lastBelow;
         if (i != numRemoved) {
-            layoutNeeded = true;
+            setLayoutNeeded();
             Slog.w(TAG_WM, "On display=" + mDisplayId + " Rebuild removed " + numRemoved
                     + " windows but added " + i + " rebuildAppWindowListLocked() "
                     + " callers=" + Debug.getCallers(10));
@@ -1055,7 +1117,7 @@
                     ws.mWinAnimator.destroySurfaceLocked();
                 }
             }
-            Slog.w(TAG_WM, "Current app token list:");
+            Slog.w(TAG_WM, "Current window hierarchy:");
             dumpChildrenNames();
             Slog.w(TAG_WM, "Final window list:");
             dumpWindows();
@@ -1076,6 +1138,20 @@
         return windowList;
     }
 
+    void setLayoutNeeded() {
+        if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3));
+        mLayoutNeeded = true;
+    }
+
+    void clearLayoutNeeded() {
+        if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3));
+        mLayoutNeeded = false;
+    }
+
+    boolean isLayoutNeeded() {
+        return mLayoutNeeded;
+    }
+
     private int addAppWindowExisting(WindowState win, WindowList tokenWindowList) {
 
         int tokenWindowsPos;
@@ -1153,29 +1229,16 @@
     }
 
     private void dumpChildrenNames() {
-        StringWriter sw = new StringWriter();
-        PrintWriter pw = new FastPrintWriter(sw, false, 1024);
-        dumpChildrenNames(pw, "  ");
-    }
-
-    private void dumpChildrenNames(PrintWriter pw, String prefix) {
-        final String childPrefix = prefix + prefix;
-        for (int j = mStacks.size() - 1; j >= 0; j--) {
-            final TaskStack stack = mStacks.get(j);
-            pw.println("#" + j + " " + getName());
-            stack.dumpChildrenNames(pw, childPrefix);
-        }
+        StringBuilder output = new StringBuilder();
+        dumpChildrenNames(output, " ");
+        Slog.v(TAG_WM, output.toString());
     }
 
     private void dumpWindows() {
-        final int numDisplays = mService.mDisplayContents.size();
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
-            Slog.v(TAG_WM, " Display #" + displayContent.getDisplayId());
-            final WindowList windows = displayContent.getWindowList();
-            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
-                Slog.v(TAG_WM, "  #" + winNdx + ": " + windows.get(winNdx));
-            }
+        Slog.v(TAG_WM, " Display #" + mDisplayId);
+        final WindowList windows = getWindowList();
+        for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
+            Slog.v(TAG_WM, "  #" + winNdx + ": " + windows.get(winNdx));
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index ff676e9..15a952d 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -131,8 +131,8 @@
     private boolean mAdjustedForDivider;
     private float mDividerAnimationStart;
     private float mDividerAnimationTarget;
-    private float mLastAnimationProgress;
-    private float mLastDividerProgress;
+    float mLastAnimationProgress;
+    float mLastDividerProgress;
     private final DividerSnapAlgorithm[] mSnapAlgorithmForRotation = new DividerSnapAlgorithm[4];
     private boolean mImeHideRequested;
 
@@ -153,7 +153,7 @@
         // If the bounds are fullscreen, return the value of the fullscreen configuration
         if (bounds == null || (bounds.left == 0 && bounds.top == 0
                 && bounds.right == di.logicalWidth && bounds.bottom == di.logicalHeight)) {
-            return mService.mGlobalConfiguration.smallestScreenWidthDp;
+            return mDisplayContent.getConfiguration().smallestScreenWidthDp;
         }
         final int baseDisplayWidth = mDisplayContent.mBaseDisplayWidth;
         final int baseDisplayHeight = mDisplayContent.mBaseDisplayHeight;
@@ -190,7 +190,7 @@
     }
 
     private void initSnapAlgorithmForRotations() {
-        final Configuration baseConfig = mService.mGlobalConfiguration;
+        final Configuration baseConfig = mDisplayContent.getConfiguration();
 
         // Initialize the snap algorithms for all 4 screen orientations.
         final Configuration config = new Configuration();
@@ -594,15 +594,7 @@
     }
 
     private boolean clearImeAdjustAnimation() {
-        boolean changed = false;
-        final ArrayList<TaskStack> stacks = mDisplayContent.getStacks();
-        for (int i = stacks.size() - 1; i >= 0; --i) {
-            final TaskStack stack = stacks.get(i);
-            if (stack != null && stack.isAdjustedForIme()) {
-                stack.resetAdjustedForIme(true /* adjustBoundsNow */);
-                changed  = true;
-            }
-        }
+        final boolean changed = mDisplayContent.clearImeAdjustAnimation();
         mAnimatingForIme = false;
         return changed;
     }
@@ -634,13 +626,7 @@
         mAnimationTarget = adjustedForIme ? 1 : 0;
         mDividerAnimationTarget = adjustedForDivider ? 1 : 0;
 
-        final ArrayList<TaskStack> stacks = mDisplayContent.getStacks();
-        for (int i = stacks.size() - 1; i >= 0; --i) {
-            final TaskStack stack = stacks.get(i);
-            if (stack.isVisible() && stack.isAdjustedForIme()) {
-                stack.beginImeAdjustAnimation();
-            }
-        }
+        mDisplayContent.beginImeAdjustAnimation();
 
         // We put all tasks into drag resizing mode - wait until all of them have completed the
         // drag resizing switch.
@@ -721,27 +707,8 @@
         float t = Math.min(1f, (float) (now - mAnimationStartTime) / mAnimationDuration);
         t = (mAnimationTarget == 1f ? IME_ADJUST_ENTRY_INTERPOLATOR : TOUCH_RESPONSE_INTERPOLATOR)
                 .getInterpolation(t);
-        final ArrayList<TaskStack> stacks = mDisplayContent.getStacks();
-        boolean updated = false;
-        for (int i = stacks.size() - 1; i >= 0; --i) {
-            final TaskStack stack = stacks.get(i);
-            if (stack != null && stack.isAdjustedForIme()) {
-                if (t >= 1f && mAnimationTarget == 0f && mDividerAnimationTarget == 0f) {
-                    stack.resetAdjustedForIme(true /* adjustBoundsNow */);
-                    updated = true;
-                } else {
-                    mLastAnimationProgress = getInterpolatedAnimationValue(t);
-                    mLastDividerProgress = getInterpolatedDividerValue(t);
-                    updated |= stack.updateAdjustForIme(
-                            mLastAnimationProgress,
-                            mLastDividerProgress,
-                            false /* force */);
-                }
-                if (t >= 1f) {
-                    stack.endImeAdjustAnimation();
-                }
-            }
-        }
+        final boolean updated =
+                mDisplayContent.animateForIme(t, mAnimationTarget, mDividerAnimationTarget);
         if (updated) {
             mService.mWindowPlacerLocked.performSurfacePlacement();
         }
@@ -785,11 +752,11 @@
         }
     }
 
-    private float getInterpolatedAnimationValue(float t) {
+    float getInterpolatedAnimationValue(float t) {
         return t * mAnimationTarget + (1 - t) * mAnimationStart;
     }
 
-    private float getInterpolatedDividerValue(float t) {
+    float getInterpolatedDividerValue(float t) {
         return t * mDividerAnimationTarget + (1 - t) * mDividerAnimationStart;
     }
 
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 535ce9d..a5387bd 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -165,7 +165,7 @@
         return 0; // abort dispatching
     }
 
-    private void addInputWindowHandleLw(final InputWindowHandle windowHandle) {
+    void addInputWindowHandle(final InputWindowHandle windowHandle) {
         if (mInputWindowHandles == null) {
             mInputWindowHandles = new InputWindowHandle[16];
         }
@@ -176,7 +176,7 @@
         mInputWindowHandles[mInputWindowHandleCount++] = windowHandle;
     }
 
-    private void addInputWindowHandleLw(final InputWindowHandle inputWindowHandle,
+    void addInputWindowHandle(final InputWindowHandle inputWindowHandle,
             final WindowState child, int flags, final int type, final boolean isVisible,
             final boolean hasFocus, final boolean hasWallpaper) {
         // Add a window to our list of input windows.
@@ -214,7 +214,7 @@
             Slog.d(TAG_WM, "addInputWindowHandle: "
                     + child + ", " + inputWindowHandle);
         }
-        addInputWindowHandleLw(inputWindowHandle);
+        addInputWindowHandle(inputWindowHandle);
     }
 
     private void clearInputWindowHandlesLw() {
@@ -241,9 +241,8 @@
         // As an optimization, we could try to prune the list of windows but this turns
         // out to be difficult because only the native code knows for sure which window
         // currently has touch focus.
-        boolean disableWallpaperTouchEvents = false;
 
-        // If there's a drag in flight, provide a pseudowindow to catch drag input
+        // If there's a drag in flight, provide a pseudo-window to catch drag input
         final boolean inDrag = (mService.mDragState != null);
         if (inDrag) {
             if (DEBUG_DRAG) {
@@ -251,7 +250,7 @@
             }
             final InputWindowHandle dragWindowHandle = mService.mDragState.getInputWindowHandle();
             if (dragWindowHandle != null) {
-                addInputWindowHandleLw(dragWindowHandle);
+                addInputWindowHandle(dragWindowHandle);
             } else {
                 Slog.w(TAG_WM, "Drag is in progress but there is no "
                         + "drag window handle.");
@@ -265,78 +264,15 @@
             }
             final InputWindowHandle dragWindowHandle = mService.mTaskPositioner.mDragWindowHandle;
             if (dragWindowHandle != null) {
-                addInputWindowHandleLw(dragWindowHandle);
+                addInputWindowHandle(dragWindowHandle);
             } else {
                 Slog.e(TAG_WM,
                         "Repositioning is in progress but there is no drag window handle.");
             }
         }
 
-        boolean addInputConsumerHandle = mService.mInputConsumer != null;
-
-        boolean addWallpaperInputConsumerHandle = mService.mWallpaperInputConsumer != null;
-
         // Add all windows on the default display.
-        final int numDisplays = mService.mDisplayContents.size();
-        final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
-            final WindowList windows = displayContent.getWindowList();
-            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
-                final WindowState child = windows.get(winNdx);
-                final InputChannel inputChannel = child.mInputChannel;
-                final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
-                if (inputChannel == null || inputWindowHandle == null || child.mRemoved
-                        || child.isAdjustedForMinimizedDock()) {
-                    // Skip this window because it cannot possibly receive input.
-                    continue;
-                }
-                if (addInputConsumerHandle
-                        && inputWindowHandle.layer <= mService.mInputConsumer.mWindowHandle.layer) {
-                    addInputWindowHandleLw(mService.mInputConsumer.mWindowHandle);
-                    addInputConsumerHandle = false;
-                }
-
-                if (addWallpaperInputConsumerHandle) {
-                    if (child.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER &&
-                            child.isVisibleLw()) {
-                        // Add the wallpaper input consumer above the first visible wallpaper.
-                        addInputWindowHandleLw(mService.mWallpaperInputConsumer.mWindowHandle);
-                        addWallpaperInputConsumerHandle = false;
-                    }
-                }
-
-                final int flags = child.mAttrs.flags;
-                final int privateFlags = child.mAttrs.privateFlags;
-                final int type = child.mAttrs.type;
-
-                final boolean hasFocus = (child == mInputFocus);
-                final boolean isVisible = child.isVisibleLw();
-                if ((privateFlags
-                        & WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS)
-                            != 0) {
-                    disableWallpaperTouchEvents = true;
-                }
-                final boolean hasWallpaper = wallpaperController.isWallpaperTarget(child)
-                        && (privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD) == 0
-                        && !disableWallpaperTouchEvents;
-                final boolean onDefaultDisplay = (child.getDisplayId() == Display.DEFAULT_DISPLAY);
-
-                // If there's a drag in progress and 'child' is a potential drop target,
-                // make sure it's been told about the drag
-                if (inDrag && isVisible && onDefaultDisplay) {
-                    mService.mDragState.sendDragStartedIfNeededLw(child);
-                }
-
-                addInputWindowHandleLw(
-                        inputWindowHandle, child, flags, type, isVisible, hasFocus, hasWallpaper);
-            }
-        }
-
-        if (addWallpaperInputConsumerHandle) {
-            // No visible wallpaper found, add the wallpaper input consumer at the end.
-            addInputWindowHandleLw(mService.mWallpaperInputConsumer.mWindowHandle);
-        }
+        mService.mRoot.updateInputWindows(this, mInputFocus, inDrag);
 
         // Send windows to native code.
         mService.mInputManager.setInputWindows(mInputWindowHandles);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
new file mode 100644
index 0000000..219fd8e
--- /dev/null
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -0,0 +1,1458 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.app.AppOpsManager;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Binder;
+import android.os.Debug;
+import android.os.ParcelFileDescriptor;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.EventLog;
+import android.util.Slog;
+import android.util.SparseIntArray;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.InputChannel;
+import android.view.WindowManager;
+import com.android.internal.util.ArrayUtils;
+import com.android.server.EventLogTags;
+import com.android.server.input.InputWindowHandle;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
+import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
+import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
+import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
+import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
+import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.H.NOTIFY_STARTING_WINDOW_DRAWN;
+import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
+import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
+import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
+import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
+import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT;
+import static com.android.server.wm.WindowManagerService.logSurface;
+import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
+import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
+import static com.android.server.wm.WindowSurfacePlacer.SET_TURN_ON_SCREEN;
+import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
+import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
+import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
+
+/** Root {@link WindowContainer} for the device. */
+// TODO: Several methods in here are accessing children of this container's children through various
+// references (WindowList I am looking at you :/). See if we can delegate instead.
+class RootWindowContainer extends WindowContainer<DisplayContent> {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM;
+
+    WindowManagerService mService;
+
+    private boolean mWallpaperForceHidingChanged = false;
+    private Object mLastWindowFreezeSource = null;
+    private Session mHoldScreen = null;
+    private float mScreenBrightness = -1;
+    private float mButtonBrightness = -1;
+    private long mUserActivityTimeout = -1;
+    private boolean mUpdateRotation = false;
+    private boolean mObscured = false;
+    boolean mSyswin = false;
+    // Set to true when the display contains content to show the user.
+    // When false, the display manager may choose to mirror or blank the display.
+    private boolean mDisplayHasContent = false;
+    private float mPreferredRefreshRate = 0;
+    private int mPreferredModeId = 0;
+    // Following variables are for debugging screen wakelock only.
+    // Last window that requires screen wakelock
+    WindowState mHoldScreenWindow = null;
+    // Last window that obscures all windows below
+    WindowState mObsuringWindow = null;
+    // Only set while traversing the default display based on its content.
+    // Affects the behavior of mirroring on secondary displays.
+    private boolean mObscureApplicationContentOnSecondaryDisplays = false;
+
+    private boolean mSustainedPerformanceModeEnabled = false;
+    private boolean mSustainedPerformanceModeCurrent = false;
+
+    boolean mWallpaperMayChange = false;
+    // During an orientation change, we track whether all windows have rendered
+    // at the new orientation, and this will be false from changing orientation until that occurs.
+    // For seamless rotation cases this always stays true, as the windows complete their orientation
+    // changes 1 by 1 without disturbing global state.
+    boolean mOrientationChangeComplete = true;
+    boolean mWallpaperActionPending = false;
+
+    private final ArrayList<Integer> mChangedStackList = new ArrayList();
+
+    // State for the RemoteSurfaceTrace system used in testing. If this is enabled SurfaceControl
+    // instances will be replaced with an instance that writes a binary representation of all
+    // commands to mSurfaceTraceFd.
+    boolean mSurfaceTraceEnabled;
+    ParcelFileDescriptor mSurfaceTraceFd;
+    RemoteEventTrace mRemoteEventTrace;
+
+    RootWindowContainer(WindowManagerService service) {
+        mService = service;
+    }
+
+    WindowState computeFocusedWindow() {
+        final int count = mChildren.size();
+        for (int i = 0; i < count; i++) {
+            final DisplayContent dc = mChildren.get(i);
+            final WindowState win = dc.findFocusedWindow();
+            if (win != null) {
+                return win;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
+     * there is a Display for the displayId.
+     *
+     * @param displayId The display the caller is interested in.
+     * @return The DisplayContent associated with displayId or null if there is no Display for it.
+     */
+    DisplayContent getDisplayContentOrCreate(int displayId) {
+        DisplayContent dc = getDisplayContent(displayId);
+
+        if (dc == null) {
+            final Display display = mService.mDisplayManager.getDisplay(displayId);
+            if (display != null) {
+                dc = createDisplayContent(display);
+            }
+        }
+        return dc;
+    }
+
+    private DisplayContent getDisplayContent(int displayId) {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final DisplayContent current = mChildren.get(i);
+            if (current.getDisplayId() == displayId) {
+                return current;
+            }
+        }
+        return null;
+    }
+
+    private DisplayContent createDisplayContent(final Display display) {
+        final DisplayContent dc = new DisplayContent(display, mService);
+        final int displayId = display.getDisplayId();
+
+        if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
+        addChild(dc, null);
+
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Rect rect = new Rect();
+        mService.mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
+        displayInfo.overscanLeft = rect.left;
+        displayInfo.overscanTop = rect.top;
+        displayInfo.overscanRight = rect.right;
+        displayInfo.overscanBottom = rect.bottom;
+        if (mService.mDisplayManagerInternal != null) {
+            mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
+                    displayId, displayInfo);
+            mService.configureDisplayPolicyLocked(dc);
+
+            // TODO(multi-display): Create an input channel for each display with touch capability.
+            if (displayId == Display.DEFAULT_DISPLAY) {
+                dc.mTapDetector = new TaskTapPointerEventListener(
+                        mService, dc);
+                mService.registerPointerEventListener(dc.mTapDetector);
+                mService.registerPointerEventListener(mService.mMousePositionTracker);
+            }
+        }
+
+        return dc;
+    }
+
+    /** Adds the input stack id to the input display id and returns the bounds of the added stack.*/
+    Rect addStackToDisplay(int stackId, int displayId, boolean onTop) {
+        final DisplayContent dc = getDisplayContent(displayId);
+        if (dc == null) {
+            Slog.w(TAG_WM, "addStackToDisplay: Trying to add stackId=" + stackId
+                    + " to unknown displayId=" + displayId + " callers=" + Debug.getCallers(6));
+            return null;
+        }
+
+        boolean attachedToDisplay = false;
+        TaskStack stack = mService.mStackIdToStack.get(stackId);
+        if (stack == null) {
+            if (DEBUG_STACK) Slog.d(TAG_WM, "attachStack: stackId=" + stackId);
+
+            stack = dc.getStackById(stackId);
+            if (stack != null) {
+                // It's already attached to the display...clear mDeferRemoval and move stack to
+                // appropriate z-order on display as needed.
+                stack.mDeferRemoval = false;
+                dc.moveStack(stack, onTop);
+                attachedToDisplay = true;
+            } else {
+                stack = new TaskStack(mService, stackId);
+            }
+
+            mService.mStackIdToStack.put(stackId, stack);
+            if (stackId == DOCKED_STACK_ID) {
+                mService.getDefaultDisplayContentLocked().mDividerControllerLocked
+                        .notifyDockedStackExistsChanged(true);
+            }
+        }
+
+        if (!attachedToDisplay) {
+            stack.attachDisplayContent(dc);
+            dc.attachStack(stack, onTop);
+        }
+
+        if (stack.getRawFullscreen()) {
+            return null;
+        }
+        final Rect bounds = new Rect();
+        stack.getRawBounds(bounds);
+        return bounds;
+    }
+
+    boolean isLayoutNeeded() {
+        final int numDisplays = mChildren.size();
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final DisplayContent displayContent = mChildren.get(displayNdx);
+            if (displayContent.isLayoutNeeded()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    void getWindows(WindowList output) {
+        final int count = mChildren.size();
+        for (int i = 0; i < count; ++i) {
+            final DisplayContent dc = mChildren.get(i);
+            output.addAll(dc.getWindowList());
+        }
+    }
+
+    void getWindows(WindowList output, boolean visibleOnly, boolean appsOnly) {
+        final int numDisplays = mChildren.size();
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final WindowList windowList = mChildren.get(displayNdx).getWindowList();
+            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
+                final WindowState w = windowList.get(winNdx);
+                if ((!visibleOnly || w.mWinAnimator.getShown())
+                        && (!appsOnly || w.mAppToken != null)) {
+                    output.add(w);
+                }
+            }
+        }
+    }
+
+    void getWindowsByName(WindowList output, String name) {
+        int objectId = 0;
+        // See if this is an object ID.
+        try {
+            objectId = Integer.parseInt(name, 16);
+            name = null;
+        } catch (RuntimeException e) {
+        }
+        final int numDisplays = mChildren.size();
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final WindowList windowList = mChildren.get(displayNdx).getWindowList();
+            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
+                final WindowState w = windowList.get(winNdx);
+                if (name != null) {
+                    if (w.mAttrs.getTitle().toString().contains(name)) {
+                        output.add(w);
+                    }
+                } else if (System.identityHashCode(w) == objectId) {
+                    output.add(w);
+                }
+            }
+        }
+    }
+
+    WindowState findWindow(int hashCode) {
+        final int numDisplays = mChildren.size();
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final WindowList windows = mChildren.get(displayNdx).getWindowList();
+            final int numWindows = windows.size();
+            for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
+                final WindowState w = windows.get(winNdx);
+                if (System.identityHashCode(w) == hashCode) {
+                    return w;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    // TODO: Users would have their own window containers under the display container?
+    void switchUser() {
+        final int count = mChildren.size();
+        for (int i = 0; i < count; ++i) {
+            final DisplayContent dc = mChildren.get(i);
+            dc.switchUser();
+        }
+    }
+
+    /** Set new config and return array of ids of stacks that were changed during update. */
+    int[] setGlobalConfigurationIfNeeded(Configuration newConfiguration) {
+        final boolean configChanged = getConfiguration().diff(newConfiguration) != 0;
+        if (!configChanged) {
+            return null;
+        }
+        onConfigurationChanged(newConfiguration);
+        return updateStackBoundsAfterConfigChange();
+    }
+
+    @Override
+    void onConfigurationChanged(Configuration newParentConfig) {
+        prepareFreezingTaskBounds();
+        super.onConfigurationChanged(newParentConfig);
+
+        mService.mPolicy.onConfigurationChanged();
+    }
+
+    /**
+     * Callback used to trigger bounds update after configuration change and get ids of stacks whose
+     * bounds were updated.
+     */
+    int[] updateStackBoundsAfterConfigChange() {
+        mChangedStackList.clear();
+
+        final int numDisplays = mChildren.size();
+        for (int i = 0; i < numDisplays; ++i) {
+            final DisplayContent dc = mChildren.get(i);
+            dc.updateStackBoundsAfterConfigChange(mChangedStackList);
+        }
+
+        return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList);
+    }
+
+    private void prepareFreezingTaskBounds() {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            mChildren.get(i).prepareFreezingTaskBounds();
+        }
+    }
+
+    void setSecureSurfaceState(int userId, boolean disabled) {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowList windows = mChildren.get(i).getWindowList();
+            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
+                final WindowState win = windows.get(winNdx);
+                if (win.mHasSurface && userId == UserHandle.getUserId(win.mOwnerUid)) {
+                    win.mWinAnimator.setSecureLocked(disabled);
+                }
+            }
+        }
+    }
+
+    void updateAppOpsState() {
+        final int count = mChildren.size();
+        for (int i = 0; i < count; ++i) {
+            final WindowList windows = mChildren.get(i).getWindowList();
+            final int numWindows = windows.size();
+            for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
+                final WindowState win = windows.get(winNdx);
+                if (win.mAppOp == AppOpsManager.OP_NONE) {
+                    continue;
+                }
+                final int mode = mService.mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
+                        win.getOwningPackage());
+                win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED ||
+                        mode == AppOpsManager.MODE_DEFAULT);
+            }
+        }
+    }
+
+    boolean canShowStrictModeViolation(int pid) {
+        final int count = mChildren.size();
+        for (int i = 0; i < count; ++i) {
+            final WindowList windows = mChildren.get(i).getWindowList();
+            final int numWindows = windows.size();
+            for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
+                final WindowState ws = windows.get(winNdx);
+                if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    void closeSystemDialogs(String reason) {
+        final int count = mChildren.size();
+        for (int i = 0; i < count; ++i) {
+            final WindowList windows = mChildren.get(i).getWindowList();
+            final int numWindows = windows.size();
+            for (int j = 0; j < numWindows; ++j) {
+                final WindowState w = windows.get(j);
+                if (w.mHasSurface) {
+                    try {
+                        w.mClient.closeSystemDialogs(reason);
+                    } catch (RemoteException e) {
+                    }
+                }
+            }
+        }
+    }
+
+    void removeReplacedWindows() {
+        if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
+        mService.openSurfaceTransaction();
+        try {
+            for (int i = mChildren.size() - 1; i >= 0; i--) {
+                DisplayContent dc = mChildren.get(i);
+                final WindowList windows = dc.getWindowList();
+                for (int j = windows.size() - 1; j >= 0; j--) {
+                    final WindowState win = windows.get(j);
+                    final AppWindowToken aToken = win.mAppToken;
+                    if (aToken != null) {
+                        aToken.removeReplacedWindowIfNeeded(win);
+                    }
+                }
+            }
+        } finally {
+            mService.closeSurfaceTransaction();
+            if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
+        }
+    }
+
+    boolean hasPendingLayoutChanges(WindowAnimator animator) {
+        boolean hasChanges = false;
+
+        final int count = mChildren.size();
+        for (int i = 0; i < count; ++i) {
+            final DisplayContent dc = mChildren.get(i);
+            final int pendingChanges = animator.getPendingLayoutChanges(dc.getDisplayId());
+            if ((pendingChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
+                animator.mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
+            }
+            if (pendingChanges != 0) {
+                hasChanges = true;
+            }
+        }
+
+        return hasChanges;
+    }
+
+    void updateInputWindows(InputMonitor inputMonitor, WindowState inputFocus, boolean inDrag) {
+        boolean addInputConsumerHandle = mService.mInputConsumer != null;
+        boolean addWallpaperInputConsumerHandle = mService.mWallpaperInputConsumer != null;
+        final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
+        boolean disableWallpaperTouchEvents = false;
+
+        final int count = mChildren.size();
+        for (int i = 0; i < count; ++i) {
+            final DisplayContent dc = mChildren.get(i);
+            final WindowList windows = dc.getWindowList();
+            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
+                final WindowState child = windows.get(winNdx);
+                final InputChannel inputChannel = child.mInputChannel;
+                final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
+                if (inputChannel == null || inputWindowHandle == null || child.mRemoved
+                        || child.isAdjustedForMinimizedDock()) {
+                    // Skip this window because it cannot possibly receive input.
+                    continue;
+                }
+                if (addInputConsumerHandle
+                        && inputWindowHandle.layer <= mService.mInputConsumer.mWindowHandle.layer) {
+                    inputMonitor.addInputWindowHandle(mService.mInputConsumer.mWindowHandle);
+                    addInputConsumerHandle = false;
+                }
+
+                if (addWallpaperInputConsumerHandle) {
+                    if (child.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER &&
+                            child.isVisibleLw()) {
+                        // Add the wallpaper input consumer above the first visible wallpaper.
+                        inputMonitor.addInputWindowHandle(
+                                mService.mWallpaperInputConsumer.mWindowHandle);
+                        addWallpaperInputConsumerHandle = false;
+                    }
+                }
+
+                final int flags = child.mAttrs.flags;
+                final int privateFlags = child.mAttrs.privateFlags;
+                final int type = child.mAttrs.type;
+
+                final boolean hasFocus = child == inputFocus;
+                final boolean isVisible = child.isVisibleLw();
+                if ((privateFlags
+                        & WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS)
+                        != 0) {
+                    disableWallpaperTouchEvents = true;
+                }
+                final boolean hasWallpaper = wallpaperController.isWallpaperTarget(child)
+                        && (privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD) == 0
+                        && !disableWallpaperTouchEvents;
+                final boolean onDefaultDisplay = (child.getDisplayId() == Display.DEFAULT_DISPLAY);
+
+                // If there's a drag in progress and 'child' is a potential drop target,
+                // make sure it's been told about the drag
+                if (inDrag && isVisible && onDefaultDisplay) {
+                    mService.mDragState.sendDragStartedIfNeededLw(child);
+                }
+
+                inputMonitor.addInputWindowHandle(
+                        inputWindowHandle, child, flags, type, isVisible, hasFocus, hasWallpaper);
+            }
+        }
+
+        if (addWallpaperInputConsumerHandle) {
+            // No visible wallpaper found, add the wallpaper input consumer at the end.
+            inputMonitor.addInputWindowHandle(mService.mWallpaperInputConsumer.mWindowHandle);
+        }
+    }
+
+    boolean reclaimSomeSurfaceMemory(WindowStateAnimator winAnimator, String operation,
+            boolean secure) {
+        final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
+        boolean leakedSurface = false;
+        boolean killedApps = false;
+
+        EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
+                winAnimator.mSession.mPid, operation);
+
+        final long callingIdentity = Binder.clearCallingIdentity();
+        try {
+            // There was some problem...   first, do a sanity check of the window list to make sure
+            // we haven't left any dangling surfaces around.
+
+            Slog.i(TAG_WM, "Out of memory for surface!  Looking for leaks...");
+            final int numDisplays = mChildren.size();
+            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+                final WindowList windows = mChildren.get(displayNdx).getWindowList();
+                final int numWindows = windows.size();
+                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
+                    final WindowState ws = windows.get(winNdx);
+                    final WindowStateAnimator wsa = ws.mWinAnimator;
+                    if (wsa.mSurfaceController == null) {
+                        continue;
+                    }
+                    if (!mService.mSessions.contains(wsa.mSession)) {
+                        Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
+                                + ws + " surface=" + wsa.mSurfaceController
+                                + " token=" + ws.mToken
+                                + " pid=" + ws.mSession.mPid
+                                + " uid=" + ws.mSession.mUid);
+                        wsa.destroySurface();
+                        mService.mForceRemoves.add(ws);
+                        leakedSurface = true;
+                    } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
+                        Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
+                                + ws + " surface=" + wsa.mSurfaceController
+                                + " token=" + ws.mAppToken
+                                + " saved=" + ws.hasSavedSurface());
+                        if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
+                        wsa.destroySurface();
+                        leakedSurface = true;
+                    }
+                }
+            }
+
+            if (!leakedSurface) {
+                Slog.w(TAG_WM, "No leaked surfaces; killing applications!");
+                SparseIntArray pidCandidates = new SparseIntArray();
+                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+                    final WindowList windows = mChildren.get(displayNdx).getWindowList();
+                    final int numWindows = windows.size();
+                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
+                        final WindowState ws = windows.get(winNdx);
+                        if (mService.mForceRemoves.contains(ws)) {
+                            continue;
+                        }
+                        WindowStateAnimator wsa = ws.mWinAnimator;
+                        if (wsa.mSurfaceController != null) {
+                            pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
+                        }
+                    }
+                    if (pidCandidates.size() > 0) {
+                        int[] pids = new int[pidCandidates.size()];
+                        for (int i = 0; i < pids.length; i++) {
+                            pids[i] = pidCandidates.keyAt(i);
+                        }
+                        try {
+                            if (mService.mActivityManager.killPids(pids, "Free memory", secure)) {
+                                killedApps = true;
+                            }
+                        } catch (RemoteException e) {
+                        }
+                    }
+                }
+            }
+
+            if (leakedSurface || killedApps) {
+                // We managed to reclaim some memory, so get rid of the trouble surface and ask the
+                // app to request another one.
+                Slog.w(TAG_WM,
+                        "Looks like we have reclaimed some memory, clearing surface for retry.");
+                if (surfaceController != null) {
+                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
+                            "RECOVER DESTROY", false);
+                    winAnimator.destroySurface();
+                    mService.scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken);
+                }
+
+                try {
+                    winAnimator.mWin.mClient.dispatchGetNewSurface();
+                } catch (RemoteException e) {
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingIdentity);
+        }
+
+        return leakedSurface || killedApps;
+    }
+
+    // "Something has changed!  Let's make it correct now."
+    // TODO: Super crazy long method that should be broken down...
+    void performSurfacePlacement(boolean recoveringMemory) {
+        if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
+                + Debug.getCallers(3));
+
+        int i;
+        boolean updateInputWindowsNeeded = false;
+
+        if (mService.mFocusMayChange) {
+            mService.mFocusMayChange = false;
+            updateInputWindowsNeeded = mService.updateFocusedWindowLocked(
+                    UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
+        }
+
+        // Initialize state of exiting tokens.
+        final int numDisplays = mChildren.size();
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final DisplayContent displayContent = mChildren.get(displayNdx);
+            for (i = displayContent.mExitingTokens.size() - 1; i >= 0; i--) {
+                displayContent.mExitingTokens.get(i).hasVisible = false;
+            }
+        }
+
+        for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
+            // Initialize state of exiting applications.
+            final AppTokenList exitingAppTokens =
+                    mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
+            for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
+                exitingAppTokens.get(tokenNdx).hasVisible = false;
+            }
+        }
+
+        mHoldScreen = null;
+        mScreenBrightness = -1;
+        mButtonBrightness = -1;
+        mUserActivityTimeout = -1;
+        mObscureApplicationContentOnSecondaryDisplays = false;
+        mSustainedPerformanceModeCurrent = false;
+        mService.mTransactionSequence++;
+
+        // TODO(multi-display):
+        final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
+        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
+        final int defaultDw = defaultInfo.logicalWidth;
+        final int defaultDh = defaultInfo.logicalHeight;
+
+        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+                ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
+        mService.openSurfaceTransaction();
+        try {
+            mService.mRoot.applySurfaceChangesTransaction(recoveringMemory, defaultDw, defaultDh);
+        } catch (RuntimeException e) {
+            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
+        } finally {
+            mService.closeSurfaceTransaction();
+            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
+        }
+
+        final WindowList defaultWindows = defaultDisplay.getWindowList();
+        final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
+
+        // If we are ready to perform an app transition, check through all of the app tokens to be
+        // shown and see if they are ready to go.
+        if (mService.mAppTransition.isReady()) {
+            defaultDisplay.pendingLayoutChanges |=
+                    surfacePlacer.handleAppTransitionReadyLocked(defaultWindows);
+            if (DEBUG_LAYOUT_REPEATS)
+                surfacePlacer.debugLayoutRepeats("after handleAppTransitionReadyLocked",
+                        defaultDisplay.pendingLayoutChanges);
+        }
+
+        if (!mService.mAnimator.mAppWindowAnimating && mService.mAppTransition.isRunning()) {
+            // We have finished the animation of an app transition. To do this, we have delayed a
+            // lot of operations like showing and hiding apps, moving apps in Z-order, etc. The app
+            // token list reflects the correct Z-order, but the window list may now be out of sync
+            // with it. So here we will just rebuild the entire app window list. Fun!
+            defaultDisplay.pendingLayoutChanges |=
+                    mService.handleAnimatingStoppedAndTransitionLocked();
+            if (DEBUG_LAYOUT_REPEATS)
+                surfacePlacer.debugLayoutRepeats("after handleAnimStopAndXitionLock",
+                        defaultDisplay.pendingLayoutChanges);
+        }
+
+        if (mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
+                && !mService.mAppTransition.isReady()) {
+            // At this point, there was a window with a wallpaper that was force hiding other
+            // windows behind it, but now it is going away. This may be simple -- just animate away
+            // the wallpaper and its window -- or it may be hard -- the wallpaper now needs to be
+            // shown behind something that was hidden.
+            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
+            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
+                    "after animateAwayWallpaperLocked", defaultDisplay.pendingLayoutChanges);
+        }
+        mWallpaperForceHidingChanged = false;
+
+        if (mWallpaperMayChange) {
+            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change!  Adjusting");
+            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("WallpaperMayChange",
+                    defaultDisplay.pendingLayoutChanges);
+        }
+
+        if (mService.mFocusMayChange) {
+            mService.mFocusMayChange = false;
+            if (mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
+                    false /*updateInputWindows*/)) {
+                updateInputWindowsNeeded = true;
+                defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
+            }
+        }
+
+        if (isLayoutNeeded()) {
+            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
+            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("mLayoutNeeded",
+                    defaultDisplay.pendingLayoutChanges);
+        }
+
+        for (i = mService.mResizingWindows.size() - 1; i >= 0; i--) {
+            WindowState win = mService.mResizingWindows.get(i);
+            if (win.mAppFreezing) {
+                // Don't remove this window until rotation has completed.
+                continue;
+            }
+            // Discard the saved surface if window size is changed, it can't be reused.
+            if (win.mAppToken != null) {
+                win.mAppToken.destroySavedSurfaces();
+            }
+            win.reportResized();
+            mService.mResizingWindows.remove(i);
+        }
+
+        if (DEBUG_ORIENTATION && mService.mDisplayFrozen) Slog.v(TAG,
+                "With display frozen, orientationChangeComplete=" + mOrientationChangeComplete);
+        if (mOrientationChangeComplete) {
+            if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
+                mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
+                mService.mLastFinishedFreezeSource = mLastWindowFreezeSource;
+                mService.mH.removeMessages(WINDOW_FREEZE_TIMEOUT);
+            }
+            mService.stopFreezingDisplayLocked();
+        }
+
+        // Destroy the surface of any windows that are no longer visible.
+        boolean wallpaperDestroyed = false;
+        i = mService.mDestroySurface.size();
+        if (i > 0) {
+            do {
+                i--;
+                WindowState win = mService.mDestroySurface.get(i);
+                win.mDestroying = false;
+                if (mService.mInputMethodWindow == win) {
+                    mService.mInputMethodWindow = null;
+                }
+                if (mService.mWallpaperControllerLocked.isWallpaperTarget(win)) {
+                    wallpaperDestroyed = true;
+                }
+                win.destroyOrSaveSurface();
+            } while (i > 0);
+            mService.mDestroySurface.clear();
+        }
+
+        // Time to remove any exiting tokens?
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final DisplayContent displayContent = mChildren.get(displayNdx);
+            ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
+            for (i = exitingTokens.size() - 1; i >= 0; i--) {
+                WindowToken token = exitingTokens.get(i);
+                if (!token.hasVisible) {
+                    exitingTokens.remove(i);
+                    if (token.windowType == TYPE_WALLPAPER) {
+                        mService.mWallpaperControllerLocked.removeWallpaperToken(token);
+                    }
+                }
+            }
+        }
+
+        // Time to remove any exiting applications?
+        for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
+            // Initialize state of exiting applications.
+            final AppTokenList exitingAppTokens =
+                    mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
+            for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
+                final AppWindowToken token = exitingAppTokens.get(i);
+                if (!token.hasVisible && !mService.mClosingApps.contains(token) &&
+                        (!token.mIsExiting || token.isEmpty())) {
+                    // Make sure there is no animation running on this token, so any windows
+                    // associated with it will be removed as soon as their animations are complete
+                    token.mAppAnimator.clearAnimation();
+                    token.mAppAnimator.animating = false;
+                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+                            "performLayout: App token exiting now removed" + token);
+                    token.removeIfPossible();
+                }
+            }
+        }
+
+        if (wallpaperDestroyed) {
+            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+            defaultDisplay.setLayoutNeeded();
+        }
+
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final DisplayContent displayContent = mChildren.get(displayNdx);
+            if (displayContent.pendingLayoutChanges != 0) {
+                displayContent.setLayoutNeeded();
+            }
+        }
+
+        // Finally update all input windows now that the window changes have stabilized.
+        mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+
+        mService.setHoldScreenLocked(mHoldScreen);
+        if (!mService.mDisplayFrozen) {
+            if (mScreenBrightness < 0 || mScreenBrightness > 1.0f) {
+                mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
+            } else {
+                mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
+                        toBrightnessOverride(mScreenBrightness));
+            }
+            if (mButtonBrightness < 0 || mButtonBrightness > 1.0f) {
+                mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
+            } else {
+                mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
+                        toBrightnessOverride(mButtonBrightness));
+            }
+            mService.mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
+                    mUserActivityTimeout);
+        }
+
+        if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) {
+            mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent;
+            mService.mPowerManagerInternal.powerHint(
+                    mService.mPowerManagerInternal.POWER_HINT_SUSTAINED_PERFORMANCE_MODE,
+                    (mSustainedPerformanceModeEnabled ? 1 : 0));
+        }
+
+        if (mService.mTurnOnScreen) {
+            if (mService.mAllowTheaterModeWakeFromLayout
+                    || Settings.Global.getInt(mService.mContext.getContentResolver(),
+                    Settings.Global.THEATER_MODE_ON, 0) == 0) {
+                if (DEBUG_VISIBILITY || DEBUG_POWER) {
+                    Slog.v(TAG, "Turning screen on after layout!");
+                }
+                mService.mPowerManager.wakeUp(SystemClock.uptimeMillis(),
+                        "android.server.wm:TURN_ON");
+            }
+            mService.mTurnOnScreen = false;
+        }
+
+        if (mUpdateRotation) {
+            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
+            if (mService.updateRotationUncheckedLocked(false)) {
+                mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
+            } else {
+                mUpdateRotation = false;
+            }
+        }
+
+        if (mService.mWaitingForDrawnCallback != null ||
+                (mOrientationChangeComplete && !defaultDisplay.isLayoutNeeded()
+                        && !mUpdateRotation)) {
+            mService.checkDrawnWindowsLocked();
+        }
+
+        final int N = mService.mPendingRemove.size();
+        if (N > 0) {
+            if (mService.mPendingRemoveTmp.length < N) {
+                mService.mPendingRemoveTmp = new WindowState[N+10];
+            }
+            mService.mPendingRemove.toArray(mService.mPendingRemoveTmp);
+            mService.mPendingRemove.clear();
+            DisplayContentList displayList = new DisplayContentList();
+            for (i = 0; i < N; i++) {
+                final WindowState w = mService.mPendingRemoveTmp[i];
+                w.removeImmediately();
+                final DisplayContent displayContent = w.getDisplayContent();
+                if (displayContent != null && !displayList.contains(displayContent)) {
+                    displayList.add(displayContent);
+                }
+            }
+
+            for (DisplayContent displayContent : displayList) {
+                mService.mLayersController.assignLayersLocked(displayContent.getWindowList());
+                displayContent.setLayoutNeeded();
+            }
+        }
+
+        // Remove all deferred displays stacks, tasks, and activities.
+        for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) {
+            mChildren.get(displayNdx).checkCompleteDeferredRemoval();
+        }
+
+        if (updateInputWindowsNeeded) {
+            mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
+        }
+        mService.setFocusTaskRegionLocked();
+
+        // Check to see if we are now in a state where the screen should
+        // be enabled, because the window obscured flags have changed.
+        mService.enableScreenIfNeededLocked();
+
+        mService.scheduleAnimationLocked();
+        mService.mWindowPlacerLocked.destroyPendingSurfaces();
+
+        if (DEBUG_WINDOW_TRACE) Slog.e(TAG,
+                "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating());
+    }
+
+    // TODO: Super crazy long method that should be broken down...
+    private void applySurfaceChangesTransaction(boolean recoveringMemory, int defaultDw, int defaultDh) {
+        mHoldScreenWindow = null;
+        mObsuringWindow = null;
+
+        if (mService.mWatermark != null) {
+            mService.mWatermark.positionSurface(defaultDw, defaultDh);
+        }
+        if (mService.mStrictModeFlash != null) {
+            mService.mStrictModeFlash.positionSurface(defaultDw, defaultDh);
+        }
+        if (mService.mCircularDisplayMask != null) {
+            mService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mService.mRotation);
+        }
+        if (mService.mEmulatorDisplayOverlay != null) {
+            mService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
+                    mService.mRotation);
+        }
+
+        boolean focusDisplayed = false;
+
+        final int count = mChildren.size();
+        for (int j = 0; j < count; ++j) {
+            final DisplayContent dc = mChildren.get(j);
+            boolean updateAllDrawn = false;
+            WindowList windows = dc.getWindowList();
+            DisplayInfo displayInfo = dc.getDisplayInfo();
+            final int displayId = dc.getDisplayId();
+            final int dw = displayInfo.logicalWidth;
+            final int dh = displayInfo.logicalHeight;
+            final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
+            final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
+
+            // Reset for each display.
+            mDisplayHasContent = false;
+            mPreferredRefreshRate = 0;
+            mPreferredModeId = 0;
+
+            int repeats = 0;
+            do {
+                repeats++;
+                if (repeats > 6) {
+                    Slog.w(TAG, "Animation repeat aborted after too many iterations");
+                    dc.clearLayoutNeeded();
+                    break;
+                }
+
+                if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
+                        "On entry to LockedInner", dc.pendingLayoutChanges);
+
+                if ((dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0
+                        && mService.mWallpaperControllerLocked.adjustWallpaperWindows()) {
+                    mService.mLayersController.assignLayersLocked(windows);
+                    dc.setLayoutNeeded();
+                }
+
+                if (isDefaultDisplay
+                        && (dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
+                    if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
+                    if (mService.updateOrientationFromAppTokensLocked(true)) {
+                        dc.setLayoutNeeded();
+                        mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
+                    }
+                }
+
+                if ((dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
+                    dc.setLayoutNeeded();
+                }
+
+                // FIRST LOOP: Perform a layout, if needed.
+                if (repeats < LAYOUT_REPEAT_THRESHOLD) {
+                    surfacePlacer.performLayoutLockedInner(dc, repeats == 1,
+                            false /* updateInputWindows */);
+                } else {
+                    Slog.w(TAG, "Layout repeat skipped after too many iterations");
+                }
+
+                // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
+                // it is animating.
+                dc.pendingLayoutChanges = 0;
+
+                if (isDefaultDisplay) {
+                    mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
+                    for (int i = windows.size() - 1; i >= 0; i--) {
+                        WindowState w = windows.get(i);
+                        if (w.mHasSurface) {
+                            mService.mPolicy.applyPostLayoutPolicyLw(
+                                    w, w.mAttrs, w.getParentWindow());
+                        }
+                    }
+                    dc.pendingLayoutChanges |=
+                            mService.mPolicy.finishPostLayoutPolicyLw();
+                    if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
+                            "after finishPostLayoutPolicyLw", dc.pendingLayoutChanges);
+                }
+            } while (dc.pendingLayoutChanges != 0);
+
+            mObscured = false;
+            mSyswin = false;
+            dc.resetDimming();
+
+            // Only used if default window
+            final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
+
+            for (int i = windows.size() - 1; i >= 0; i--) {
+                WindowState w = windows.get(i);
+                final Task task = w.getTask();
+                final boolean obscuredChanged = w.mObscured != mObscured;
+
+                // Update effect.
+                w.mObscured = mObscured;
+                if (!mObscured) {
+                    handleNotObscuredLocked(w, displayInfo);
+                }
+
+                w.applyDimLayerIfNeeded();
+
+                if (isDefaultDisplay && obscuredChanged && w.isVisibleLw()
+                        && mService.mWallpaperControllerLocked.isWallpaperTarget(w)) {
+                    // This is the wallpaper target and its obscured state changed... make sure the
+                    // current wallaper's visibility has been updated accordingly.
+                    mService.mWallpaperControllerLocked.updateWallpaperVisibility();
+                }
+
+                final WindowStateAnimator winAnimator = w.mWinAnimator;
+
+                // If the window has moved due to its containing content frame changing, then
+                // notify the listeners and optionally animate it. Simply checking a change of
+                // position is not enough, because being move due to dock divider is not a trigger
+                // for animation.
+                if (w.hasMoved()) {
+                    // Frame has moved, containing content frame has also moved, and we're not
+                    // currently animating... let's do something.
+                    final int left = w.mFrame.left;
+                    final int top = w.mFrame.top;
+                    final boolean adjustedForMinimizedDockOrIme = task != null
+                            && (task.mStack.isAdjustedForMinimizedDockedStack()
+                            || task.mStack.isAdjustedForIme());
+                    if (mService.okToDisplay()
+                            && (w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
+                            && !w.isDragResizing() && !adjustedForMinimizedDockOrIme
+                            && (task == null || w.getTask().mStack.hasMovementAnimations())
+                            && !w.mWinAnimator.mLastHidden) {
+                        winAnimator.setMoveAnimation(left, top);
+                    }
+
+                    //TODO (multidisplay): Accessibility supported only for the default display.
+                    if (mService.mAccessibilityController != null
+                            && displayId == Display.DEFAULT_DISPLAY) {
+                        mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
+                    }
+
+                    try {
+                        w.mClient.moved(left, top);
+                    } catch (RemoteException e) {
+                    }
+                    w.mMovedByResize = false;
+                }
+
+                //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
+                w.mContentChanged = false;
+
+                // Moved from updateWindowsAndWallpaperLocked().
+                if (w.mHasSurface) {
+                    // Take care of the window being ready to display.
+                    final boolean committed = winAnimator.commitFinishDrawingLocked();
+                    if (isDefaultDisplay && committed) {
+                        if (w.mAttrs.type == TYPE_DREAM) {
+                            // HACK: When a dream is shown, it may at that point hide the lock
+                            // screen. So we need to redo the layout to let the phone window manager
+                            // make this happen.
+                            dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
+                            if (DEBUG_LAYOUT_REPEATS) {
+                                surfacePlacer.debugLayoutRepeats(
+                                        "dream and commitFinishDrawingLocked true",
+                                        dc.pendingLayoutChanges);
+                            }
+                        }
+                        if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
+                            if (DEBUG_WALLPAPER_LIGHT)
+                                Slog.v(TAG, "First draw done in potential wallpaper target " + w);
+                            mWallpaperMayChange = true;
+                            dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+                            if (DEBUG_LAYOUT_REPEATS) {
+                                surfacePlacer.debugLayoutRepeats(
+                                        "wallpaper and commitFinishDrawingLocked true",
+                                        dc.pendingLayoutChanges);
+                            }
+                        }
+                    }
+                    if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) {
+                        // Updates the shown frame before we set up the surface. This is needed
+                        // because the resizing could change the top-left position (in addition to
+                        // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
+                        // position the surface.
+                        //
+                        // If an animation is being started, we can't call this method because the
+                        // animation hasn't processed its initial transformation yet, but in general
+                        // we do want to update the position if the window is animating.
+                        winAnimator.computeShownFrameLocked();
+                    }
+                    winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
+                }
+
+                final AppWindowToken atoken = w.mAppToken;
+                if (DEBUG_STARTING_WINDOW && atoken != null && w == atoken.startingWindow) {
+                    Slog.d(TAG, "updateWindows: starting " + w
+                            + " isOnScreen=" + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
+                            + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
+                }
+                if (atoken != null && (!atoken.allDrawn || !atoken.allDrawnExcludingSaved
+                        || atoken.mAppAnimator.freezingScreen)) {
+                    if (atoken.lastTransactionSequence != mService.mTransactionSequence) {
+                        atoken.lastTransactionSequence = mService.mTransactionSequence;
+                        atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
+                        atoken.numInterestingWindowsExcludingSaved = 0;
+                        atoken.numDrawnWindowsExcludingSaved = 0;
+                        atoken.startingDisplayed = false;
+                    }
+                    if (!atoken.allDrawn && w.mightAffectAllDrawn(false /* visibleOnly */)) {
+                        if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
+                            Slog.v(TAG, "Eval win " + w + ": isDrawn="
+                                    + w.isDrawnLw()
+                                    + ", isAnimationSet=" + winAnimator.isAnimationSet());
+                            if (!w.isDrawnLw()) {
+                                Slog.v(TAG, "Not displayed: s="
+                                        + winAnimator.mSurfaceController
+                                        + " pv=" + w.mPolicyVisibility
+                                        + " mDrawState=" + winAnimator.drawStateToString()
+                                        + " ph=" + w.isParentWindowHidden()
+                                        + " th=" + atoken.hiddenRequested
+                                        + " a=" + winAnimator.mAnimating);
+                            }
+                        }
+                        if (w != atoken.startingWindow) {
+                            if (w.isInteresting()) {
+                                atoken.numInterestingWindows++;
+                                if (w.isDrawnLw()) {
+                                    atoken.numDrawnWindows++;
+                                    if (DEBUG_VISIBILITY || DEBUG_ORIENTATION)
+                                        Slog.v(TAG, "tokenMayBeDrawn: " + atoken
+                                                + " w=" + w + " numInteresting="
+                                                + atoken.numInterestingWindows
+                                                + " freezingScreen="
+                                                + atoken.mAppAnimator.freezingScreen
+                                                + " mAppFreezing=" + w.mAppFreezing);
+                                    updateAllDrawn = true;
+                                }
+                            }
+                        } else if (w.isDrawnLw()) {
+                            mService.mH.sendEmptyMessage(NOTIFY_STARTING_WINDOW_DRAWN);
+                            atoken.startingDisplayed = true;
+                        }
+                    }
+                    if (!atoken.allDrawnExcludingSaved
+                            && w.mightAffectAllDrawn(true /* visibleOnly */)) {
+                        if (w != atoken.startingWindow && w.isInteresting()) {
+                            atoken.numInterestingWindowsExcludingSaved++;
+                            if (w.isDrawnLw() && !w.isAnimatingWithSavedSurface()) {
+                                atoken.numDrawnWindowsExcludingSaved++;
+                                if (DEBUG_VISIBILITY || DEBUG_ORIENTATION)
+                                    Slog.v(TAG, "tokenMayBeDrawnExcludingSaved: " + atoken
+                                            + " w=" + w + " numInteresting="
+                                            + atoken.numInterestingWindowsExcludingSaved
+                                            + " freezingScreen="
+                                            + atoken.mAppAnimator.freezingScreen
+                                            + " mAppFreezing=" + w.mAppFreezing);
+                                updateAllDrawn = true;
+                            }
+                        }
+                    }
+                }
+
+                if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
+                        && w.isDisplayedLw()) {
+                    focusDisplayed = true;
+                }
+
+                mService.updateResizingWindows(w);
+            }
+
+            mService.mDisplayManagerInternal.setDisplayProperties(displayId,
+                    mDisplayHasContent,
+                    mPreferredRefreshRate,
+                    mPreferredModeId,
+                    true /* inTraversal, must call performTraversalInTrans... below */);
+
+            dc.stopDimmingIfNeeded();
+
+            if (updateAllDrawn) {
+                // See if any windows have been drawn, so they (and others associated with them)
+                // can now be shown.
+                dc.updateAllDrawn();
+            }
+        }
+
+        if (focusDisplayed) {
+            mService.mH.sendEmptyMessage(REPORT_LOSING_FOCUS);
+        }
+
+        // Give the display manager a chance to adjust properties
+        // like display rotation if it needs to.
+        mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
+    }
+
+    /**
+     * @param w WindowState this method is applied to.
+     * @param dispInfo info of the display that the window's obscuring state is checked against.
+     */
+    private void handleNotObscuredLocked(final WindowState w, final DisplayInfo dispInfo) {
+        final WindowManager.LayoutParams attrs = w.mAttrs;
+        final int attrFlags = attrs.flags;
+        final boolean canBeSeen = w.isDisplayedLw();
+        final int privateflags = attrs.privateFlags;
+
+        if (canBeSeen && w.isObscuringFullscreen(dispInfo)) {
+            // This window completely covers everything behind it,
+            // so we want to leave all of them as undimmed (for
+            // performance reasons).
+            if (!mObscured) {
+                mObsuringWindow = w;
+            }
+
+            mObscured = true;
+        }
+
+        if (w.mHasSurface && canBeSeen) {
+            if ((attrFlags & FLAG_KEEP_SCREEN_ON) != 0) {
+                mHoldScreen = w.mSession;
+                mHoldScreenWindow = w;
+            } else if (DEBUG_KEEP_SCREEN_ON && w == mService.mLastWakeLockHoldingWindow) {
+                Slog.d(TAG_KEEP_SCREEN_ON, "handleNotObscuredLocked: " + w + " was holding "
+                        + "screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by"
+                        + Debug.getCallers(10));
+            }
+            if (!mSyswin && w.mAttrs.screenBrightness >= 0 && mScreenBrightness < 0) {
+                mScreenBrightness = w.mAttrs.screenBrightness;
+            }
+            if (!mSyswin && w.mAttrs.buttonBrightness >= 0 && mButtonBrightness < 0) {
+                mButtonBrightness = w.mAttrs.buttonBrightness;
+            }
+            if (!mSyswin && w.mAttrs.userActivityTimeout >= 0 && mUserActivityTimeout < 0) {
+                mUserActivityTimeout = w.mAttrs.userActivityTimeout;
+            }
+
+            final int type = attrs.type;
+            if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
+                    || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+                mSyswin = true;
+            }
+
+            // This function assumes that the contents of the default display are processed first
+            // before secondary displays.
+            final DisplayContent displayContent = w.getDisplayContent();
+            if (displayContent != null && displayContent.isDefaultDisplay) {
+                // While a dream or keyguard is showing, obscure ordinary application content on
+                // secondary displays (by forcibly enabling mirroring unless there is other content
+                // we want to show) but still allow opaque keyguard dialogs to be shown.
+                if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+                    mObscureApplicationContentOnSecondaryDisplays = true;
+                }
+                mDisplayHasContent = true;
+            } else if (displayContent != null &&
+                    (!mObscureApplicationContentOnSecondaryDisplays
+                            || (mObscured && type == TYPE_KEYGUARD_DIALOG))) {
+                // Allow full screen keyguard presentation dialogs to be seen.
+                mDisplayHasContent = true;
+            }
+            if (mPreferredRefreshRate == 0 && w.mAttrs.preferredRefreshRate != 0) {
+                mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
+            }
+            if (mPreferredModeId == 0 && w.mAttrs.preferredDisplayModeId != 0) {
+                mPreferredModeId = w.mAttrs.preferredDisplayModeId;
+            }
+            if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) {
+                mSustainedPerformanceModeCurrent = true;
+            }
+        }
+    }
+
+    boolean copyAnimToLayoutParams() {
+        boolean doRequest = false;
+
+        final int bulkUpdateParams = mService.mAnimator.mBulkUpdateParams;
+        if ((bulkUpdateParams & SET_UPDATE_ROTATION) != 0) {
+            mUpdateRotation = true;
+            doRequest = true;
+        }
+        if ((bulkUpdateParams & SET_WALLPAPER_MAY_CHANGE) != 0) {
+            mWallpaperMayChange = true;
+            doRequest = true;
+        }
+        if ((bulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0) {
+            mWallpaperForceHidingChanged = true;
+            doRequest = true;
+        }
+        if ((bulkUpdateParams & SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
+            mOrientationChangeComplete = false;
+        } else {
+            mOrientationChangeComplete = true;
+            mLastWindowFreezeSource = mService.mAnimator.mLastWindowFreezeSource;
+            if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
+                doRequest = true;
+            }
+        }
+        if ((bulkUpdateParams & SET_TURN_ON_SCREEN) != 0) {
+            mService.mTurnOnScreen = true;
+        }
+        if ((bulkUpdateParams & SET_WALLPAPER_ACTION_PENDING) != 0) {
+            mWallpaperActionPending = true;
+        }
+
+        return doRequest;
+    }
+
+    private static int toBrightnessOverride(float value) {
+        return (int)(value * PowerManager.BRIGHTNESS_ON);
+    }
+
+    void enableSurfaceTrace(ParcelFileDescriptor pfd) {
+        final FileDescriptor fd = pfd.getFileDescriptor();
+        if (mSurfaceTraceEnabled) {
+            disableSurfaceTrace();
+        }
+        mSurfaceTraceEnabled = true;
+        mRemoteEventTrace = new RemoteEventTrace(mService, fd);
+        mSurfaceTraceFd = pfd;
+        for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) {
+            final DisplayContent dc = mChildren.get(displayNdx);
+            dc.enableSurfaceTrace(fd);
+        }
+    }
+
+    void disableSurfaceTrace() {
+        mSurfaceTraceEnabled = false;
+        mRemoteEventTrace = null;
+        mSurfaceTraceFd = null;
+        for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) {
+            final DisplayContent dc = mChildren.get(displayNdx);
+            dc.disableSurfaceTrace();
+        }
+    }
+
+    void dumpDisplayContents(PrintWriter pw) {
+        pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
+        if (mService.mDisplayReady) {
+            final int count = mChildren.size();
+            for (int i = 0; i < count; ++i) {
+                final DisplayContent displayContent = mChildren.get(i);
+                displayContent.dump("  ", pw);
+            }
+        } else {
+            pw.println("  NO DISPLAY");
+        }
+    }
+
+    void dumpLayoutNeededDisplayIds(PrintWriter pw) {
+        if (!isLayoutNeeded()) {
+            return;
+        }
+        pw.print("  mLayoutNeeded on displays=");
+        final int count = mChildren.size();
+        for (int displayNdx = 0; displayNdx < count; ++displayNdx) {
+            final DisplayContent displayContent = mChildren.get(displayNdx);
+            if (displayContent.isLayoutNeeded()) {
+                pw.print(displayContent.getDisplayId());
+            }
+        }
+        pw.println();
+    }
+
+    void dumpWindowsNoHeader(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows) {
+        final int numDisplays = mChildren.size();
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final WindowList windowList = mChildren.get(displayNdx).getWindowList();
+            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
+                final WindowState w = windowList.get(winNdx);
+                if (windows == null || windows.contains(w)) {
+                    pw.println("  Window #" + winNdx + " " + w + ":");
+                    w.dump(pw, "    ", dumpAll || windows != null);
+                }
+            }
+        }
+    }
+
+    @Override
+    String getName() {
+        return "ROOT";
+    }
+}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 9e8c609..f6598c1 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -70,12 +70,6 @@
     // Whether mBounds is fullscreen
     private boolean mFillsParent = true;
 
-    /**
-     * Contains configurations settings that are different from the parent configuration due to
-     * stack specific operations. E.g. {@link #setBounds}.
-     */
-    Configuration mOverrideConfig = Configuration.EMPTY;
-
     // For comparison with DisplayContent bounds.
     private Rect mTmpRect = new Rect();
     // For handling display rotations.
@@ -120,8 +114,9 @@
             }
         }
 
-        if (wtoken.mParent != null) {
-            wtoken.mParent.removeChild(wtoken);
+        final WindowContainer parent = wtoken.getParent();
+        if (parent != null) {
+            parent.removeChild(wtoken);
         }
         addChild(wtoken, addPos);
         wtoken.mTask = this;
@@ -153,7 +148,7 @@
         if (content != null) {
             content.mDimLayerController.removeDimLayerUser(this);
         }
-        mParent.removeChild(this);
+        getParent().removeChild(this);
         mService.mTaskIdToTask.delete(mTaskId);
     }
 
@@ -165,7 +160,7 @@
         if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: removing taskId=" + mTaskId
                 + " from stack=" + mStack);
         EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "moveTask");
-        mParent.removeChild(this);
+        getParent().removeChild(this);
         stack.addTask(this, toTop);
     }
 
@@ -254,7 +249,7 @@
         if (displayContent != null) {
             displayContent.mDimLayerController.updateDimLayer(this);
         }
-        mOverrideConfig = mFillsParent ? Configuration.EMPTY : overrideConfig;
+        onOverrideConfigurationChanged(mFillsParent ? Configuration.EMPTY : overrideConfig);
         return boundsChange;
     }
 
@@ -321,8 +316,7 @@
      */
     void prepareFreezingBounds() {
         mPreparedFrozenBounds.set(mBounds);
-        mPreparedFrozenMergedConfig.setTo(mService.mGlobalConfiguration);
-        mPreparedFrozenMergedConfig.updateFrom(mOverrideConfig);
+        mPreparedFrozenMergedConfig.setTo(getConfiguration());
     }
 
     /**
@@ -334,9 +328,9 @@
      *                    bounds's bottom; false if the task's top should be aligned
      *                    the adjusted bounds's top.
      */
-    void alignToAdjustedBounds(
-            Rect adjustedBounds, Rect tempInsetBounds, boolean alignBottom) {
-        if (!isResizeable() || mOverrideConfig == Configuration.EMPTY) {
+    void alignToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds, boolean alignBottom) {
+        final Configuration overrideConfig = getOverrideConfiguration();
+        if (!isResizeable() || Configuration.EMPTY.equals(overrideConfig)) {
             return;
         }
 
@@ -348,7 +342,7 @@
             mTmpRect2.offsetTo(adjustedBounds.left, adjustedBounds.top);
         }
         setTempInsetBounds(tempInsetBounds);
-        resizeLocked(mTmpRect2, mOverrideConfig, false /* forced */);
+        resizeLocked(mTmpRect2, overrideConfig, false /* forced */);
     }
 
     /** Return true if the current bound can get outputted to the rest of the system as-is. */
@@ -500,12 +494,12 @@
         mTmpRect2.set(mBounds);
 
         if (!StackId.isTaskResizeAllowed(mStack.mStackId)) {
-            setBounds(mTmpRect2, mOverrideConfig);
+            setBounds(mTmpRect2, getOverrideConfiguration());
             return;
         }
 
         displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
-        if (setBounds(mTmpRect2, mOverrideConfig) != BOUNDS_CHANGE_NONE) {
+        if (setBounds(mTmpRect2, getOverrideConfiguration()) != BOUNDS_CHANGE_NONE) {
             // Post message to inform activity manager of the bounds change simulating a one-way
             // call. We do this to prevent a deadlock between window manager lock and activity
             // manager lock been held.
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 21db840..6887312 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -478,7 +478,7 @@
     private int getDimSide(int x) {
         if (mTask.mStack.mStackId != FREEFORM_WORKSPACE_STACK_ID
                 || !mTask.mStack.fillsParent()
-                || mService.mGlobalConfiguration.orientation != ORIENTATION_LANDSCAPE) {
+                || mTask.mStack.getConfiguration().orientation != ORIENTATION_LANDSCAPE) {
             return CTRL_NONE;
         }
 
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index b24a06a..e98fc39 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -110,7 +110,7 @@
 
     /** Detach this stack from its display when animation completes. */
     // TODO: maybe tie this to WindowContainer#removeChild some how...
-    boolean mDeferDetach;
+    boolean mDeferRemoval;
 
     private final Rect mTmpAdjustedBounds = new Rect();
     private boolean mAdjustedForIme;
@@ -230,7 +230,7 @@
             }
         }
         alignTasksToAdjustedBounds(adjusted ? mAdjustedBounds : mBounds, insetBounds);
-        mDisplayContent.layoutNeeded = true;
+        mDisplayContent.setLayoutNeeded();
     }
 
     private void alignTasksToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds) {
@@ -354,11 +354,8 @@
         // If the rotation or density didn't match, we'll update it in onConfigurationChanged.
     }
 
-    boolean onConfigurationChanged() {
-        return updateBoundsAfterConfigChange();
-    }
-
-    private boolean updateBoundsAfterConfigChange() {
+    /** @return true if bounds were updated to some non-empty value. */
+    boolean updateBoundsAfterConfigChange() {
         if (mDisplayContent == null) {
             // If the stack is already detached we're not updating anything,
             // as it's going away soon anyway.
@@ -459,7 +456,7 @@
 
         // Snap the position to a target.
         final int rotation = displayInfo.rotation;
-        final int orientation = mService.mGlobalConfiguration.orientation;
+        final int orientation = mDisplayContent.getConfiguration().orientation;
         mService.mPolicy.getStableInsetsLw(rotation, displayWidth, displayHeight, outBounds);
         final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm(
                 mService.mContext.getResources(), displayWidth, displayHeight,
@@ -493,7 +490,9 @@
     void positionTask(Task task, int position, boolean showForAllUsers) {
         final boolean canShowTask =
                 showForAllUsers || mService.isCurrentProfileLocked(task.mUserId);
-        removeChild(task);
+        if (mChildren.contains(task)) {
+            super.removeChild(task);
+        }
         int stackSize = mChildren.size();
         int minPosition = 0;
         int maxPosition = stackSize;
@@ -589,10 +588,6 @@
     @Override
     void removeChild(Task task) {
         if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "removeChild: task=" + task);
-        if (!mChildren.contains(task)) {
-            Slog.e(TAG_WM, "removeChild: task=" + this + " not found.");
-            return;
-        }
 
         super.removeChild(task);
 
@@ -600,7 +595,7 @@
             if (mChildren.isEmpty()) {
                 mDisplayContent.moveStack(this, false);
             }
-            mDisplayContent.layoutNeeded = true;
+            mDisplayContent.setLayoutNeeded();
         }
         for (int appNdx = mExitingAppTokens.size() - 1; appNdx >= 0; --appNdx) {
             final AppWindowToken wtoken = mExitingAppTokens.get(appNdx);
@@ -715,7 +710,7 @@
                     di.logicalWidth,
                     di.logicalHeight,
                     dockDividerWidth,
-                    mService.mGlobalConfiguration.orientation == ORIENTATION_PORTRAIT,
+                    mDisplayContent.getConfiguration().orientation == ORIENTATION_PORTRAIT,
                     mTmpRect2).getMiddleTarget().position;
 
             if (dockOnTopOrLeft) {
@@ -764,12 +759,34 @@
                 1 /*allowResizeInDockedMode*/, bounds).sendToTarget();
     }
 
-    // TODO: Should this really be removeImmidiately or removeChild?
-    boolean detachFromDisplay() {
+    @Override
+    void removeIfPossible() {
+        if (isAnimating()) {
+            mDeferRemoval = true;
+            return;
+        }
+        removeImmediately();
+    }
+
+    @Override
+    void removeImmediately() {
+        super.removeImmediately();
+
+        mDisplayContent.mDimLayerController.removeDimLayerUser(this);
         EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
-        boolean didSomething = super.detachFromDisplay();
-        close();
-        return didSomething;
+
+        if (mAnimationBackgroundSurface != null) {
+            mAnimationBackgroundSurface.destroySurface();
+            mAnimationBackgroundSurface = null;
+        }
+        mDisplayContent = null;
+
+        mService.mWindowPlacerLocked.requestTraversal();
+
+        if (mStackId == DOCKED_STACK_ID) {
+            mService.getDefaultDisplayContentLocked().mDividerControllerLocked
+                    .notifyDockedStackExistsChanged(false);
+        }
     }
 
     void resetAnimationBackgroundAnimator() {
@@ -801,14 +818,6 @@
         }
     }
 
-    void close() {
-        if (mAnimationBackgroundSurface != null) {
-            mAnimationBackgroundSurface.destroySurface();
-            mAnimationBackgroundSurface = null;
-        }
-        mDisplayContent = null;
-    }
-
     /**
      * Adjusts the stack bounds if the IME is visible.
      *
@@ -1068,7 +1077,7 @@
 
         final Rect insetBounds = mImeGoingAway ? mBounds : mFullyAdjustedImeBounds;
         task.alignToAdjustedBounds(mAdjustedBounds, insetBounds, getDockSide() == DOCKED_TOP);
-        mDisplayContent.layoutNeeded = true;
+        mDisplayContent.setLayoutNeeded();
     }
 
     boolean isAdjustedForMinimizedDockedStack() {
@@ -1077,7 +1086,7 @@
 
     public void dump(String prefix, PrintWriter pw) {
         pw.println(prefix + "mStackId=" + mStackId);
-        pw.println(prefix + "mDeferDetach=" + mDeferDetach);
+        pw.println(prefix + "mDeferRemoval=" + mDeferRemoval);
         pw.println(prefix + "mFillsParent=" + mFillsParent);
         pw.println(prefix + "mBounds=" + mBounds.toShortString());
         if (mMinimizeAmount != 0f) {
@@ -1170,7 +1179,7 @@
             return DOCKED_INVALID;
         }
         mDisplayContent.getLogicalDisplayRect(mTmpRect);
-        final int orientation = mService.mGlobalConfiguration.orientation;
+        final int orientation = mDisplayContent.getConfiguration().orientation;
         return getDockSideUnchecked(bounds, mTmpRect, orientation);
     }
 
@@ -1411,8 +1420,8 @@
         if (isAnimating()) {
             return true;
         }
-        if (mDeferDetach) {
-            mDisplayContent.detachChild(this);
+        if (mDeferRemoval) {
+            removeImmediately();
         }
 
         return super.checkCompleteDeferredRemoval();
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index b269d4c..58439eb 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -641,7 +641,7 @@
     }
 
     boolean adjustWallpaperWindows() {
-        mService.mWindowPlacerLocked.mWallpaperMayChange = false;
+        mService.mRoot.mWallpaperMayChange = false;
 
         final WindowList windows = mService.getDefaultWindowListLocked();
         // First find top-most window that has asked to be on top of the wallpaper;
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index a13b6a1..fb6b09a 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -40,7 +40,6 @@
 import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
 import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
 import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
-import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
 
 import android.content.Context;
@@ -528,7 +527,7 @@
     }
 
     private void updateWallpaperLocked(int displayId) {
-        mService.getDisplayContentLocked(displayId).resetAnimationBackgroundAnimator();
+        mService.mRoot.getDisplayContentOrCreate(displayId).resetAnimationBackgroundAnimator();
 
         final WindowList windows = mService.getWindowListLocked(displayId);
         WindowState detachedWallpaper = null;
@@ -615,7 +614,8 @@
             final int numDisplays = mDisplayContentsAnimators.size();
             for (int i = 0; i < numDisplays; i++) {
                 final int displayId = mDisplayContentsAnimators.keyAt(i);
-                final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
+                final DisplayContent displayContent = mService.mRoot.getDisplayContentOrCreate(
+                        displayId);
                 displayContent.stepAppWindowsAnimation(mCurrentTime);
                 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
 
@@ -654,7 +654,8 @@
 
             for (int i = 0; i < numDisplays; i++) {
                 final int displayId = mDisplayContentsAnimators.keyAt(i);
-                final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
+                final DisplayContent displayContent = mService.mRoot.getDisplayContentOrCreate(
+                        displayId);
 
                 displayContent.checkAppWindowsReadyToShow();
 
@@ -691,22 +692,10 @@
                     TAG, "<<< CLOSE TRANSACTION animateLocked");
         }
 
-        boolean hasPendingLayoutChanges = false;
-        final int numDisplays = mService.mDisplayContents.size();
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
-            final int pendingChanges = getPendingLayoutChanges(displayContent.getDisplayId());
-            if ((pendingChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
-                mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
-            }
-            if (pendingChanges != 0) {
-                hasPendingLayoutChanges = true;
-            }
-        }
-
+        boolean hasPendingLayoutChanges = mService.mRoot.hasPendingLayoutChanges(this);
         boolean doRequest = false;
         if (mBulkUpdateParams != 0) {
-            doRequest = mWindowPlacerLocked.copyAnimToLayoutParamsLocked();
+            doRequest = mService.mRoot.copyAnimToLayoutParams();
         }
 
         if (hasPendingLayoutChanges || doRequest) {
@@ -725,7 +714,8 @@
         }
 
         if (mRemoveReplacedWindows) {
-            removeReplacedWindowsLocked();
+            mService.mRoot.removeReplacedWindows();
+            mRemoveReplacedWindows = false;
         }
 
         mService.stopUsingSavedSurfaceLocked();
@@ -740,28 +730,6 @@
         }
     }
 
-    private void removeReplacedWindowsLocked() {
-        if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
-        mService.openSurfaceTransaction();
-        try {
-            for (int i = mService.mDisplayContents.size() - 1; i >= 0; i--) {
-                DisplayContent display = mService.mDisplayContents.valueAt(i);
-                final WindowList windows = mService.getWindowListLocked(display.getDisplayId());
-                for (int j = windows.size() - 1; j >= 0; j--) {
-                    final WindowState win = windows.get(j);
-                    final AppWindowToken aToken = win.mAppToken;
-                    if (aToken != null) {
-                        aToken.removeReplacedWindowIfNeeded(win);
-                    }
-                }
-            }
-        } finally {
-            mService.closeSurfaceTransaction();
-            if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
-        }
-        mRemoveReplacedWindows = false;
-    }
-
     private static String bulkUpdateParamsToString(int bulkUpdateParams) {
         StringBuilder builder = new StringBuilder(128);
         if ((bulkUpdateParams & WindowSurfacePlacer.SET_UPDATE_ROTATION) != 0) {
@@ -832,7 +800,7 @@
         if (displayId < 0) {
             return 0;
         }
-        final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
+        final DisplayContent displayContent = mService.mRoot.getDisplayContentOrCreate(displayId);
         return (displayContent != null) ? displayContent.pendingLayoutChanges : 0;
     }
 
@@ -840,7 +808,7 @@
         if (displayId < 0) {
             return;
         }
-        final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
+        final DisplayContent displayContent = mService.mRoot.getDisplayContentOrCreate(displayId);
         if (displayContent != null) {
             displayContent.pendingLayoutChanges |= changes;
         }
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 106284a..8777d88 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -17,9 +17,9 @@
 package com.android.server.wm;
 
 import android.annotation.CallSuper;
+import android.content.res.Configuration;
 import android.view.animation.Animation;
 
-import java.io.PrintWriter;
 import java.util.Comparator;
 import java.util.LinkedList;
 
@@ -35,13 +35,33 @@
  */
 class WindowContainer<E extends WindowContainer> implements Comparable<WindowContainer> {
 
-    // The parent of this window container.
-    protected WindowContainer mParent = null;
+    /**
+     * The parent of this window container.
+     * For removing or setting new parent {@link #setParent} should be used, because it also
+     * performs configuration updates based on new parent's settings.
+     */
+    private WindowContainer mParent = null;
 
     // List of children for this window container. List is in z-order as the children appear on
     // screen with the top-most window container at the tail of the list.
     protected final LinkedList<E> mChildren = new LinkedList();
 
+    /** Contains override configuration settings applied to this window container. */
+    private Configuration mOverrideConfiguration = new Configuration();
+
+    /**
+     * Contains full configuration applied to this window container. Corresponds to full parent's
+     * config with applied {@link #mOverrideConfiguration}.
+     */
+    private Configuration mFullConfiguration = new Configuration();
+
+    /**
+     * Contains merged override configuration settings from the top of the hierarchy down to this
+     * particular instance. It is different from {@link #mFullConfiguration} because it starts from
+     * topmost container's override config instead of global config.
+     */
+    private Configuration mMergedOverrideConfiguration = new Configuration();
+
     // The specified orientation for this window container.
     protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
 
@@ -49,6 +69,14 @@
         return mParent;
     }
 
+    final protected void setParent(WindowContainer parent) {
+        mParent = parent;
+        // Update full configuration of this container and all its children.
+        onConfigurationChanged(mParent != null ? mParent.mFullConfiguration : Configuration.EMPTY);
+        // Update merged override configuration of this container and all its children.
+        onMergedOverrideConfigurationChanged();
+    }
+
     // Temp. holders for a chain of containers we are currently processing.
     private final LinkedList<WindowContainer> mTmpChain1 = new LinkedList();
     private final LinkedList<WindowContainer> mTmpChain2 = new LinkedList();
@@ -62,12 +90,12 @@
      */
     @CallSuper
     protected void addChild(E child, Comparator<E> comparator) {
-        if (child.mParent != null) {
-            throw new IllegalArgumentException("addChild: container=" + child
-                    + " is already a child of container=" + child.mParent
-                    + " can't add to container=" + this);
+        if (child.getParent() != null) {
+            throw new IllegalArgumentException("addChild: container=" + child.getName()
+                    + " is already a child of container=" + child.getParent().getName()
+                    + " can't add to container=" + getName());
         }
-        child.mParent = this;
+        child.setParent(this);
 
         if (mChildren.isEmpty() || comparator == null) {
             mChildren.add(child);
@@ -88,12 +116,12 @@
     /** Adds the input window container has a child of this container at the input index. */
     @CallSuper
     protected void addChild(E child, int index) {
-        if (child.mParent != null) {
-            throw new IllegalArgumentException("addChild: container=" + child
-                    + " is already a child of container=" + child.mParent
-                    + " can't add to container=" + this);
+        if (child.getParent() != null) {
+            throw new IllegalArgumentException("addChild: container=" + child.getName()
+                    + " is already a child of container=" + child.getParent().getName()
+                    + " can't add to container=" + getName());
         }
-        child.mParent = this;
+        child.setParent(this);
         mChildren.add(index, child);
     }
 
@@ -105,10 +133,10 @@
     @CallSuper
     void removeChild(E child) {
         if (mChildren.remove(child)) {
-            child.mParent = null;
+            child.setParent(null);
         } else {
-            throw new IllegalArgumentException("removeChild: container=" + child
-                    + " is not a child of container=" + this);
+            throw new IllegalArgumentException("removeChild: container=" + child.getName()
+                    + " is not a child of container=" + getName());
         }
     }
 
@@ -159,6 +187,73 @@
         return false;
     }
 
+    /**
+     * Returns full configuration applied to this window container.
+     * This method should be used for getting settings applied in each particular level of the
+     * hierarchy.
+     */
+    Configuration getConfiguration() {
+        return mFullConfiguration;
+    }
+
+    /**
+     * Notify that parent config changed and we need to update full configuration.
+     * @see #mFullConfiguration
+     */
+    void onConfigurationChanged(Configuration newParentConfig) {
+        mFullConfiguration.setTo(newParentConfig);
+        mFullConfiguration.updateFrom(mOverrideConfiguration);
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer child = mChildren.get(i);
+            child.onConfigurationChanged(mFullConfiguration);
+        }
+    }
+
+    /** Returns override configuration applied to this window container. */
+    Configuration getOverrideConfiguration() {
+        return mOverrideConfiguration;
+    }
+
+    /**
+     * Update override configuration and recalculate full config.
+     * @see #mOverrideConfiguration
+     * @see #mFullConfiguration
+     */
+    void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+        mOverrideConfiguration.setTo(overrideConfiguration);
+        // Update full configuration of this container and all its children.
+        onConfigurationChanged(mParent != null ? mParent.getConfiguration() : Configuration.EMPTY);
+        // Update merged override config of this container and all its children.
+        onMergedOverrideConfigurationChanged();
+    }
+
+    /**
+     * Get merged override configuration from the top of the hierarchy down to this
+     * particular instance. This should be reported to client as override config.
+     */
+    Configuration getMergedOverrideConfiguration() {
+        return mMergedOverrideConfiguration;
+    }
+
+    /**
+     * Update merged override configuration based on corresponding parent's config and notify all
+     * its children. If there is no parent, merged override configuration will set equal to current
+     * override config.
+     * @see #mMergedOverrideConfiguration
+     */
+    private void onMergedOverrideConfigurationChanged() {
+        if (mParent != null) {
+            mMergedOverrideConfiguration.setTo(mParent.getMergedOverrideConfiguration());
+            mMergedOverrideConfiguration.updateFrom(mOverrideConfiguration);
+        } else {
+            mMergedOverrideConfiguration.setTo(mOverrideConfiguration);
+        }
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer child = mChildren.get(i);
+            child.onMergedOverrideConfigurationChanged();
+        }
+    }
+
     void setWaitingForDrawnIfResizingChanged() {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final WindowContainer wc = mChildren.get(i);
@@ -187,15 +282,6 @@
         }
     }
 
-    boolean detachFromDisplay() {
-        boolean didSomething = false;
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final WindowContainer wc = mChildren.get(i);
-            didSomething |= wc.detachFromDisplay();
-        }
-        return didSomething;
-    }
-
     void forceWindowsScaleableInTransaction(boolean force) {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final WindowContainer wc = mChildren.get(i);
@@ -478,12 +564,14 @@
      * Dumps the names of this container children in the input print writer indenting each
      * level with the input prefix.
      */
-    void dumpChildrenNames(PrintWriter pw, String prefix) {
-        final String childPrefix = prefix + prefix;
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
+    void dumpChildrenNames(StringBuilder out, String prefix) {
+        final String childPrefix = prefix + " ";
+        out.append(getName() + "\n");
+        final int count = mChildren.size();
+        for (int i = 0; i < count; i++) {
             final WindowContainer wc = mChildren.get(i);
-            pw.println("#" + i + " " + getName());
-            wc.dumpChildrenNames(pw, childPrefix);
+            out.append(childPrefix + "#" + i + " ");
+            wc.dumpChildrenNames(out, childPrefix);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a3c830a..310ad5a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -129,7 +129,6 @@
 import com.android.internal.app.IAssistScreenshotReceiver;
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.policy.IShortcutService;
-import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodClient;
@@ -173,9 +172,7 @@
 import static android.app.StatusBarManager.DISABLE_MASK;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.view.WindowManager.DOCKED_BOTTOM;
 import static android.view.WindowManager.DOCKED_INVALID;
-import static android.view.WindowManager.DOCKED_TOP;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
@@ -217,7 +214,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
@@ -240,7 +236,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_VERBOSE_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
@@ -534,9 +529,10 @@
      * LAST_ANR_LIFETIME_DURATION_MSECS */
     String mLastANRState;
 
-    /** All DisplayContents in the world, kept here */
-    SparseArray<DisplayContent> mDisplayContents = new SparseArray<>(2);
+    // The root of the device window hierarchy.
+    RootWindowContainer mRoot;
 
+    // TODO: Move several of this states to the RootWindowContainer
     int mRotation = 0;
     int mLastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     boolean mAltOrientation = false;
@@ -548,8 +544,6 @@
 
     private final SparseIntArray mTmpTaskIds = new SparseIntArray();
 
-    private final ArrayList<Integer> mChangedStackList = new ArrayList();
-
     boolean mForceResizableTasks = false;
 
     int getDragLayerLocked() {
@@ -598,12 +592,6 @@
     // State while inside of layoutAndPlaceSurfacesLocked().
     boolean mFocusMayChange;
 
-    /**
-     * Current global configuration information. Contains general settings for the entire system,
-     * corresponds to the configuration of the default display.
-     */
-    Configuration mGlobalConfiguration = new Configuration();
-
     // This is held as long as we have the screen frozen, to give us time to
     // perform a rotation animation when turning off shows the lock screen which
     // changes the orientation.
@@ -703,6 +691,7 @@
 
     boolean mAnimateWallpaperWithTarget;
 
+    // TODO: Move to RootWindowContainer
     AppWindowToken mFocusedApp = null;
 
     PowerManager mPowerManager;
@@ -747,6 +736,7 @@
 
     /** All of the TaskStacks in the window manager, unordered. For an ordered list call
      * DisplayContent.getStacks(). */
+    // TODO: Don't believe this is needed with the WindowContainer model.
     SparseArray<TaskStack> mStackIdToStack = new SparseArray<>();
 
     private final PointerEventDispatcher mPointerEventDispatcher;
@@ -886,17 +876,11 @@
     // since they won't be notified through the app window animator.
     final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>();
 
-    // State for the RemoteSurfaceTrace system used in testing. If this is enabled SurfaceControl
-    // instances will be replaced with an instance that writes a binary representation of all
-    // commands to mSurfaceTraceFd.
-    boolean mSurfaceTraceEnabled;
-    ParcelFileDescriptor mSurfaceTraceFd;
-    RemoteEventTrace mRemoteEventTrace;
 
     void openSurfaceTransaction() {
         synchronized (mWindowMap) {
-            if (mSurfaceTraceEnabled) {
-                mRemoteEventTrace.openSurfaceTransaction();
+            if (mRoot.mSurfaceTraceEnabled) {
+                mRoot.mRemoteEventTrace.openSurfaceTransaction();
             }
             SurfaceControl.openTransaction();
         }
@@ -904,8 +888,8 @@
 
     void closeSurfaceTransaction() {
         synchronized (mWindowMap) {
-            if (mSurfaceTraceEnabled) {
-                mRemoteEventTrace.closeSurfaceTransaction();
+            if (mRoot.mSurfaceTraceEnabled) {
+                mRoot.mRemoteEventTrace.closeSurfaceTransaction();
             }
             SurfaceControl.closeTransaction();
         }
@@ -978,6 +962,7 @@
     private WindowManagerService(Context context, InputManagerService inputManager,
             boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
             WindowManagerPolicy policy) {
+        mRoot = new RootWindowContainer(this);
         mContext = context;
         mHaveInputMethods = haveInputMethods;
         mAllowBootMessages = showBootMsgs;
@@ -1504,7 +1489,7 @@
                 throw new IllegalStateException("Display has not been initialialized");
             }
 
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
             if (displayContent == null) {
                 Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: "
                         + displayId + ".  Aborting.");
@@ -1955,39 +1940,25 @@
 
     @Override
     public void enableSurfaceTrace(ParcelFileDescriptor pfd) {
-        int callingUid = Binder.getCallingUid();
+        final int callingUid = Binder.getCallingUid();
         if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) {
             throw new SecurityException("Only shell can call enableSurfaceTrace");
         }
-        final FileDescriptor fd = pfd.getFileDescriptor();
 
         synchronized (mWindowMap) {
-            if (mSurfaceTraceEnabled) {
-                disableSurfaceTrace();
-            }
-            mSurfaceTraceEnabled = true;
-            mRemoteEventTrace = new RemoteEventTrace(this, fd);
-            mSurfaceTraceFd = pfd;
-            for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
-                DisplayContent dc = mDisplayContents.valueAt(displayNdx);
-                dc.enableSurfaceTrace(fd);
-            }
+            mRoot.enableSurfaceTrace(pfd);
         }
     }
 
     @Override
     public void disableSurfaceTrace() {
-        int callingUid = Binder.getCallingUid();
+        final int callingUid = Binder.getCallingUid();
         if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID &&
             callingUid != Process.SYSTEM_UID) {
             throw new SecurityException("Only shell can call disableSurfaceTrace");
         }
-        mSurfaceTraceEnabled = false;
-        mRemoteEventTrace = null;
-        mSurfaceTraceFd = null;
-        for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
-            DisplayContent dc = mDisplayContents.valueAt(displayNdx);
-            dc.disableSurfaceTrace();
+        synchronized (mWindowMap) {
+            mRoot.disableSurfaceTrace();
         }
     }
 
@@ -2004,15 +1975,7 @@
         synchronized(mWindowMap) {
             mScreenCaptureDisabled.put(userId, disabled);
             // Update secure surface for all windows belonging to this user.
-            for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
-                WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
-                for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
-                    final WindowState win = windows.get(winNdx);
-                    if (win.mHasSurface && userId == UserHandle.getUserId(win.mOwnerUid)) {
-                        win.mWinAnimator.setSecureLocked(disabled);
-                    }
-                }
-            }
+            mRoot.setSecureSurfaceState(userId, disabled);
         }
     }
 
@@ -2095,20 +2058,7 @@
 
     public void updateAppOpsState() {
         synchronized(mWindowMap) {
-            final int numDisplays = mDisplayContents.size();
-            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
-                final int numWindows = windows.size();
-                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
-                    final WindowState win = windows.get(winNdx);
-                    if (win.mAppOp != AppOpsManager.OP_NONE) {
-                        final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
-                                win.getOwningPackage());
-                        win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED ||
-                                mode == AppOpsManager.MODE_DEFAULT);
-                    }
-                }
-            }
+            mRoot.updateAppOpsState();
         }
     }
 
@@ -2674,7 +2624,7 @@
     }
 
     public boolean outOfMemoryWindow(Session session, IWindow client) {
-        long origId = Binder.clearCallingIdentity();
+        final long origId = Binder.clearCallingIdentity();
 
         try {
             synchronized (mWindowMap) {
@@ -2682,7 +2632,7 @@
                 if (win == null) {
                     return false;
                 }
-                return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false);
+                return mRoot.reclaimSomeSurfaceMemory(win.mWinAnimator, "from-client", false);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -2718,7 +2668,8 @@
         // is running.
         Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked");
         if (okToDisplay()) {
-            DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
+            final DisplayContent displayContent = atoken.mTask.getDisplayContent();
+            final DisplayInfo displayInfo = displayContent.getDisplayInfo();
             final int width = displayInfo.appWidth;
             final int height = displayInfo.appHeight;
             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
@@ -2755,10 +2706,10 @@
             if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
                     + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
                     + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
-            Animation a = mAppTransition.loadAnimation(lp, transit, enter,
-                    mGlobalConfiguration.uiMode, mGlobalConfiguration.orientation, frame,
-                    displayFrame, insets, surfaceInsets, isVoiceInteraction, freeform,
-                    atoken.mTask.mTaskId);
+            final Configuration displayConfig = displayContent.getConfiguration();
+            Animation a = mAppTransition.loadAnimation(lp, transit, enter, displayConfig.uiMode,
+                    displayConfig.orientation, frame, displayFrame, insets, surfaceInsets,
+                    isVoiceInteraction, freeform, atoken.mTask.mTaskId);
             if (a != null) {
                 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken);
                 final int containingWidth = frame.width();
@@ -3049,7 +3000,11 @@
         Configuration config = null;
 
         if (updateOrientationFromAppTokensLocked(false)) {
-            if (freezeThisOneIfNeeded != null) {
+            // If we changed the orientation but mOrientationChangeComplete is
+            // already true, we used seamless rotation, and we don't need
+            // to freeze the screen.
+            if (freezeThisOneIfNeeded != null &&
+                    !mRoot.mOrientationChangeComplete) {
                 final AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded);
                 if (atoken != null) {
                     atoken.startFreezingScreen();
@@ -3069,7 +3024,7 @@
             if (currentConfig.diff(mTempConfiguration) != 0) {
                 mWaitingForConfig = true;
                 final DisplayContent displayContent = getDefaultDisplayContentLocked();
-                displayContent.layoutNeeded = true;
+                displayContent.setLayoutNeeded();
                 int anim[] = new int[2];
                 if (displayContent.isDimming()) {
                     anim[0] = anim[1] = 0;
@@ -3119,6 +3074,19 @@
         }
     }
 
+    // If this is true we have updated our desired orientation, but not yet
+    // changed the real orientation our applied our screen rotation animation.
+    // For example, because a previous screen rotation was in progress.
+    boolean rotationNeedsUpdateLocked() {
+        int rotation = mPolicy.rotationForOrientationLw(mLastOrientation, mRotation);
+        boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
+                mLastOrientation, rotation);
+        if (mRotation == rotation && mAltOrientation == altOrientation) {
+            return false;
+        }
+        return true;
+    }
+
     @Override
     public int[] setNewConfiguration(Configuration config) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
@@ -3131,13 +3099,7 @@
                 mWaitingForConfig = false;
                 mLastFinishedFreezeSource = "new-config";
             }
-            boolean configChanged = mGlobalConfiguration.diff(config) != 0;
-            if (!configChanged) {
-                return null;
-            }
-            prepareFreezingAllTaskBounds();
-            mGlobalConfiguration = new Configuration(config);
-            return onConfigurationChanged();
+            return mRoot.setGlobalConfigurationIfNeeded(config);
         }
     }
 
@@ -3151,31 +3113,6 @@
         }
     }
 
-    private void prepareFreezingAllTaskBounds() {
-        for (int i = mDisplayContents.size() - 1; i >= 0; i--) {
-            ArrayList<TaskStack> stacks = mDisplayContents.valueAt(i).getStacks();
-            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
-                final TaskStack stack = stacks.get(stackNdx);
-                stack.prepareFreezingTaskBounds();
-            }
-        }
-
-    }
-
-    private int[] onConfigurationChanged() {
-        mPolicy.onConfigurationChanged();
-
-        mChangedStackList.clear();
-
-        final int numDisplays = mDisplayContents.size();
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
-            displayContent.onConfigurationChanged(mChangedStackList);
-        }
-
-        return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList);
-    }
-
     @Override
     public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
@@ -3858,7 +3795,7 @@
 
         displayContent.rebuildAppWindowList();
 
-        // Set displayContent.layoutNeeded if window order changed.
+        // Set displayContent.mLayoutNeeded if window order changed.
         final int tmpSize = mTmpWindows.size();
         final int winSize = windows.size();
         int tmpNdx = 0, winNdx = 0;
@@ -3876,13 +3813,13 @@
 
             if (tmp != win) {
                 // Window order changed.
-                displayContent.layoutNeeded = true;
+                displayContent.setLayoutNeeded();
                 break;
             }
         }
         if (tmpNdx != winNdx) {
             // One list was different from the other.
-            displayContent.layoutNeeded = true;
+            displayContent.setLayoutNeeded();
         }
         mTmpWindows.clear();
 
@@ -3977,60 +3914,18 @@
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mWindowMap) {
-                final DisplayContent displayContent = mDisplayContents.get(displayId);
-                boolean attachedToDisplay = false;
-                if (displayContent != null) {
-                    TaskStack stack = mStackIdToStack.get(stackId);
-                    if (stack == null) {
-                        if (DEBUG_STACK) Slog.d(TAG_WM, "attachStack: stackId=" + stackId);
-
-                        stack = displayContent.getStackById(stackId);
-                        if (stack != null) {
-                            // It's already attached to the display. Detach and re-attach
-                            // because onTop might change, and be sure to clear mDeferDetach!
-                            displayContent.detachStack(stack);
-                            stack.mDeferDetach = false;
-                            attachedToDisplay = true;
-                        } else {
-                            stack = new TaskStack(this, stackId);
-                        }
-
-                        mStackIdToStack.put(stackId, stack);
-                        if (stackId == DOCKED_STACK_ID) {
-                            getDefaultDisplayContentLocked().mDividerControllerLocked
-                                    .notifyDockedStackExistsChanged(true);
-                        }
-                    }
-                    if (!attachedToDisplay) {
-                        stack.attachDisplayContent(displayContent);
-                    }
-                    displayContent.attachStack(stack, onTop);
-                    if (stack.getRawFullscreen()) {
-                        return null;
-                    }
-                    Rect bounds = new Rect();
-                    stack.getRawBounds(bounds);
-                    return bounds;
-                }
+                return mRoot.addStackToDisplay(stackId, displayId, onTop);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
         }
-        return null;
     }
 
     public void detachStack(int stackId) {
         synchronized (mWindowMap) {
             final TaskStack stack = mStackIdToStack.get(stackId);
             if (stack != null) {
-                final DisplayContent displayContent = stack.getDisplayContent();
-                if (displayContent != null) {
-                    if (stack.isAnimating()) {
-                        stack.mDeferDetach = true;
-                        return;
-                    }
-                    displayContent.detachChild(stack);
-                }
+                stack.removeIfPossible();
             }
         }
     }
@@ -4072,23 +3967,6 @@
         }
     }
 
-    public void addTask(int taskId, int stackId, boolean toTop) {
-        synchronized (mWindowMap) {
-            if (DEBUG_STACK) Slog.i(TAG_WM, "addTask: adding taskId=" + taskId
-                    + " to " + (toTop ? "top" : "bottom"));
-            Task task = mTaskIdToTask.get(taskId);
-            if (task == null) {
-                if (DEBUG_STACK) Slog.i(TAG_WM, "addTask: could not find taskId=" + taskId);
-                return;
-            }
-            TaskStack stack = mStackIdToStack.get(stackId);
-            stack.addTask(task, toTop);
-            final DisplayContent displayContent = stack.getDisplayContent();
-            displayContent.layoutNeeded = true;
-            mWindowPlacerLocked.performSurfacePlacement();
-        }
-    }
-
     public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
         synchronized (mWindowMap) {
             if (DEBUG_STACK) Slog.i(TAG_WM, "moveTaskToStack: moving taskId=" + taskId
@@ -4105,7 +3983,7 @@
             }
             task.moveTaskToStack(stack, toTop);
             final DisplayContent displayContent = stack.getDisplayContent();
-            displayContent.layoutNeeded = true;
+            displayContent.setLayoutNeeded();
             mWindowPlacerLocked.performSurfacePlacement();
         }
     }
@@ -4135,7 +4013,7 @@
 
     @Override
     public void overridePlayingAppAnimationsLw(Animation a) {
-        getDefaultDisplayContentLocked().overridePlayingAppAnimationsLw(a);
+        getDefaultDisplayContentLocked().overridePlayingAppAnimations(a);
     }
 
     /**
@@ -4157,7 +4035,7 @@
             }
             if (stack.setBounds(bounds, configs, taskBounds, taskTempInsetBounds)
                     && stack.isVisible()) {
-                stack.getDisplayContent().layoutNeeded = true;
+                stack.getDisplayContent().setLayoutNeeded();
                 mWindowPlacerLocked.performSurfacePlacement();
             }
             return stack.getRawFullscreen();
@@ -4194,7 +4072,7 @@
             }
             task.positionTaskInStack(stack, position, bounds, config);
             final DisplayContent displayContent = stack.getDisplayContent();
-            displayContent.layoutNeeded = true;
+            displayContent.setLayoutNeeded();
             mWindowPlacerLocked.performSurfacePlacement();
         }
     }
@@ -4214,7 +4092,7 @@
             }
 
             if (task.resizeLocked(bounds, overrideConfig, forced) && relayout) {
-                task.getDisplayContent().layoutNeeded = true;
+                task.getDisplayContent().setLayoutNeeded();
                 mWindowPlacerLocked.performSurfacePlacement();
             }
         }
@@ -4491,20 +4369,7 @@
     @Override
     public void closeSystemDialogs(String reason) {
         synchronized(mWindowMap) {
-            final int numDisplays = mDisplayContents.size();
-            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
-                final int numWindows = windows.size();
-                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
-                    final WindowState w = windows.get(winNdx);
-                    if (w.mHasSurface) {
-                        try {
-                            w.mClient.closeSystemDialogs(reason);
-                        } catch (RemoteException e) {
-                        }
-                    }
-                }
-            }
+            mRoot.closeSystemDialogs(reason);
         }
     }
 
@@ -4693,11 +4558,7 @@
             mPolicy.enableKeyguard(true);
 
             // Hide windows that should not be seen by the new user.
-            final int numDisplays = mDisplayContents.size();
-            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
-                displayContent.switchUserStacks();
-            }
+            mRoot.switchUser();
             mWindowPlacerLocked.performSurfacePlacement();
 
             // Notify whether the docked stack exists for the current user
@@ -4751,7 +4612,7 @@
             hideBootMessagesLocked();
             // If the screen still doesn't come up after 30 seconds, give
             // up and turn it on.
-            mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
+            mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30 * 1000);
         }
 
         mPolicy.systemBooted();
@@ -5082,26 +4943,10 @@
     private void showStrictModeViolation(int arg, int pid) {
         final boolean on = arg != 0;
         synchronized(mWindowMap) {
-            // Ignoring requests to enable the red border from clients
-            // which aren't on screen.  (e.g. Broadcast Receivers in
-            // the background..)
-            if (on) {
-                boolean isVisible = false;
-                final int numDisplays = mDisplayContents.size();
-                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
-                    final int numWindows = windows.size();
-                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
-                        final WindowState ws = windows.get(winNdx);
-                        if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
-                            isVisible = true;
-                            break;
-                        }
-                    }
-                }
-                if (!isVisible) {
-                    return;
-                }
+            // Ignoring requests to enable the red border from clients which aren't on screen.
+            // (e.g. Broadcast Receivers in the background..)
+            if (on && !mRoot.canShowStrictModeViolation(pid)) {
+                return;
             }
 
             if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
@@ -5236,7 +5081,7 @@
             boolean wallpaperOnly) {
         final DisplayContent displayContent;
         synchronized(mWindowMap) {
-            displayContent = getDisplayContentLocked(displayId);
+            displayContent = mRoot.getDisplayContentOrCreate(displayId);
             if (displayContent == null) {
                 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
                         + ": returning null. No Display for displayId=" + displayId);
@@ -5605,7 +5450,7 @@
         synchronized(mWindowMap) {
             changed = updateRotationUncheckedLocked(false);
             if (!changed || forceRelayout) {
-                getDefaultDisplayContentLocked().layoutNeeded = true;
+                getDefaultDisplayContentLocked().setLayoutNeeded();
                 mWindowPlacerLocked.performSurfacePlacement();
             }
         }
@@ -5688,7 +5533,7 @@
         mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
         mWaitingForConfig = true;
         final DisplayContent displayContent = getDefaultDisplayContentLocked();
-        displayContent.layoutNeeded = true;
+        displayContent.setLayoutNeeded();
         final int[] anim = new int[2];
         if (displayContent.isDimming()) {
             anim[0] = anim[1] = 0;
@@ -5741,7 +5586,7 @@
         // the top of the method, the caller is obligated to call computeNewConfigurationLocked().
         // By updating the Display info here it will be available to
         // computeScreenConfigurationLocked later.
-        updateDisplayAndOrientationLocked(mGlobalConfiguration.uiMode);
+        updateDisplayAndOrientationLocked(mRoot.getConfiguration().uiMode);
 
         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
         if (!inTransaction) {
@@ -5789,7 +5634,7 @@
             if (w.mHasSurface && !rotateSeamlessly) {
                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);
                 w.mOrientationChanging = true;
-                mWindowPlacerLocked.mOrientationChangeComplete = false;
+                mRoot.mOrientationChangeComplete = false;
                 w.mLastFreezeDuration = 0;
             }
         }
@@ -6026,13 +5871,12 @@
     }
 
     /**
-     * Lists all availble windows in the system. The listing is written in the
-     * specified Socket's output stream with the following syntax:
-     * windowHashCodeInHexadecimal windowName
-     * Each line of the ouput represents a different window.
+     * Lists all available windows in the system. The listing is written in the specified Socket's
+     * output stream with the following syntax: windowHashCodeInHexadecimal windowName
+     * Each line of the output represents a different window.
      *
      * @param client The remote client to send the listing to.
-     * @return False if an error occured, true otherwise.
+     * @return false if an error occurred, true otherwise.
      */
     boolean viewServerListWindows(Socket client) {
         if (isSystemSecure()) {
@@ -6041,14 +5885,9 @@
 
         boolean result = true;
 
-        WindowList windows = new WindowList();
+        final WindowList windows = new WindowList();
         synchronized (mWindowMap) {
-            //noinspection unchecked
-            final int numDisplays = mDisplayContents.size();
-            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
-                windows.addAll(displayContent.getWindowList());
-            }
+            mRoot.getWindows(windows);
         }
 
         BufferedWriter out = null;
@@ -6275,20 +6114,8 @@
         }
 
         synchronized (mWindowMap) {
-            final int numDisplays = mDisplayContents.size();
-            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
-                final int numWindows = windows.size();
-                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
-                    final WindowState w = windows.get(winNdx);
-                    if (System.identityHashCode(w) == hashCode) {
-                        return w;
-                    }
-                }
-            }
+            return mRoot.findWindow(hashCode);
         }
-
-        return null;
     }
 
     /**
@@ -6689,51 +6516,6 @@
         }
     }
 
-    void adjustForImeIfNeeded(final DisplayContent displayContent) {
-        final WindowState imeWin = mInputMethodWindow;
-        final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
-                && !displayContent.mDividerControllerLocked.isImeHideRequested();
-        final boolean dockVisible = isStackVisibleLocked(DOCKED_STACK_ID);
-        final TaskStack imeTargetStack = getImeFocusStackLocked();
-        final int imeDockSide = (dockVisible && imeTargetStack != null) ?
-                imeTargetStack.getDockSide() : DOCKED_INVALID;
-        final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
-        final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM);
-        final boolean dockMinimized = displayContent.mDividerControllerLocked.isMinimizedDock();
-        final int imeHeight = mPolicy.getInputMethodWindowVisibleHeightLw();
-        final boolean imeHeightChanged = imeVisible &&
-                imeHeight != displayContent.mDividerControllerLocked.getImeHeightAdjustedFor();
-
-        // The divider could be adjusted for IME position, or be thinner than usual,
-        // or both. There are three possible cases:
-        // - If IME is visible, and focus is on top, divider is not moved for IME but thinner.
-        // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner.
-        // - If IME is not visible, divider is not moved and is normal width.
-
-        if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
-            final ArrayList<TaskStack> stacks = displayContent.getStacks();
-            for (int i = stacks.size() - 1; i >= 0; --i) {
-                final TaskStack stack = stacks.get(i);
-                final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
-                if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)) {
-                    stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
-                } else {
-                    stack.resetAdjustedForIme(false);
-                }
-            }
-            displayContent.mDividerControllerLocked.setAdjustedForIme(
-                    imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
-        } else {
-            final ArrayList<TaskStack> stacks = displayContent.getStacks();
-            for (int i = stacks.size() - 1; i >= 0; --i) {
-                final TaskStack stack = stacks.get(i);
-                stack.resetAdjustedForIme(!dockVisible);
-            }
-            displayContent.mDividerControllerLocked.setAdjustedForIme(
-                    false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight);
-        }
-    }
-
     // -------------------------------------------------------------
     // Drag and drop
     // -------------------------------------------------------------
@@ -6991,7 +6773,7 @@
 
     private void displayReady(int displayId) {
         synchronized(mWindowMap) {
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
             if (displayContent != null) {
                 mAnimator.addDisplayLocked(displayId);
                 displayContent.initializeDisplayBaseInfo();
@@ -7170,8 +6952,8 @@
 
                     View view = null;
                     try {
-                        final Configuration overrideConfig = wtoken != null && wtoken.mTask != null
-                                ? wtoken.mTask.mOverrideConfig : null;
+                        final Configuration overrideConfig =
+                                wtoken != null ? wtoken.getMergedOverrideConfiguration() : null;
                         view = mPolicy.addStartingWindow(wtoken.token, sd.pkg, sd.theme,
                             sd.compatInfo, sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo,
                             sd.windowFlags, overrideConfig);
@@ -7636,7 +7418,7 @@
                     synchronized (mWindowMap) {
                         final DisplayContent displayContent = getDefaultDisplayContentLocked();
                         displayContent.getDockedDividerController().reevaluateVisibility(false);
-                        adjustForImeIfNeeded(displayContent);
+                        displayContent.adjustForImeIfNeeded();
                     }
                 }
                 break;
@@ -7832,7 +7614,7 @@
     @Override
     public void getInitialDisplaySize(int displayId, Point size) {
         synchronized (mWindowMap) {
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
                 size.x = displayContent.mInitialDisplayWidth;
                 size.y = displayContent.mInitialDisplayHeight;
@@ -7843,7 +7625,7 @@
     @Override
     public void getBaseDisplaySize(int displayId, Point size) {
         synchronized (mWindowMap) {
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
                 size.x = displayContent.mBaseDisplayWidth;
                 size.y = displayContent.mBaseDisplayHeight;
@@ -7870,7 +7652,7 @@
                 final int MIN_WIDTH = 200;
                 final int MIN_HEIGHT = 200;
                 final int MAX_SCALE = 2;
-                final DisplayContent displayContent = getDisplayContentLocked(displayId);
+                final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
                 if (displayContent != null) {
                     width = Math.min(Math.max(width, MIN_WIDTH),
                             displayContent.mInitialDisplayWidth * MAX_SCALE);
@@ -7900,7 +7682,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                final DisplayContent displayContent = getDisplayContentLocked(displayId);
+                final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
                 if (displayContent != null) {
                     if (mode < 0 || mode > 1) {
                         mode = 0;
@@ -7983,7 +7765,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                final DisplayContent displayContent = getDisplayContentLocked(displayId);
+                final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
                 if (displayContent != null) {
                     setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
                             displayContent.mInitialDisplayHeight);
@@ -7999,7 +7781,7 @@
     @Override
     public int getInitialDisplayDensity(int displayId) {
         synchronized (mWindowMap) {
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
                 return displayContent.mInitialDisplayDensity;
             }
@@ -8010,7 +7792,7 @@
     @Override
     public int getBaseDisplayDensity(int displayId) {
         synchronized (mWindowMap) {
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
                 return displayContent.mBaseDisplayDensity;
             }
@@ -8036,7 +7818,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                final DisplayContent displayContent = getDisplayContentLocked(displayId);
+                final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
                 if (displayContent != null && mCurrentUserId == targetUserId) {
                     setForcedDisplayDensityLocked(displayContent, density);
                 }
@@ -8067,7 +7849,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                final DisplayContent displayContent = getDisplayContentLocked(displayId);
+                final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
                 if (displayContent != null && mCurrentUserId == callingUserId) {
                     setForcedDisplayDensityLocked(displayContent,
                             displayContent.mInitialDisplayDensity);
@@ -8117,12 +7899,13 @@
             return;
         }
         configureDisplayPolicyLocked(displayContent);
-        displayContent.layoutNeeded = true;
+        displayContent.setLayoutNeeded();
 
         boolean configChanged = updateOrientationFromAppTokensLocked(false);
-        mTempConfiguration.setTo(mGlobalConfiguration);
+        final Configuration globalConfig = mRoot.getConfiguration();
+        mTempConfiguration.setTo(globalConfig);
         computeScreenConfigurationLocked(mTempConfiguration);
-        configChanged |= mGlobalConfiguration.diff(mTempConfiguration) != 0;
+        configChanged |= globalConfig.diff(mTempConfiguration) != 0;
 
         if (configChanged) {
             mWaitingForConfig = true;
@@ -8133,7 +7916,7 @@
         mWindowPlacerLocked.performSurfacePlacement();
     }
 
-    private void configureDisplayPolicyLocked(DisplayContent displayContent) {
+    void configureDisplayPolicyLocked(DisplayContent displayContent) {
         mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
                 displayContent.mBaseDisplayWidth,
                 displayContent.mBaseDisplayHeight,
@@ -8156,7 +7939,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                DisplayContent displayContent = getDisplayContentLocked(displayId);
+                DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
                 if (displayContent != null) {
                     setOverscanLocked(displayContent, left, top, right, bottom);
                 }
@@ -8223,7 +8006,7 @@
             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Changing surface while display frozen: " + w);
             w.mOrientationChanging = true;
             w.mLastFreezeDuration = 0;
-            mWindowPlacerLocked.mOrientationChangeComplete = false;
+            mRoot.mOrientationChangeComplete = false;
             if (mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_NONE) {
                 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
                 // XXX should probably keep timeout from
@@ -8257,7 +8040,7 @@
         if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM,
                 "Wallpaper layer changed: assigning layers + relayout");
         moveInputMethodWindowsIfNeededLocked(true);
-        mWindowPlacerLocked.mWallpaperMayChange = true;
+        mRoot.mWallpaperMayChange = true;
         // Since the window list has been rebuilt, focus might have to be recomputed since the
         // actual order of windows might have changed again.
         mFocusMayChange = true;
@@ -8280,7 +8063,7 @@
             w.setReportResizeHints();
             boolean configChanged = w.isConfigChanged();
             if (DEBUG_CONFIGURATION && configChanged) {
-                Slog.v(TAG_WM, "Win " + w + " config changed: " + mGlobalConfiguration);
+                Slog.v(TAG_WM, "Win " + w + " config changed: " + w.getConfiguration());
             }
             final boolean dragResizingChanged = w.isDragResizeChanged()
                     && !w.isDragResizingChangeReported();
@@ -8406,20 +8189,20 @@
         if (hold != state) {
             if (hold) {
                 if (DEBUG_KEEP_SCREEN_ON) {
-                    Slog.d(TAG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to " +
-                            mWindowPlacerLocked.mHoldScreenWindow);
+                    Slog.d(TAG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to "
+                            + mRoot.mHoldScreenWindow);
                 }
-                mLastWakeLockHoldingWindow = mWindowPlacerLocked.mHoldScreenWindow;
+                mLastWakeLockHoldingWindow = mRoot.mHoldScreenWindow;
                 mLastWakeLockObscuringWindow = null;
                 mHoldingScreenWakeLock.acquire();
                 mPolicy.keepScreenOnStartedLw();
             } else {
                 if (DEBUG_KEEP_SCREEN_ON) {
-                    Slog.d(TAG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by " +
-                            mWindowPlacerLocked.mObsuringWindow);
+                    Slog.d(TAG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by "
+                            + mRoot.mObsuringWindow);
                 }
                 mLastWakeLockHoldingWindow = null;
-                mLastWakeLockObscuringWindow = mWindowPlacerLocked.mObsuringWindow;
+                mLastWakeLockObscuringWindow = mRoot.mObsuringWindow;
                 mPolicy.keepScreenOnStoppedLw();
                 mHoldingScreenWakeLock.release();
             }
@@ -8440,17 +8223,6 @@
         }
     }
 
-    boolean needsLayout() {
-        final int numDisplays = mDisplayContents.size();
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
-            if (displayContent.layoutNeeded) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     /** If a window that has an animation specifying a colored background and the current wallpaper
      * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
      * suddenly disappear. */
@@ -8465,108 +8237,8 @@
         return winAnimator.mAnimLayer;
     }
 
-    boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
-                                           boolean secure) {
-        final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
-        boolean leakedSurface = false;
-        boolean killedApps = false;
-
-        EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
-                winAnimator.mSession.mPid, operation);
-
-        final long callingIdentity = Binder.clearCallingIdentity();
-        try {
-            // There was some problem...   first, do a sanity check of the window list to make sure
-            // we haven't left any dangling surfaces around.
-
-            Slog.i(TAG_WM, "Out of memory for surface!  Looking for leaks...");
-            final int numDisplays = mDisplayContents.size();
-            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
-                final int numWindows = windows.size();
-                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
-                    final WindowState ws = windows.get(winNdx);
-                    final WindowStateAnimator wsa = ws.mWinAnimator;
-                    if (wsa.mSurfaceController == null) {
-                        continue;
-                    }
-                    if (!mSessions.contains(wsa.mSession)) {
-                        Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
-                                + ws + " surface=" + wsa.mSurfaceController
-                                + " token=" + ws.mToken
-                                + " pid=" + ws.mSession.mPid
-                                + " uid=" + ws.mSession.mUid);
-                        wsa.destroySurface();
-                        mForceRemoves.add(ws);
-                        leakedSurface = true;
-                    } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
-                        Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
-                                + ws + " surface=" + wsa.mSurfaceController
-                                + " token=" + ws.mAppToken
-                                + " saved=" + ws.hasSavedSurface());
-                        if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
-                        wsa.destroySurface();
-                        leakedSurface = true;
-                    }
-                }
-            }
-
-            if (!leakedSurface) {
-                Slog.w(TAG_WM, "No leaked surfaces; killing applicatons!");
-                SparseIntArray pidCandidates = new SparseIntArray();
-                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
-                    final int numWindows = windows.size();
-                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
-                        final WindowState ws = windows.get(winNdx);
-                        if (mForceRemoves.contains(ws)) {
-                            continue;
-                        }
-                        WindowStateAnimator wsa = ws.mWinAnimator;
-                        if (wsa.mSurfaceController != null) {
-                            pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
-                        }
-                    }
-                    if (pidCandidates.size() > 0) {
-                        int[] pids = new int[pidCandidates.size()];
-                        for (int i=0; i<pids.length; i++) {
-                            pids[i] = pidCandidates.keyAt(i);
-                        }
-                        try {
-                            if (mActivityManager.killPids(pids, "Free memory", secure)) {
-                                killedApps = true;
-                            }
-                        } catch (RemoteException e) {
-                        }
-                    }
-                }
-            }
-
-            if (leakedSurface || killedApps) {
-                // We managed to reclaim some memory, so get rid of the trouble
-                // surface and ask the app to request another one.
-                Slog.w(TAG_WM, "Looks like we have reclaimed some memory, clearing surface for retry.");
-                if (surfaceController != null) {
-                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
-                            "RECOVER DESTROY", false);
-                    winAnimator.destroySurface();
-                    scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken);
-                }
-
-                try {
-                    winAnimator.mWin.mClient.dispatchGetNewSurface();
-                } catch (RemoteException e) {
-                }
-            }
-        } finally {
-            Binder.restoreCallingIdentity(callingIdentity);
-        }
-
-        return leakedSurface || killedApps;
-    }
-
     boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
-        WindowState newFocus = computeFocusedWindowLocked();
+        WindowState newFocus = mRoot.computeFocusedWindow();
         if (mCurrentFocus != newFocus) {
             Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
             // This check makes sure that we don't already have the focus
@@ -8579,8 +8251,8 @@
                     mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
                             && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
             if (imWindowChanged) {
-                displayContent.layoutNeeded = true;
-                newFocus = computeFocusedWindowLocked();
+                displayContent.setLayoutNeeded();
+                newFocus = mRoot.computeFocusedWindow();
             }
 
             if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG_WM, "Changing focus from " +
@@ -8606,7 +8278,7 @@
 
             if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
                 // The change in focus caused us to need to do a layout.  Okay.
-                displayContent.layoutNeeded = true;
+                displayContent.setLayoutNeeded();
                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
                     mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/,
                             updateInputWindows);
@@ -8619,7 +8291,7 @@
                 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
             }
 
-            adjustForImeIfNeeded(displayContent);
+            displayContent.adjustForImeIfNeeded();
 
             // We may need to schedule some toast windows to be removed. The
             // toasts for an app that does not have input focus are removed
@@ -8633,18 +8305,6 @@
         return false;
     }
 
-    private WindowState computeFocusedWindowLocked() {
-        final int displayCount = mDisplayContents.size();
-        for (int i = 0; i < displayCount; i++) {
-            final DisplayContent displayContent = mDisplayContents.valueAt(i);
-            final WindowState win = displayContent.findFocusedWindow();
-            if (win != null) {
-                return win;
-            }
-        }
-        return null;
-    }
-
     void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
         if (mDisplayFrozen) {
             return;
@@ -9179,19 +8839,6 @@
         }
     }
 
-    void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
-        pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
-        if (mDisplayReady) {
-            final int numDisplays = mDisplayContents.size();
-            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
-                displayContent.dump("  ", pw);
-            }
-        } else {
-            pw.println("  NO DISPLAY");
-        }
-    }
-
     void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
             ArrayList<WindowState> windows) {
         pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
@@ -9200,18 +8847,8 @@
 
     void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
             ArrayList<WindowState> windows) {
-        final int numDisplays = mDisplayContents.size();
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
-            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
-                final WindowState w = windowList.get(winNdx);
-                if (windows == null || windows.contains(w)) {
-                    pw.print("  Window #"); pw.print(winNdx); pw.print(' ');
-                            pw.print(w); pw.println(":");
-                    w.dump(pw, "    ", dumpAll || windows != null);
-                }
-            }
-        }
+        mRoot.dumpWindowsNoHeader(pw, dumpAll, windows);
+
         if (mInputMethodDialogs.size() > 0) {
             pw.println();
             pw.println("  Input method dialogs:");
@@ -9314,7 +8951,7 @@
             }
         }
         pw.println();
-        pw.print("  mGlobalConfiguration="); pw.println(mGlobalConfiguration);
+        pw.print("  mGlobalConfiguration="); pw.println(mRoot.getConfiguration());
         pw.print("  mHasPermanentDpad="); pw.println(mHasPermanentDpad);
         pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
         if (mLastFocus != mCurrentFocus) {
@@ -9354,16 +8991,9 @@
             mLayersController.dump(pw, "  ");
             pw.print("  mSystemBooted="); pw.print(mSystemBooted);
                     pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
-            if (needsLayout()) {
-                pw.print("  layoutNeeded on displays=");
-                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                    final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
-                    if (displayContent.layoutNeeded) {
-                        pw.print(displayContent.getDisplayId());
-                    }
-                }
-                pw.println();
-            }
+
+            mRoot.dumpLayoutNeededDisplayIds(pw);
+
             pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
             pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
                     pw.print(" windows="); pw.print(mWindowsFreezingScreen);
@@ -9385,54 +9015,21 @@
         }
     }
 
-    boolean dumpWindows(PrintWriter pw, String name, String[] args,
-            int opti, boolean dumpAll) {
+    boolean dumpWindows(PrintWriter pw, String name, String[] args, int opti, boolean dumpAll) {
         WindowList windows = new WindowList();
         if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) {
             final boolean appsOnly = name.contains("apps");
             final boolean visibleOnly = name.contains("visible");
             synchronized(mWindowMap) {
                 if (appsOnly) {
-                    dumpDisplayContentsLocked(pw, true);
+                    mRoot.dumpDisplayContents(pw);
                 }
 
-                final int numDisplays = mDisplayContents.size();
-                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                    final WindowList windowList =
-                            mDisplayContents.valueAt(displayNdx).getWindowList();
-                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
-                        final WindowState w = windowList.get(winNdx);
-                        if ((!visibleOnly || w.mWinAnimator.getShown())
-                                && (!appsOnly || w.mAppToken != null)) {
-                            windows.add(w);
-                        }
-                    }
-                }
+                mRoot.getWindows(windows, visibleOnly, appsOnly);
             }
         } else {
-            int objectId = 0;
-            // See if this is an object ID.
-            try {
-                objectId = Integer.parseInt(name, 16);
-                name = null;
-            } catch (RuntimeException e) {
-            }
             synchronized(mWindowMap) {
-                final int numDisplays = mDisplayContents.size();
-                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                    final WindowList windowList =
-                            mDisplayContents.valueAt(displayNdx).getWindowList();
-                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
-                        final WindowState w = windowList.get(winNdx);
-                        if (name != null) {
-                            if (w.mAttrs.getTitle().toString().contains(name)) {
-                                windows.add(w);
-                            }
-                        } else if (System.identityHashCode(w) == objectId) {
-                            windows.add(w);
-                        }
-                    }
-                }
+                mRoot.getWindowsByName(windows, name);
             }
         }
 
@@ -9482,7 +9079,7 @@
         dumpWindowsNoHeaderLocked(pw, true, null);
         pw.println();
         pw.println("Last ANR continued");
-        dumpDisplayContentsLocked(pw, true);
+        mRoot.dumpDisplayContents(pw);
         pw.close();
         mLastANRState = sw.toString();
 
@@ -9567,7 +9164,7 @@
                 return;
             } else if ("displays".equals(cmd) || "d".equals(cmd)) {
                 synchronized(mWindowMap) {
-                    dumpDisplayContentsLocked(pw, true);
+                    mRoot.dumpDisplayContents(pw);
                 }
                 return;
             } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
@@ -9585,6 +9182,13 @@
                     dumpWindowsLocked(pw, true, null);
                 }
                 return;
+            } else if ("containers".equals(cmd)) {
+                synchronized(mWindowMap) {
+                    StringBuilder output = new StringBuilder();
+                    mRoot.dumpChildrenNames(output, " ");
+                    pw.println(output.toString());
+                }
+                return;
             } else {
                 // Dumping a single name?
                 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
@@ -9627,7 +9231,7 @@
             if (dumpAll) {
                 pw.println("-------------------------------------------------------------------------------");
             }
-            dumpDisplayContentsLocked(pw, dumpAll);
+            mRoot.dumpDisplayContents(pw);
             pw.println();
             if (dumpAll) {
                 pw.println("-------------------------------------------------------------------------------");
@@ -9647,61 +9251,17 @@
         synchronized (mWindowMap) { }
     }
 
-    private DisplayContent newDisplayContentLocked(final Display display) {
-        DisplayContent displayContent = new DisplayContent(display, this);
-        final int displayId = display.getDisplayId();
-        if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
-        mDisplayContents.put(displayId, displayContent);
-
-        DisplayInfo displayInfo = displayContent.getDisplayInfo();
-        final Rect rect = new Rect();
-        mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
-        displayInfo.overscanLeft = rect.left;
-        displayInfo.overscanTop = rect.top;
-        displayInfo.overscanRight = rect.right;
-        displayInfo.overscanBottom = rect.bottom;
-        if (mDisplayManagerInternal != null) {
-            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(displayId, displayInfo);
-            configureDisplayPolicyLocked(displayContent);
-
-            // TODO: Create an input channel for each display with touch capability.
-            if (displayId == Display.DEFAULT_DISPLAY) {
-                displayContent.mTapDetector = new TaskTapPointerEventListener(this, displayContent);
-                registerPointerEventListener(displayContent.mTapDetector);
-                registerPointerEventListener(mMousePositionTracker);
-            }
-        }
-
-        return displayContent;
-    }
-
+    // TODO: All the display method below should probably be moved into the RootWindowContainer...
     public void createDisplayContentLocked(final Display display) {
         if (display == null) {
             throw new IllegalArgumentException("getDisplayContent: display must not be null");
         }
-        getDisplayContentLocked(display.getDisplayId());
-    }
-
-    /**
-     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
-     * there is a Display for the displayId.
-     * @param displayId The display the caller is interested in.
-     * @return The DisplayContent associated with displayId or null if there is no Display for it.
-     */
-    public DisplayContent getDisplayContentLocked(final int displayId) {
-        DisplayContent displayContent = mDisplayContents.get(displayId);
-        if (displayContent == null) {
-            final Display display = mDisplayManager.getDisplay(displayId);
-            if (display != null) {
-                displayContent = newDisplayContentLocked(display);
-            }
-        }
-        return displayContent;
+        mRoot.getDisplayContentOrCreate(display.getDisplayId());
     }
 
     // There is an inherent assumption that this will never return null.
     public DisplayContent getDefaultDisplayContentLocked() {
-        return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
+        return mRoot.getDisplayContentOrCreate(Display.DEFAULT_DISPLAY);
     }
 
     public WindowList getDefaultWindowListLocked() {
@@ -9714,20 +9274,11 @@
 
     /**
      * Return the list of WindowStates associated on the passed display.
-     * @param display The screen to return windows from.
-     * @return The list of WindowStates on the screen, or null if the there is no screen.
-     */
-    public WindowList getWindowListLocked(final Display display) {
-        return getWindowListLocked(display.getDisplayId());
-    }
-
-    /**
-     * Return the list of WindowStates associated on the passed display.
      * @param displayId The screen to return windows from.
      * @return The list of WindowStates on the screen, or null if the there is no screen.
      */
-    public WindowList getWindowListLocked(final int displayId) {
-        final DisplayContent displayContent = getDisplayContentLocked(displayId);
+    WindowList getWindowListLocked(final int displayId) {
+        final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
         return displayContent != null ? displayContent.getWindowList() : null;
     }
 
@@ -9751,19 +9302,9 @@
     }
 
     private void handleDisplayRemovedLocked(int displayId) {
-        final DisplayContent displayContent = getDisplayContentLocked(displayId);
+        final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
         if (displayContent != null) {
-            if (displayContent.isAnimating()) {
-                displayContent.mDeferredRemoval = true;
-                return;
-            }
-            if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + displayContent);
-            mDisplayContents.delete(displayId);
-            displayContent.close();
-            if (displayId == Display.DEFAULT_DISPLAY) {
-                unregisterPointerEventListener(displayContent.mTapDetector);
-                unregisterPointerEventListener(mMousePositionTracker);
-            }
+            displayContent.removeIfPossible();
         }
         mAnimator.removeDisplayLocked(displayId);
         mWindowPlacerLocked.requestTraversal();
@@ -9774,7 +9315,7 @@
     }
 
     private void handleDisplayChangedLocked(int displayId) {
-        final DisplayContent displayContent = getDisplayContentLocked(displayId);
+        final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
         if (displayContent != null) {
             displayContent.updateDisplayInfo();
         }
@@ -10030,7 +9571,7 @@
         }
     }
 
-    private MousePositionTracker mMousePositionTracker = new MousePositionTracker();
+    MousePositionTracker mMousePositionTracker = new MousePositionTracker();
 
     private static class MousePositionTracker implements PointerEventListener {
         private boolean mLatestEventWasMouse;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 60b0d03..ee2da13 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1493,7 +1493,7 @@
             }
             changed = true;
             if (displayContent != null) {
-                displayContent.layoutNeeded = true;
+                displayContent.setLayoutNeeded();
             }
         }
 
@@ -1562,7 +1562,7 @@
      */
     boolean hasMoved() {
         return mHasSurface && (mContentChanged || mMovedByResize)
-                && !mAnimatingExit && mService.okToDisplay()
+                && !mAnimatingExit
                 && (mFrame.top != mLastFrame.top || mFrame.left != mLastFrame.left)
                 && (!mIsChildWindow || !getParentWindow().hasMoved());
     }
@@ -1816,15 +1816,6 @@
         Binder.restoreCallingIdentity(origId);
     }
 
-    @Override
-    boolean detachFromDisplay() {
-        // We are in the middle of changing the state of displays/stacks/tasks. We need
-        // to finish that, before we let layout interfere with it.
-        // Also removes child windows.
-        removeIfPossible();
-        return true;
-    }
-
     private void setupWindowForRemoveOnExit() {
         mRemoveOnExit = true;
         setDisplayLayoutNeeded();
@@ -2048,7 +2039,7 @@
 
     void setDisplayLayoutNeeded() {
         if (mDisplayContent != null) {
-            mDisplayContent.layoutNeeded = true;
+            mDisplayContent.setLayoutNeeded();
         }
     }
 
@@ -2516,7 +2507,7 @@
                 && mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "set mOrientationChanging of " + this);
             mOrientationChanging = true;
-            mService.mWindowPlacerLocked.mOrientationChangeComplete = false;
+            mService.mRoot.mOrientationChangeComplete = false;
         }
         mLastFreezeDuration = 0;
         setDisplayLayoutNeeded();
@@ -2895,14 +2886,8 @@
             outConfig.setTo(mAppToken.mFrozenMergedConfig.peek());
             return;
         }
-        final Task task = getTask();
-        final Configuration overrideConfig = task != null
-                ? task.mOverrideConfig
-                : Configuration.EMPTY;
-        outConfig.setTo(mService.mGlobalConfiguration);
-        if (overrideConfig != Configuration.EMPTY) {
-            outConfig.updateFrom(overrideConfig);
-        }
+        outConfig.setTo(
+                mAppToken != null ? getConfiguration() : mDisplayContent.getConfiguration());
     }
 
     void reportResized() {
@@ -3537,7 +3522,7 @@
     void requestUpdateWallpaperIfNeeded() {
         if (mDisplayContent != null && (mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
             mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
-            mDisplayContent.layoutNeeded = true;
+            mDisplayContent.setLayoutNeeded();
             mService.mWindowPlacerLocked.requestTraversal();
         }
 
@@ -3655,7 +3640,7 @@
                     // want to make sure to do a layout.  If called from within the transaction
                     // loop, this will cause it to restart with a new layout.
                     if (displayContent != null) {
-                        displayContent.layoutNeeded = true;
+                        displayContent.setLayoutNeeded();
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 125368c..6c7d136 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -482,7 +482,7 @@
             // Upon completion of a not-visible to visible status bar animation a relayout is
             // required.
             if (displayContent != null) {
-                displayContent.layoutNeeded = true;
+                displayContent.setLayoutNeeded();
             }
         }
 
@@ -685,7 +685,7 @@
             }
         } catch (OutOfResourcesException e) {
             Slog.w(TAG, "OutOfResourcesException creating surface");
-            mService.reclaimSomeSurfaceMemoryLocked(this, "create", true);
+            mService.mRoot.reclaimSomeSurfaceMemory(this, "create", true);
             mDrawState = NO_SURFACE;
             return null;
         } catch (Exception e) {
@@ -1020,7 +1020,7 @@
                     + " screen=" + (screenAnimation ?
                             screenRotationAnimation.getEnterTransformation().getAlpha() : "null"));
             return;
-        } else if (mIsWallpaper && mService.mWindowPlacerLocked.mWallpaperActionPending) {
+        } else if (mIsWallpaper && mService.mRoot.mWallpaperActionPending) {
             return;
         } else if (mWin.isDragResizeChanged()) {
             // This window is awaiting a relayout because user just started (or ended)
@@ -1750,7 +1750,7 @@
         Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
 
         if (mWin.mAttrs.type == TYPE_INPUT_METHOD) {
-            mService.adjustForImeIfNeeded(mWin.mDisplayContent);
+            mWin.mDisplayContent.adjustForImeIfNeeded();
             if (isEntrance) {
                 mWin.setDisplayLayoutNeeded();
                 mService.mWindowPlacerLocked.requestTraversal();
@@ -1850,7 +1850,7 @@
     }
 
     void reclaimSomeSurfaceMemory(String operation, boolean secure) {
-        mService.reclaimSomeSurfaceMemoryLocked(this, operation, secure);
+        mService.mRoot.reclaimSomeSurfaceMemory(this, operation, secure);
     }
 
     boolean getShown() {
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index cc72352..368484a 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -101,8 +101,9 @@
                     s, name, w, h, format, flags);
         }
 
-        if (mService.mSurfaceTraceEnabled) {
-            mSurfaceControl = new RemoteSurfaceTrace(mService.mSurfaceTraceFd.getFileDescriptor(),
+        if (mService.mRoot.mSurfaceTraceEnabled) {
+            mSurfaceControl = new RemoteSurfaceTrace(
+                    mService.mRoot.mSurfaceTraceFd.getFileDescriptor(),
                     mSurfaceControl, animator.mWin);
         }
     }
@@ -116,7 +117,7 @@
     }
 
 
-    void logSurface(String msg, RuntimeException where) {
+    private void logSurface(String msg, RuntimeException where) {
         String str = "  SURFACE " + msg + ": " + title;
         if (where != null) {
             Slog.i(TAG, str, where);
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 13d3501..668e1b4 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -1,65 +1,37 @@
+
 package com.android.server.wm;
 
 import static android.app.ActivityManagerInternal.APP_TRANSITION_SAVED_SURFACE;
 import static android.app.ActivityManagerInternal.APP_TRANSITION_STARTING_WINDOW;
 import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;
 import static android.app.ActivityManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
-import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
-import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.H.DO_TRAVERSAL;
 import static com.android.server.wm.WindowManagerService.H.NOTIFY_APP_TRANSITION_STARTING;
-import static com.android.server.wm.WindowManagerService.H.NOTIFY_STARTING_WINDOW_DRAWN;
-import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
 import static com.android.server.wm.WindowManagerService.H.REPORT_WINDOWS_CHANGE;
-import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
 import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER;
-import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT;
 import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
 import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
-import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
 
+import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.os.Debug;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.SystemClock;
 import android.os.Trace;
-import android.provider.Settings;
 import android.util.ArraySet;
 import android.util.Slog;
 import android.view.Display;
@@ -98,46 +70,12 @@
     static final int SET_TURN_ON_SCREEN                 = 1 << 4;
     static final int SET_WALLPAPER_ACTION_PENDING       = 1 << 5;
 
-    boolean mWallpaperMayChange = false;
-    boolean mOrientationChangeComplete = true;
-    boolean mWallpaperActionPending = false;
-
-    private boolean mWallpaperForceHidingChanged = false;
-    private Object mLastWindowFreezeSource = null;
-    private Session mHoldScreen = null;
-    private boolean mObscured = false;
-    private boolean mSyswin = false;
-    private float mScreenBrightness = -1;
-    private float mButtonBrightness = -1;
-    private long mUserActivityTimeout = -1;
-    private boolean mUpdateRotation = false;
     private final Rect mTmpStartRect = new Rect();
     private final Rect mTmpContentRect = new Rect();
 
-    // Set to true when the display contains content to show the user.
-    // When false, the display manager may choose to mirror or blank the display.
-    private boolean mDisplayHasContent = false;
-
-    // Only set while traversing the default display based on its content.
-    // Affects the behavior of mirroring on secondary displays.
-    private boolean mObscureApplicationContentOnSecondaryDisplays = false;
-
-    private float mPreferredRefreshRate = 0;
-
-    private int mPreferredModeId = 0;
-
     private boolean mTraversalScheduled;
     private int mDeferDepth = 0;
 
-    private boolean mSustainedPerformanceModeEnabled = false;
-    private boolean mSustainedPerformanceModeCurrent = false;
-
-    // Following variables are for debugging screen wakelock only.
-    // Last window that requires screen wakelock
-    WindowState mHoldScreenWindow = null;
-    // Last window that obscures all windows below
-    WindowState mObsuringWindow = null;
-
     private static final class LayerAndToken {
         public int layer;
         public AppWindowToken token;
@@ -179,7 +117,7 @@
             mService.mH.removeMessages(DO_TRAVERSAL);
             loopCount--;
         } while (mTraversalScheduled && loopCount > 0);
-        mWallpaperActionPending = false;
+        mService.mRoot.mWallpaperActionPending = false;
     }
 
     private void performSurfacePlacementLoop() {
@@ -227,11 +165,11 @@
         }
 
         try {
-            performSurfacePlacementInner(recoveringMemory);
+            mService.mRoot.performSurfacePlacement(recoveringMemory);
 
             mInLayout = false;
 
-            if (mService.needsLayout()) {
+            if (mService.mRoot.isLayoutNeeded()) {
                 if (++mLayoutRepeatCount < 6) {
                     requestTraversal();
                 } else {
@@ -261,635 +199,16 @@
         }
     }
 
-    // "Something has changed!  Let's make it correct now."
-    private void performSurfacePlacementInner(boolean recoveringMemory) {
-        if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
-                + Debug.getCallers(3));
-
-        int i;
-        boolean updateInputWindowsNeeded = false;
-
-        if (mService.mFocusMayChange) {
-            mService.mFocusMayChange = false;
-            updateInputWindowsNeeded = mService.updateFocusedWindowLocked(
-                    UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
-        }
-
-        // Initialize state of exiting tokens.
-        final int numDisplays = mService.mDisplayContents.size();
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
-            for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
-                displayContent.mExitingTokens.get(i).hasVisible = false;
-            }
-        }
-
-        for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
-            // Initialize state of exiting applications.
-            final AppTokenList exitingAppTokens =
-                    mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
-            for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
-                exitingAppTokens.get(tokenNdx).hasVisible = false;
-            }
-        }
-
-        mHoldScreen = null;
-        mHoldScreenWindow = null;
-        mObsuringWindow = null;
-        mScreenBrightness = -1;
-        mButtonBrightness = -1;
-        mUserActivityTimeout = -1;
-        mObscureApplicationContentOnSecondaryDisplays = false;
-        mSustainedPerformanceModeCurrent = false;
-        mService.mTransactionSequence++;
-
-        // TODO(multi-display): Perform same actions on all displays.
-        final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
-        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
-        final int defaultDw = defaultInfo.logicalWidth;
-        final int defaultDh = defaultInfo.logicalHeight;
-
-        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
-                ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
-        mService.openSurfaceTransaction();
-        try {
-            applySurfaceChangesTransaction(recoveringMemory, numDisplays, defaultDw, defaultDh);
-        } catch (RuntimeException e) {
-            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
-        } finally {
-            mService.closeSurfaceTransaction();
-            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
-                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
-        }
-
-        final WindowList defaultWindows = defaultDisplay.getWindowList();
-
-        // If we are ready to perform an app transition, check through
-        // all of the app tokens to be shown and see if they are ready
-        // to go.
-        if (mService.mAppTransition.isReady()) {
-            defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
-            if (DEBUG_LAYOUT_REPEATS)
-                debugLayoutRepeats("after handleAppTransitionReadyLocked",
-                        defaultDisplay.pendingLayoutChanges);
-        }
-
-        if (!mService.mAnimator.mAppWindowAnimating && mService.mAppTransition.isRunning()) {
-            // We have finished the animation of an app transition.  To do
-            // this, we have delayed a lot of operations like showing and
-            // hiding apps, moving apps in Z-order, etc.  The app token list
-            // reflects the correct Z-order, but the window list may now
-            // be out of sync with it.  So here we will just rebuild the
-            // entire app window list.  Fun!
-            defaultDisplay.pendingLayoutChanges |=
-                    mService.handleAnimatingStoppedAndTransitionLocked();
-            if (DEBUG_LAYOUT_REPEATS)
-                debugLayoutRepeats("after handleAnimStopAndXitionLock",
-                        defaultDisplay.pendingLayoutChanges);
-        }
-
-        if (mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
-                && !mService.mAppTransition.isReady()) {
-            // At this point, there was a window with a wallpaper that
-            // was force hiding other windows behind it, but now it
-            // is going away.  This may be simple -- just animate
-            // away the wallpaper and its window -- or it may be
-            // hard -- the wallpaper now needs to be shown behind
-            // something that was hidden.
-            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
-            if (DEBUG_LAYOUT_REPEATS)
-                debugLayoutRepeats("after animateAwayWallpaperLocked",
-                        defaultDisplay.pendingLayoutChanges);
-        }
-        mWallpaperForceHidingChanged = false;
-
-        if (mWallpaperMayChange) {
-            if (DEBUG_WALLPAPER_LIGHT)
-                Slog.v(TAG, "Wallpaper may change!  Adjusting");
-            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
-            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
-                    defaultDisplay.pendingLayoutChanges);
-        }
-
-        if (mService.mFocusMayChange) {
-            mService.mFocusMayChange = false;
-            if (mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
-                    false /*updateInputWindows*/)) {
-                updateInputWindowsNeeded = true;
-                defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
-            }
-        }
-
-        if (mService.needsLayout()) {
-            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
-            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
-                    defaultDisplay.pendingLayoutChanges);
-        }
-
-        for (i = mService.mResizingWindows.size() - 1; i >= 0; i--) {
-            WindowState win = mService.mResizingWindows.get(i);
-            if (win.mAppFreezing) {
-                // Don't remove this window until rotation has completed.
-                continue;
-            }
-            // Discard the saved surface if window size is changed, it can't be reused.
-            if (win.mAppToken != null) {
-                win.mAppToken.destroySavedSurfaces();
-            }
-            win.reportResized();
-            mService.mResizingWindows.remove(i);
-        }
-
-        if (DEBUG_ORIENTATION && mService.mDisplayFrozen) Slog.v(TAG,
-                "With display frozen, orientationChangeComplete=" + mOrientationChangeComplete);
-        if (mOrientationChangeComplete) {
-            if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
-                mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
-                mService.mLastFinishedFreezeSource = mLastWindowFreezeSource;
-                mService.mH.removeMessages(WINDOW_FREEZE_TIMEOUT);
-            }
-            mService.stopFreezingDisplayLocked();
-        }
-
-        // Destroy the surface of any windows that are no longer visible.
-        boolean wallpaperDestroyed = false;
-        i = mService.mDestroySurface.size();
-        if (i > 0) {
-            do {
-                i--;
-                WindowState win = mService.mDestroySurface.get(i);
-                win.mDestroying = false;
-                if (mService.mInputMethodWindow == win) {
-                    mService.mInputMethodWindow = null;
-                }
-                if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
-                    wallpaperDestroyed = true;
-                }
-                win.destroyOrSaveSurface();
-            } while (i > 0);
-            mService.mDestroySurface.clear();
-        }
-
-        // Time to remove any exiting tokens?
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
-            ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
-            for (i = exitingTokens.size() - 1; i >= 0; i--) {
-                WindowToken token = exitingTokens.get(i);
-                if (!token.hasVisible) {
-                    exitingTokens.remove(i);
-                    if (token.windowType == TYPE_WALLPAPER) {
-                        mWallpaperControllerLocked.removeWallpaperToken(token);
-                    }
-                }
-            }
-        }
-
-        // Time to remove any exiting applications?
-        for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
-            // Initialize state of exiting applications.
-            final AppTokenList exitingAppTokens =
-                    mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
-            for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
-                AppWindowToken token = exitingAppTokens.get(i);
-                if (!token.hasVisible && !mService.mClosingApps.contains(token) &&
-                        (!token.mIsExiting || token.isEmpty())) {
-                    // Make sure there is no animation running on this token,
-                    // so any windows associated with it will be removed as
-                    // soon as their animations are complete
-                    token.mAppAnimator.clearAnimation();
-                    token.mAppAnimator.animating = false;
-                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
-                            "performLayout: App token exiting now removed" + token);
-                    token.removeIfPossible();
-                }
-            }
-        }
-
-        if (wallpaperDestroyed) {
-            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
-            defaultDisplay.layoutNeeded = true;
-        }
-
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
-            if (displayContent.pendingLayoutChanges != 0) {
-                displayContent.layoutNeeded = true;
-            }
-        }
-
-        // Finally update all input windows now that the window changes have stabilized.
-        mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
-
-        mService.setHoldScreenLocked(mHoldScreen);
-        if (!mService.mDisplayFrozen) {
-            if (mScreenBrightness < 0 || mScreenBrightness > 1.0f) {
-                mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
-            } else {
-                mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
-                        toBrightnessOverride(mScreenBrightness));
-            }
-            if (mButtonBrightness < 0
-                    || mButtonBrightness > 1.0f) {
-                mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
-            } else {
-                mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
-                        toBrightnessOverride(mButtonBrightness));
-            }
-            mService.mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
-                    mUserActivityTimeout);
-        }
-
-        if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) {
-            mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent;
-            mService.mPowerManagerInternal.powerHint(
-                    mService.mPowerManagerInternal.POWER_HINT_SUSTAINED_PERFORMANCE_MODE,
-                    (mSustainedPerformanceModeEnabled ? 1 : 0));
-        }
-
-        if (mService.mTurnOnScreen) {
-            if (mService.mAllowTheaterModeWakeFromLayout
-                    || Settings.Global.getInt(mService.mContext.getContentResolver(),
-                        Settings.Global.THEATER_MODE_ON, 0) == 0) {
-                if (DEBUG_VISIBILITY || DEBUG_POWER) {
-                    Slog.v(TAG, "Turning screen on after layout!");
-                }
-                mService.mPowerManager.wakeUp(SystemClock.uptimeMillis(),
-                        "android.server.wm:TURN_ON");
-            }
-            mService.mTurnOnScreen = false;
-        }
-
-        if (mUpdateRotation) {
-            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
-            if (mService.updateRotationUncheckedLocked(false)) {
-                mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
-            } else {
-                mUpdateRotation = false;
-            }
-        }
-
-        if (mService.mWaitingForDrawnCallback != null ||
-                (mOrientationChangeComplete && !defaultDisplay.layoutNeeded &&
-                        !mUpdateRotation)) {
-            mService.checkDrawnWindowsLocked();
-        }
-
-        final int N = mService.mPendingRemove.size();
-        if (N > 0) {
-            if (mService.mPendingRemoveTmp.length < N) {
-                mService.mPendingRemoveTmp = new WindowState[N+10];
-            }
-            mService.mPendingRemove.toArray(mService.mPendingRemoveTmp);
-            mService.mPendingRemove.clear();
-            DisplayContentList displayList = new DisplayContentList();
-            for (i = 0; i < N; i++) {
-                final WindowState w = mService.mPendingRemoveTmp[i];
-                w.removeImmediately();
-                final DisplayContent displayContent = w.getDisplayContent();
-                if (displayContent != null && !displayList.contains(displayContent)) {
-                    displayList.add(displayContent);
-                }
-            }
-
-            for (DisplayContent displayContent : displayList) {
-                mService.mLayersController.assignLayersLocked(displayContent.getWindowList());
-                displayContent.layoutNeeded = true;
-            }
-        }
-
-        // Remove all deferred displays stacks, tasks, and activities.
-        for (int displayNdx = mService.mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
-            mService.mDisplayContents.valueAt(displayNdx).checkCompleteDeferredRemoval();
-        }
-
-        if (updateInputWindowsNeeded) {
-            mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
-        }
-        mService.setFocusTaskRegionLocked();
-
-        // Check to see if we are now in a state where the screen should
-        // be enabled, because the window obscured flags have changed.
-        mService.enableScreenIfNeededLocked();
-
-        mService.scheduleAnimationLocked();
-        mService.mWindowPlacerLocked.destroyPendingSurfaces();
-
-        if (DEBUG_WINDOW_TRACE) Slog.e(TAG,
-                "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating());
-    }
-
-    private void applySurfaceChangesTransaction(boolean recoveringMemory, int numDisplays,
-            int defaultDw, int defaultDh) {
-        if (mService.mWatermark != null) {
-            mService.mWatermark.positionSurface(defaultDw, defaultDh);
-        }
-        if (mService.mStrictModeFlash != null) {
-            mService.mStrictModeFlash.positionSurface(defaultDw, defaultDh);
-        }
-        if (mService.mCircularDisplayMask != null) {
-            mService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh,
-                    mService.mRotation);
-        }
-        if (mService.mEmulatorDisplayOverlay != null) {
-            mService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
-                    mService.mRotation);
-        }
-
-        boolean focusDisplayed = false;
-
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
-            boolean updateAllDrawn = false;
-            WindowList windows = displayContent.getWindowList();
-            DisplayInfo displayInfo = displayContent.getDisplayInfo();
-            final int displayId = displayContent.getDisplayId();
-            final int dw = displayInfo.logicalWidth;
-            final int dh = displayInfo.logicalHeight;
-            final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
-
-            // Reset for each display.
-            mDisplayHasContent = false;
-            mPreferredRefreshRate = 0;
-            mPreferredModeId = 0;
-
-            int repeats = 0;
-            do {
-                repeats++;
-                if (repeats > 6) {
-                    Slog.w(TAG, "Animation repeat aborted after too many iterations");
-                    displayContent.layoutNeeded = false;
-                    break;
-                }
-
-                if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
-                        "On entry to LockedInner", displayContent.pendingLayoutChanges);
-
-                if ((displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
-                        mWallpaperControllerLocked.adjustWallpaperWindows()) {
-                    mService.mLayersController.assignLayersLocked(windows);
-                    displayContent.layoutNeeded = true;
-                }
-
-                if (isDefaultDisplay
-                        && (displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
-                    if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
-                    if (mService.updateOrientationFromAppTokensLocked(true)) {
-                        displayContent.layoutNeeded = true;
-                        mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
-                    }
-                }
-
-                if ((displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
-                    displayContent.layoutNeeded = true;
-                }
-
-                // FIRST LOOP: Perform a layout, if needed.
-                if (repeats < LAYOUT_REPEAT_THRESHOLD) {
-                    performLayoutLockedInner(displayContent, repeats == 1,
-                            false /* updateInputWindows */);
-                } else {
-                    Slog.w(TAG, "Layout repeat skipped after too many iterations");
-                }
-
-                // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
-                // it is animating.
-                displayContent.pendingLayoutChanges = 0;
-
-                if (isDefaultDisplay) {
-                    mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
-                    for (int i = windows.size() - 1; i >= 0; i--) {
-                        WindowState w = windows.get(i);
-                        if (w.mHasSurface) {
-                            mService.mPolicy.applyPostLayoutPolicyLw(
-                                    w, w.mAttrs, w.getParentWindow());
-                        }
-                    }
-                    displayContent.pendingLayoutChanges |=
-                            mService.mPolicy.finishPostLayoutPolicyLw();
-                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishPostLayoutPolicyLw",
-                            displayContent.pendingLayoutChanges);
-                }
-            } while (displayContent.pendingLayoutChanges != 0);
-
-            mObscured = false;
-            mSyswin = false;
-            displayContent.resetDimming();
-
-            // Only used if default window
-            final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
-
-            for (int i = windows.size() - 1; i >= 0; i--) {
-                WindowState w = windows.get(i);
-                final Task task = w.getTask();
-                final boolean obscuredChanged = w.mObscured != mObscured;
-
-                // Update effect.
-                w.mObscured = mObscured;
-                if (!mObscured) {
-                    handleNotObscuredLocked(w, displayInfo);
-                }
-
-                w.applyDimLayerIfNeeded();
-
-                if (isDefaultDisplay && obscuredChanged
-                        && mWallpaperControllerLocked.isWallpaperTarget(w) && w.isVisibleLw()) {
-                    // This is the wallpaper target and its obscured state
-                    // changed... make sure the current wallaper's visibility
-                    // has been updated accordingly.
-                    mWallpaperControllerLocked.updateWallpaperVisibility();
-                }
-
-                final WindowStateAnimator winAnimator = w.mWinAnimator;
-
-                // If the window has moved due to its containing content frame changing, then
-                // notify the listeners and optionally animate it. Simply checking a change of
-                // position is not enough, because being move due to dock divider is not a trigger
-                // for animation.
-                if (w.hasMoved()) {
-                    // Frame has moved, containing content frame has also moved, and we're not
-                    // currently animating... let's do something.
-                    final int left = w.mFrame.left;
-                    final int top = w.mFrame.top;
-                    final boolean adjustedForMinimizedDockOrIme = task != null
-                                && (task.mStack.isAdjustedForMinimizedDockedStack()
-                                    || task.mStack.isAdjustedForIme());
-                    if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
-                            && !w.isDragResizing() && !adjustedForMinimizedDockOrIme
-                            && (task == null || w.getTask().mStack.hasMovementAnimations())
-                            && !w.mWinAnimator.mLastHidden) {
-                        winAnimator.setMoveAnimation(left, top);
-                    }
-
-                    //TODO (multidisplay): Accessibility supported only for the default display.
-                    if (mService.mAccessibilityController != null
-                            && displayId == Display.DEFAULT_DISPLAY) {
-                        mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
-                    }
-
-                    try {
-                        w.mClient.moved(left, top);
-                    } catch (RemoteException e) {
-                    }
-                    w.mMovedByResize = false;
-                }
-
-                //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
-                w.mContentChanged = false;
-
-                // Moved from updateWindowsAndWallpaperLocked().
-                if (w.mHasSurface) {
-                    // Take care of the window being ready to display.
-                    final boolean committed = winAnimator.commitFinishDrawingLocked();
-                    if (isDefaultDisplay && committed) {
-                        if (w.mAttrs.type == TYPE_DREAM) {
-                            // HACK: When a dream is shown, it may at that
-                            // point hide the lock screen.  So we need to
-                            // redo the layout to let the phone window manager
-                            // make this happen.
-                            displayContent.pendingLayoutChanges |=
-                                    FINISH_LAYOUT_REDO_LAYOUT;
-                            if (DEBUG_LAYOUT_REPEATS) {
-                                debugLayoutRepeats("dream and commitFinishDrawingLocked true",
-                                        displayContent.pendingLayoutChanges);
-                            }
-                        }
-                        if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
-                            if (DEBUG_WALLPAPER_LIGHT)
-                                Slog.v(TAG, "First draw done in potential wallpaper target " + w);
-                            mWallpaperMayChange = true;
-                            displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
-                            if (DEBUG_LAYOUT_REPEATS) {
-                                debugLayoutRepeats("wallpaper and commitFinishDrawingLocked true",
-                                        displayContent.pendingLayoutChanges);
-                            }
-                        }
-                    }
-                    if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) {
-                        // Updates the shown frame before we set up the surface. This is needed
-                        // because the resizing could change the top-left position (in addition to
-                        // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
-                        // position the surface.
-                        //
-                        // If an animation is being started, we can't call this method because the
-                        // animation hasn't processed its initial transformation yet, but in general
-                        // we do want to update the position if the window is animating.
-                        winAnimator.computeShownFrameLocked();
-                    }
-                    winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
-                }
-
-                final AppWindowToken atoken = w.mAppToken;
-                if (DEBUG_STARTING_WINDOW && atoken != null && w == atoken.startingWindow) {
-                    Slog.d(TAG, "updateWindows: starting " + w
-                            + " isOnScreen=" + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
-                            + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
-                }
-                if (atoken != null && (!atoken.allDrawn || !atoken.allDrawnExcludingSaved
-                        || atoken.mAppAnimator.freezingScreen)) {
-                    if (atoken.lastTransactionSequence != mService.mTransactionSequence) {
-                        atoken.lastTransactionSequence = mService.mTransactionSequence;
-                        atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
-                        atoken.numInterestingWindowsExcludingSaved = 0;
-                        atoken.numDrawnWindowsExcludingSaved = 0;
-                        atoken.startingDisplayed = false;
-                    }
-                    if (!atoken.allDrawn && w.mightAffectAllDrawn(false /* visibleOnly */)) {
-                        if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
-                            Slog.v(TAG, "Eval win " + w + ": isDrawn="
-                                    + w.isDrawnLw()
-                                    + ", isAnimationSet=" + winAnimator.isAnimationSet());
-                            if (!w.isDrawnLw()) {
-                                Slog.v(TAG, "Not displayed: s="
-                                        + winAnimator.mSurfaceController
-                                        + " pv=" + w.mPolicyVisibility
-                                        + " mDrawState=" + winAnimator.drawStateToString()
-                                        + " ph=" + w.isParentWindowHidden()
-                                        + " th=" + atoken.hiddenRequested
-                                        + " a=" + winAnimator.mAnimating);
-                            }
-                        }
-                        if (w != atoken.startingWindow) {
-                            if (w.isInteresting()) {
-                                atoken.numInterestingWindows++;
-                                if (w.isDrawnLw()) {
-                                    atoken.numDrawnWindows++;
-                                    if (DEBUG_VISIBILITY || DEBUG_ORIENTATION)
-                                        Slog.v(TAG, "tokenMayBeDrawn: " + atoken
-                                                + " w=" + w + " numInteresting="
-                                                + atoken.numInterestingWindows
-                                                + " freezingScreen="
-                                                + atoken.mAppAnimator.freezingScreen
-                                                + " mAppFreezing=" + w.mAppFreezing);
-                                    updateAllDrawn = true;
-                                }
-                            }
-                        } else if (w.isDrawnLw()) {
-                            mService.mH.sendEmptyMessage(NOTIFY_STARTING_WINDOW_DRAWN);
-                            atoken.startingDisplayed = true;
-                        }
-                    }
-                    if (!atoken.allDrawnExcludingSaved
-                            && w.mightAffectAllDrawn(true /* visibleOnly */)) {
-                        if (w != atoken.startingWindow && w.isInteresting()) {
-                            atoken.numInterestingWindowsExcludingSaved++;
-                            if (w.isDrawnLw() && !w.isAnimatingWithSavedSurface()) {
-                                atoken.numDrawnWindowsExcludingSaved++;
-                                if (DEBUG_VISIBILITY || DEBUG_ORIENTATION)
-                                    Slog.v(TAG, "tokenMayBeDrawnExcludingSaved: " + atoken
-                                            + " w=" + w + " numInteresting="
-                                            + atoken.numInterestingWindowsExcludingSaved
-                                            + " freezingScreen="
-                                            + atoken.mAppAnimator.freezingScreen
-                                            + " mAppFreezing=" + w.mAppFreezing);
-                                updateAllDrawn = true;
-                            }
-                        }
-                    }
-                }
-
-                if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
-                        && w.isDisplayedLw()) {
-                    focusDisplayed = true;
-                }
-
-                mService.updateResizingWindows(w);
-            }
-
-            mService.mDisplayManagerInternal.setDisplayProperties(displayId,
-                    mDisplayHasContent,
-                    mPreferredRefreshRate,
-                    mPreferredModeId,
-                    true /* inTraversal, must call performTraversalInTrans... below */);
-
-            displayContent.stopDimmingIfNeeded();
-
-            if (updateAllDrawn) {
-                // See if any windows have been drawn, so they (and others associated with them)
-                // can now be shown.
-                displayContent.updateAllDrawn();
-            }
-        }
-
-        if (focusDisplayed) {
-            mService.mH.sendEmptyMessage(REPORT_LOSING_FOCUS);
-        }
-
-        // Give the display manager a chance to adjust properties
-        // like display rotation if it needs to.
-        mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
-    }
-
     boolean isInLayout() {
         return mInLayout;
     }
 
     final void performLayoutLockedInner(final DisplayContent displayContent,
             boolean initial, boolean updateInputWindows) {
-        if (!displayContent.layoutNeeded) {
+        if (!displayContent.isLayoutNeeded()) {
             return;
         }
-        displayContent.layoutNeeded = false;
+        displayContent.clearLayoutNeeded();
         WindowList windows = displayContent.getWindowList();
         boolean isDefaultDisplay = displayContent.isDefaultDisplay;
 
@@ -910,12 +229,12 @@
 
         if (DEBUG_LAYOUT) {
             Slog.v(TAG, "-------------------------------------");
-            Slog.v(TAG, "performLayout: needed="
-                    + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
+            Slog.v(TAG, "performLayout: needed=" + displayContent.isLayoutNeeded()
+                    + " dw=" + dw + " dh=" + dh);
         }
 
         mService.mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mService.mRotation,
-                mService.mGlobalConfiguration.uiMode);
+                displayContent.getConfiguration().uiMode);
         if (isDefaultDisplay) {
             // Not needed on non-default displays.
             mService.mSystemDecorLayer = mService.mPolicy.getSystemDecorLayerLw();
@@ -1064,7 +383,7 @@
      * @param windows List of windows on default display.
      * @return bitmap indicating if another pass through layout must be made.
      */
-    private int handleAppTransitionReadyLocked(WindowList windows) {
+    int handleAppTransitionReadyLocked(WindowList windows) {
         int appsCount = mService.mOpeningApps.size();
         if (!transitionGoodToGo(appsCount)) {
             return 0;
@@ -1084,7 +403,7 @@
         final DisplayContent displayContent = mService.getDefaultDisplayContentLocked();
         displayContent.rebuildAppWindowList();
 
-        mWallpaperMayChange = false;
+        mService.mRoot.mWallpaperMayChange = false;
 
         // The top-most window will supply the layout params,
         // and we will determine it below.
@@ -1109,7 +428,7 @@
         if ((displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
                 mWallpaperControllerLocked.adjustWallpaperWindows()) {
             mService.mLayersController.assignLayersLocked(windows);
-            displayContent.layoutNeeded = true;
+            displayContent.setLayoutNeeded();
         }
 
         final WindowState lowerWallpaperTarget =
@@ -1214,7 +533,7 @@
 
         // This has changed the visibility of windows, so perform
         // a new layout to get them all up-to-date.
-        displayContent.layoutNeeded = true;
+        displayContent.setLayoutNeeded();
 
         // TODO(multidisplay): IMEs are only supported on the default display.
         if (windows == mService.getDefaultWindowListLocked()
@@ -1332,8 +651,25 @@
                 "Checking " + appsCount + " opening apps (frozen="
                         + mService.mDisplayFrozen + " timeout="
                         + mService.mAppTransition.isTimeout() + ")...");
+        final ScreenRotationAnimation screenRotationAnimation =
+            mService.mAnimator.getScreenRotationAnimationLocked(
+                    Display.DEFAULT_DISPLAY);
+
         int reason = APP_TRANSITION_TIMEOUT;
         if (!mService.mAppTransition.isTimeout()) {
+            // Imagine the case where we are changing orientation due to an app transition, but a previous
+            // orientation change is still in progress. We won't process the orientation change
+            // for our transition because we need to wait for the rotation animation to finish.
+            // If we start the app transition at this point, we will interrupt it halfway with a new rotation
+            // animation after the old one finally finishes. It's better to defer the
+            // app transition.
+            if (screenRotationAnimation != null && screenRotationAnimation.isAnimating() &&
+                    mService.rotationNeedsUpdateLocked()) {
+                if (DEBUG_APP_TRANSITIONS) {
+                    Slog.v(TAG, "Delaying app transition for screen rotation animation to finish");
+                }
+                return false;
+            }
             for (int i = 0; i < appsCount; i++) {
                 AppWindowToken wtoken = mService.mOpeningApps.valueAt(i);
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
@@ -1437,91 +773,6 @@
         return transit;
     }
 
-    /**
-     * @param w WindowState this method is applied to.
-     * @param dispInfo info of the display that the window's obscuring state is checked against.
-     */
-    private void handleNotObscuredLocked(final WindowState w, final DisplayInfo dispInfo) {
-        final LayoutParams attrs = w.mAttrs;
-        final int attrFlags = attrs.flags;
-        final boolean canBeSeen = w.isDisplayedLw();
-        final int privateflags = attrs.privateFlags;
-
-        if (canBeSeen && w.isObscuringFullscreen(dispInfo)) {
-            // This window completely covers everything behind it,
-            // so we want to leave all of them as undimmed (for
-            // performance reasons).
-            if (!mObscured) {
-                mObsuringWindow = w;
-            }
-
-            mObscured = true;
-        }
-
-        if (w.mHasSurface && canBeSeen) {
-            if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
-                mHoldScreen = w.mSession;
-                mHoldScreenWindow = w;
-            } else if (DEBUG_KEEP_SCREEN_ON && w == mService.mLastWakeLockHoldingWindow) {
-                Slog.d(TAG_KEEP_SCREEN_ON, "handleNotObscuredLocked: " + w + " was holding "
-                        + "screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by"
-                        + Debug.getCallers(10));
-            }
-            if (!mSyswin && w.mAttrs.screenBrightness >= 0
-                    && mScreenBrightness < 0) {
-                mScreenBrightness = w.mAttrs.screenBrightness;
-            }
-            if (!mSyswin && w.mAttrs.buttonBrightness >= 0
-                    && mButtonBrightness < 0) {
-                mButtonBrightness = w.mAttrs.buttonBrightness;
-            }
-            if (!mSyswin && w.mAttrs.userActivityTimeout >= 0
-                    && mUserActivityTimeout < 0) {
-                mUserActivityTimeout = w.mAttrs.userActivityTimeout;
-            }
-
-            final int type = attrs.type;
-            if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
-                    || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
-                mSyswin = true;
-            }
-
-            // This function assumes that the contents of the default display are
-            // processed first before secondary displays.
-            final DisplayContent displayContent = w.getDisplayContent();
-            if (displayContent != null && displayContent.isDefaultDisplay) {
-                // While a dream or keyguard is showing, obscure ordinary application
-                // content on secondary displays (by forcibly enabling mirroring unless
-                // there is other content we want to show) but still allow opaque
-                // keyguard dialogs to be shown.
-                if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
-                    mObscureApplicationContentOnSecondaryDisplays = true;
-                }
-                mDisplayHasContent = true;
-            } else if (displayContent != null &&
-                    (!mObscureApplicationContentOnSecondaryDisplays
-                            || (mObscured && type == TYPE_KEYGUARD_DIALOG))) {
-                // Allow full screen keyguard presentation dialogs to be seen.
-                mDisplayHasContent = true;
-            }
-            if (mPreferredRefreshRate == 0
-                    && w.mAttrs.preferredRefreshRate != 0) {
-                mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
-            }
-            if (mPreferredModeId == 0
-                    && w.mAttrs.preferredDisplayModeId != 0) {
-                mPreferredModeId = w.mAttrs.preferredDisplayModeId;
-            }
-            if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) {
-                mSustainedPerformanceModeCurrent = true;
-            }
-        }
-    }
-
-    private static int toBrightnessOverride(float value) {
-        return (int)(value * PowerManager.BRIGHTNESS_ON);
-    }
-
     private void processApplicationsAnimatingInPlace(int transit) {
         if (transit == AppTransition.TRANSIT_TASK_IN_PLACE) {
             // Find the focused window
@@ -1590,13 +841,14 @@
                 Rect appRect = win != null ? win.getContentFrameLw() :
                         new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
                 Rect insets = win != null ? win.mContentInsets : null;
+                final Configuration displayConfig = displayContent.getConfiguration();
                 // For the new aspect-scaled transition, we want it to always show
                 // above the animating opening/closing window, and we want to
                 // synchronize its thumbnail surface with the surface for the
                 // open/close animation (only on the way down)
                 anim = mService.mAppTransition.createThumbnailAspectScaleAnimationLocked(appRect,
-                        insets, thumbnailHeader, taskId, mService.mGlobalConfiguration.uiMode,
-                        mService.mGlobalConfiguration.orientation);
+                        insets, thumbnailHeader, taskId, displayConfig.uiMode,
+                        displayConfig.orientation);
                 openingAppAnimator.thumbnailForceAboveLayer = Math.max(openingLayer, closingLayer);
                 openingAppAnimator.deferThumbnailDestruction =
                         !mService.mAppTransition.isNextThumbnailTransitionScaleUp();
@@ -1618,41 +870,6 @@
         }
     }
 
-    boolean copyAnimToLayoutParamsLocked() {
-        boolean doRequest = false;
-
-        final int bulkUpdateParams = mService.mAnimator.mBulkUpdateParams;
-        if ((bulkUpdateParams & SET_UPDATE_ROTATION) != 0) {
-            mUpdateRotation = true;
-            doRequest = true;
-        }
-        if ((bulkUpdateParams & SET_WALLPAPER_MAY_CHANGE) != 0) {
-            mWallpaperMayChange = true;
-            doRequest = true;
-        }
-        if ((bulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0) {
-            mWallpaperForceHidingChanged = true;
-            doRequest = true;
-        }
-        if ((bulkUpdateParams & SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
-            mOrientationChangeComplete = false;
-        } else {
-            mOrientationChangeComplete = true;
-            mLastWindowFreezeSource = mService.mAnimator.mLastWindowFreezeSource;
-            if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
-                doRequest = true;
-            }
-        }
-        if ((bulkUpdateParams & SET_TURN_ON_SCREEN) != 0) {
-            mService.mTurnOnScreen = true;
-        }
-        if ((bulkUpdateParams & SET_WALLPAPER_ACTION_PENDING) != 0) {
-            mWallpaperActionPending = true;
-        }
-
-        return doRequest;
-    }
-
     void requestTraversal() {
         if (!mTraversalScheduled) {
             mTraversalScheduled = true;
@@ -1680,8 +897,8 @@
     }
 
     public void dump(PrintWriter pw, String prefix) {
-        pw.print(prefix); pw.print("mTraversalScheduled="); pw.println(mTraversalScheduled);
-        pw.print(prefix); pw.print("mHoldScreenWindow="); pw.println(mHoldScreenWindow);
-        pw.print(prefix); pw.print("mObsuringWindow="); pw.println(mObsuringWindow);
+        pw.println(prefix + "mTraversalScheduled=" + mTraversalScheduled);
+        pw.println(prefix + "mHoldScreenWindow=" + mService.mRoot.mHoldScreenWindow);
+        pw.println(prefix + "mObsuringWindow=" + mService.mRoot.mObsuringWindow);
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 7ed8e78..177652c 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -16,7 +16,6 @@
 
 package com.android.server.wm;
 
-import android.annotation.CallSuper;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.IBinder;
@@ -258,7 +257,7 @@
         if (hidden == visible) {
             hidden = !visible;
             // Need to do a layout to ensure the wallpaper now has the correct size.
-            displayContent.layoutNeeded = true;
+            displayContent.setLayoutNeeded();
         }
 
         final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
@@ -281,7 +280,7 @@
                     "Wallpaper token " + token + " hidden=" + !visible);
             hidden = !visible;
             // Need to do a layout to ensure the wallpaper now has the correct size.
-            mService.getDefaultDisplayContentLocked().layoutNeeded = true;
+            mService.getDefaultDisplayContentLocked().setLayoutNeeded();
         }
 
         final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
diff --git a/services/core/proto/ipconnectivity.proto b/services/core/proto/ipconnectivity.proto
new file mode 100644
index 0000000..e0d7f09
--- /dev/null
+++ b/services/core/proto/ipconnectivity.proto
@@ -0,0 +1,274 @@
+// LINT: LEGACY_NAMES
+syntax = "proto2";
+
+package clearcut.connectivity;
+
+option java_package = "com.android.server.connectivity.metrics";
+option java_outer_classname = "IpConnectivityLogClass";
+
+// NetworkId represents the id given by the system to a physical network on the
+// Android device. It is used to relates events to each other for devices with
+// multiple networks (WiFi, 4G, ...).
+message NetworkId {
+  // Every network gets assigned a network_id on creation based on order of
+  // creation. Thus network_id N is assigned to the network created directly
+  // after network N-1. Thus there is no PII involved here. Zero means no
+  // network. The value 0 is never assigned to a network.
+  optional int32 network_id = 1;
+};
+
+// Logs changes in the system default network. Changes can be 1) acquiring a
+// default network with no previous default, 2) a switch of the system default
+// network to a new default network, 3) a loss of the system default network.
+// This message is associated to android.net.metrics.DefaultNetworkEvent.
+message DefaultNetworkEvent {
+  // A value of 0 means this is a loss of the system default network.
+  optional NetworkId network_id = 1;
+
+  // A value of 0 means there was no previous default network.
+  optional NetworkId previous_network_id = 2;
+
+  // Whether the network supports IPv4, IPv6, or both.
+  enum IPSupport {
+    NONE = 0;
+    IPV4 = 1;
+    IPV6 = 2;
+    DUAL = 3;
+  };
+
+  // Best available information about IP support of the previous network when
+  // disconnecting or switching to a new default network.
+  optional IPSupport previous_network_ip_support = 3;
+
+  // The transport types of the new default network, represented by
+  // TRANSPORT_* constants as defined in NetworkCapabilities.
+  repeated int32 transport_types = 4;
+};
+
+// Logs IpReachabilityMonitor probe events and NUD_FAILED events.
+// This message is associated to android.net.metrics.IpReachabilityEvent.
+message IpReachabilityEvent {
+  // The interface name (wlan, rmnet, lo, ...) on which the probe was sent.
+  optional string if_name = 1;
+
+  // The event type code of the probe, represented by constants defined in
+  // android.net.metrics.IpReachabilityEvent.
+  optional int32 event_type = 2;
+};
+
+// Logs NetworkMonitor and ConnectivityService events related to the state of
+// a network: connection, evaluation, validation, lingering, and disconnection.
+// This message is associated to android.net.metrics.NetworkEvent.
+message NetworkEvent {
+  // The id of the network on which this event happened.
+  optional NetworkId network_id = 1;
+
+  // The type of network event, represented by NETWORK_* constants defined in
+  // android.net.metrics.NetworkEvent.
+  optional int32 event_type = 2;
+
+  // Only valid after finishing evaluating a network for Internet connectivity.
+  // The time it took for this evaluation to complete.
+  optional int32 latency_ms = 3;
+}
+
+// Logs individual captive portal probing events that are performed when
+// evaluating or reevaluating networks for Internet connectivity.
+// This message is associated to android.net.metrics.ValidationProbeEvent.
+message ValidationProbeEvent {
+  // The id of the network for which the probe was sent.
+  optional NetworkId network_id = 1;
+
+  // The time it took for that probe to complete or time out.
+  optional int32 latency_ms = 2;
+
+  // The type of portal probe, represented by PROBE_* constants defined in
+  // android.net.metrics.ValidationProbeEvent.
+  optional int32 probe_type = 3;
+
+  // The http code result of the probe test.
+  optional int32 probe_result = 4;
+}
+
+// Logs DNS lookup latencies. Repeated fields must have the same length.
+// This message is associated to android.net.metrics.DnsEvent.
+message DNSLookupBatch {
+  // The id of the network on which the DNS lookups took place.
+  optional NetworkId network_id = 1;
+
+  // The types of the DNS lookups, as defined in android.net.metrics.DnsEvent.
+  repeated int32 event_types = 2;
+
+  // The return values of the DNS resolver for each DNS lookups.
+  repeated int32 return_codes = 3;
+
+  // The time it took for each DNS lookups to complete.
+  repeated int32 latencies_ms = 4;
+};
+
+// Represents a DHCP event on a single interface, which can be a DHCPClient
+// state transition or a response packet parsing error.
+// This message is associated to android.net.metrics.DhcpClientEvent and
+// android.net.metrics.DhcpErrorEvent.
+message DHCPEvent {
+  // The interface name (wlan, rmnet, lo, ...) on which the event happened.
+  optional string if_name = 1;
+
+  oneof value {
+    // The name of a state in the DhcpClient state machine, represented by
+    // the inner classes of android.net.dhcp.DhcpClient.
+    string state_transition = 2;
+
+    // The error code of a DHCP error, represented by constants defined in
+    // android.net.metrics.DhcpErrorEvent.
+    int32 error_code = 3;
+  }
+
+  // Lifetime duration in milliseconds of a DhcpClient state, or transition
+  // time in milliseconds between specific pairs of DhcpClient's states.
+  // Only populated when state_transition is populated.
+  optional int32 duration_ms = 4;
+}
+
+// Represents the generation of an Android Packet Filter program.
+message ApfProgramEvent {
+  // Lifetime of the program in seconds.
+  optional int64 lifetime = 1;
+
+  // Number of RAs filtered by the APF program.
+  optional int32 filtered_ras = 2;
+
+  // Total number of RAs to filter currently tracked by ApfFilter. Can be more
+  // than filtered_ras if all available program size was exhausted.
+  optional int32 current_ras = 3;
+
+  // Length of the APF program in bytes.
+  optional int32 program_length = 4;
+
+  // True if the APF program is dropping multicast and broadcast traffic.
+  optional bool drop_multicast = 5;
+
+  // True if the interface on which APF runs has an IPv4 address.
+  optional bool has_ipv4_addr = 6;
+}
+
+// Represents Router Advertisement listening statistics for an interface with
+// Android Packet Filter enabled.
+message ApfStatistics {
+  // The time interval in milliseconds these stastistics cover.
+  optional int64 duration_ms = 1;
+
+  // The total number of received RAs.
+  optional int32 received_ras = 2;
+
+  // The total number of received RAs that matched a known RA.
+  optional int32 matching_ras = 3;
+
+  // The total number of received RAs ignored due to the MAX_RAS limit.
+  optional int32 dropped_ras = 5;
+
+  // The total number of received RAs with an effective lifetime of 0 seconds.
+  // Effective lifetime for APF is the minimum of all lifetimes in a RA.
+  optional int32 zero_lifetime_ras = 6;
+
+  // The total number of received RAs that could not be parsed.
+  optional int32 parse_errors = 7;
+
+  // The total number of APF program updates triggered by an RA reception.
+  optional int32 program_updates = 8;
+
+  // The maximum APF program size in byte advertised by hardware.
+  optional int32 max_program_size = 9;
+}
+
+// Represents the reception of a Router Advertisement packet for an interface
+// with Android Packet Filter enabled.
+message RaEvent {
+  // All lifetime values are expressed in seconds. The default value for an
+  // option lifetime that was not present in the RA option list is -1.
+  // The lifetime of an option (e.g., the Prefix Information Option) is the
+  // minimum lifetime of all such options in the packet.
+
+  // The value of the router lifetime in the RA packet.
+  optional int64 router_lifetime = 1;
+
+  // Prefix valid lifetime from the prefix information option.
+  optional int64 prefix_valid_lifetime = 2;
+
+  // Prefix preferred lifetime from the prefix information option.
+  optional int64 prefix_preferred_lifetime = 3;
+
+  // Route info lifetime.
+  optional int64 route_info_lifetime = 4;
+
+  // Recursive DNS server lifetime.
+  optional int64 rdnss_lifetime = 5;
+
+  // DNS search list lifetime.
+  optional int64 dnssl_lifetime = 6;
+}
+
+// Represents an IP provisioning event in IpManager and how long the
+// provisioning action took.
+// This message is associated to android.net.metrics.IpManagerEvent.
+message IpProvisioningEvent {
+  // The interface name (wlan, rmnet, lo, ...) on which the probe was sent.
+  optional string if_name = 1;
+
+  // The code of the IP provisioning event, represented by constants defined in
+  // android.net.metrics.IpManagerEvent.
+  optional int32 event_type = 2;
+
+  // The duration of the provisioning action that resulted in this event.
+  optional int32 latency_ms = 3;
+}
+
+// Represents one of the IP connectivity event defined in this file.
+// Next tag: 12
+message IpConnectivityEvent {
+  // Time in ms when the event was recorded.
+  optional int64 time_ms = 1;
+
+  // Event type.
+  oneof event {
+
+    // An event about the system default network.
+    DefaultNetworkEvent default_network_event = 2;
+
+    // An IP reachability probe event.
+    IpReachabilityEvent ip_reachability_event = 3;
+
+    // A network lifecycle event.
+    NetworkEvent network_event = 4;
+
+    // A batch of DNS lookups.
+    DNSLookupBatch dns_lookup_batch = 5;
+
+    // A DHCP client event or DHCP receive error.
+    DHCPEvent dhcp_event = 6;
+
+    // An IP provisioning event.
+    IpProvisioningEvent ip_provisioning_event = 7;
+
+    // A network validation probe event.
+    ValidationProbeEvent validation_probe_event = 8;
+
+    // An Android Packet Filter program event.
+    ApfProgramEvent apf_program_event = 9;
+
+    // An Android Packet Filter statistics event.
+    ApfStatistics apf_statistics = 10;
+
+    // An RA packet reception event.
+    RaEvent ra_event = 11;
+  };
+};
+
+// The information about IP connectivity events.
+message IpConnectivityLog {
+  // An array of IP connectivity events.
+  repeated IpConnectivityEvent events = 1;
+
+  // The number of events that had to be dropped due to a full buffer.
+  optional int32 dropped_events = 2;
+};
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index af84c2a..0c57179 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -496,6 +496,12 @@
                     }
                 });
             }
+            // STOPSHIP: Remove this code once all dogfood devices are fixed. See b/31754835
+            if (Intent.ACTION_BOOT_COMPLETED.equals(action) && !mOwners.hasDeviceOwner()
+                    && !isBackupServiceEnabledInternal()) {
+                setBackupServiceEnabledInternal(true);
+                Slog.w(LOG_TAG, "Fix backup for device that is not in Device Owner mode.");
+            }
             if (Intent.ACTION_USER_UNLOCKED.equals(action)
                     || Intent.ACTION_USER_STARTED.equals(action)
                     || KeyChain.ACTION_TRUST_STORE_CHANGED.equals(action)) {
@@ -3029,8 +3035,8 @@
             throw new IllegalStateException(e);
         }
         if (ai == null) {
-            throw new IllegalStateException("Couldn't find package to remove admin "
-                    + packageName + " " + userHandle);
+            throw new IllegalStateException("Couldn't find package: "
+                    + packageName + " on user " + userHandle);
         }
         return (ai.flags & ApplicationInfo.FLAG_TEST_ONLY) != 0;
     }
@@ -9058,8 +9064,10 @@
         if (!isDeviceOwnerManagedSingleUserDevice()) {
             mInjector.securityLogSetLoggingEnabledProperty(false);
             Slog.w(LOG_TAG, "Security logging turned off as it's no longer a single user device.");
-            setBackupServiceEnabledInternal(false);
-            Slog.w(LOG_TAG, "Backup is off as it's a managed device that has more that one user.");
+            if (mOwners.hasDeviceOwner()) {
+                setBackupServiceEnabledInternal(false);
+                Slog.w(LOG_TAG, "Backup is off as it's a managed device that has more that one user.");
+            }
         }
     }
 
@@ -9350,12 +9358,15 @@
         }
         synchronized (this) {
             getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
-            try {
-                IBackupManager ibm = mInjector.getIBackupManager();
-                return ibm != null && ibm.isBackupServiceActive(UserHandle.USER_SYSTEM);
-            } catch (RemoteException e) {
-                throw new IllegalStateException("Failed requesting backup service state.", e);
-            }
+            return isBackupServiceEnabledInternal();
+        }
+    }
+    private boolean isBackupServiceEnabledInternal() {
+        try {
+            IBackupManager ibm = mInjector.getIBackupManager();
+            return ibm != null && ibm.isBackupServiceActive(UserHandle.USER_SYSTEM);
+        } catch (RemoteException e) {
+            throw new IllegalStateException("Failed requesting backup service state.", e);
         }
     }
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 96e9cb4..aba4dc0 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -54,17 +54,20 @@
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.SamplingProfilerIntegration;
 import com.android.internal.os.ZygoteInit;
+import com.android.internal.policy.EmergencyAffordanceManager;
 import com.android.internal.widget.ILockSettings;
 import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.audio.AudioService;
 import com.android.server.camera.CameraService;
 import com.android.server.clipboard.ClipboardService;
+import com.android.server.connectivity.IpConnectivityMetrics;
 import com.android.server.connectivity.MetricsLoggerService;
 import com.android.server.devicepolicy.DevicePolicyManagerService;
 import com.android.server.display.DisplayManagerService;
 import com.android.server.display.NightDisplayService;
 import com.android.server.dreams.DreamManagerService;
+import com.android.server.emergency.EmergencyAffordanceService;
 import com.android.server.fingerprint.FingerprintService;
 import com.android.server.hdmi.HdmiControlService;
 import com.android.server.input.InputManagerService;
@@ -593,12 +596,14 @@
                 false);
         boolean disableTrustManager = SystemProperties.getBoolean("config.disable_trustmanager",
                 false);
-        boolean disableTextServices = SystemProperties.getBoolean("config.disable_textservices", false);
+        boolean disableTextServices = SystemProperties.getBoolean("config.disable_textservices",
+                false);
         boolean disableSamplingProfiler = SystemProperties.getBoolean("config.disable_samplingprof",
                 false);
-
         boolean disableConsumerIr = SystemProperties.getBoolean("config.disable_consumerir", false);
         boolean disableVrManager = SystemProperties.getBoolean("config.disable_vrmanager", false);
+        boolean disableCameraService = SystemProperties.getBoolean("config.disable_cameraservice",
+                false);
 
         boolean isEmulator = SystemProperties.get("ro.kernel.qemu").equals("1");
 
@@ -611,7 +616,7 @@
             traceBeginAndSlog("StartKeyAttestationApplicationIdProviderService");
             ServiceManager.addService("sec_key_att_app_id_provider",
                     new KeyAttestationApplicationIdProviderService(context));
-            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+            traceEnd();
 
             traceBeginAndSlog("StartSchedulingPolicyService");
             ServiceManager.addService("scheduling_policy", new SchedulingPolicyService());
@@ -632,10 +637,12 @@
 
             mContentResolver = context.getContentResolver();
 
-            Slog.i(TAG, "Camera Service");
-            traceBeginAndSlog("StartCameraService");
-            mSystemServiceManager.startService(CameraService.class);
-            traceEnd();
+            if (!disableCameraService) {
+                Slog.i(TAG, "Camera Service");
+                traceBeginAndSlog("StartCameraService");
+                mSystemServiceManager.startService(CameraService.class);
+                traceEnd();
+            }
 
             // The AccountManager must come before the ContentService
             traceBeginAndSlog("StartAccountManagerService");
@@ -723,6 +730,10 @@
             mSystemServiceManager.startService(MetricsLoggerService.class);
             traceEnd();
 
+            traceBeginAndSlog("IpConnectivityMetrics");
+            mSystemServiceManager.startService(IpConnectivityMetrics.class);
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+
             traceBeginAndSlog("PinnerService");
             mSystemServiceManager.startService(PinnerService.class);
             traceEnd();
@@ -1217,6 +1228,11 @@
                 traceEnd();
             }
 
+            if (!disableNetwork && !disableNonCoreServices && EmergencyAffordanceManager.ENABLED) {
+                // EmergencyMode sevice
+                mSystemServiceManager.startService(EmergencyAffordanceService.class);
+            }
+
             if (!disableNonCoreServices) {
                 // Dreams (interactive idle-time views, a/k/a screen savers, and doze mode)
                 traceBeginAndSlog("StartDreamManager");
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 215059d..ee67d953 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -358,6 +358,7 @@
     }
 
     public static final String DUMP_ARG = "ipmanager";
+    public static final String DUMP_ARG_CONFIRM = "confirm";
 
     private static final int CMD_STOP = 1;
     private static final int CMD_START = 2;
@@ -562,6 +563,12 @@
     }
 
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+        if (args.length > 0 && DUMP_ARG_CONFIRM.equals(args[0])) {
+            // Execute confirmConfiguration() and take no further action.
+            confirmConfiguration();
+            return;
+        }
+
         IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
         pw.println("APF dump:");
         pw.increaseIndent();
diff --git a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
index 1612b99..004edec 100644
--- a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
@@ -43,6 +43,7 @@
 import android.media.AudioManager;
 import android.media.AudioSystem;
 import android.net.Uri;
+import android.net.wifi.WifiManager;
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.Handler;
@@ -465,6 +466,9 @@
                 mInjector.getSystemUsersConfiguration(), userId);
         mInjector.turnOffAllFlashLights(mCameraIdsWithFlash);
         muteVolumeStreams();
+        if (!mInjector.getWifiManager().isWifiEnabled()) {
+            mInjector.getWifiManager().setWifiEnabled(true);
+        }
         // Disable lock screen for demo users.
         mInjector.getLockPatternUtils().setLockScreenDisabled(true, userId);
         mInjector.getNotificationManager().notifyAsUser(TAG,
@@ -519,6 +523,7 @@
         private PowerManager mPowerManager;
         private CameraManager mCameraManager;
         private PowerManager.WakeLock mWakeLock;
+        private WifiManager mWifiManager;
         private Configuration mSystemUserConfiguration;
         private PendingIntent mResetDemoPendingIntent;
 
@@ -530,6 +535,13 @@
             return mContext;
         }
 
+        WifiManager getWifiManager() {
+            if (mWifiManager == null) {
+                mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+            }
+            return mWifiManager;
+        }
+
         UserManager getUserManager() {
             if (mUm == null) {
                 mUm = getContext().getSystemService(UserManager.class);
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 97d8bdd..3f5b96e 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -48,6 +48,13 @@
 
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
+# Code coverage puts us over the dex limit, so enable multi-dex for coverage-enabled builds
+ifeq (true,$(EMMA_INSTRUMENT))
+LOCAL_JACK_FLAGS := --multi-dex native
+endif # EMMA_INSTRUMENT_STATIC
+
+LOCAL_STATIC_JAVA_LIBRARIES += ub-uiautomator
+
 include $(BUILD_PACKAGE)
 
 #########################################################################
@@ -70,6 +77,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
   libbinder \
+  liblog \
   libcutils \
   libnativehelper \
   libnetdaidl
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index b8ace28..514f095 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -43,6 +43,7 @@
     <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
     <uses-permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD" />
     <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" />
+    <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
 
     <application>
         <uses-library android:name="android.test.runner" />
@@ -155,6 +156,9 @@
             </intent-filter>
         </activity-alias>
 
+        <activity android:name="com.android.server.am.TaskStackChangedListenerTest$ActivityA" />
+        <activity android:name="com.android.server.am.TaskStackChangedListenerTest$ActivityB" />
+
     </application>
 
     <instrumentation
diff --git a/services/tests/servicestests/src/android/net/metrics/IpConnectivityLogTest.java b/services/tests/servicestests/src/android/net/ConnectivityMetricsLoggerTest.java
similarity index 60%
rename from services/tests/servicestests/src/android/net/metrics/IpConnectivityLogTest.java
rename to services/tests/servicestests/src/android/net/ConnectivityMetricsLoggerTest.java
index 1433f95..6d42cce 100644
--- a/services/tests/servicestests/src/android/net/metrics/IpConnectivityLogTest.java
+++ b/services/tests/servicestests/src/android/net/ConnectivityMetricsLoggerTest.java
@@ -14,49 +14,45 @@
  * limitations under the License.
  */
 
-package android.net.metrics;
+package android.net;
 
 import android.os.Bundle;
 import android.os.Parcel;
-import android.net.ConnectivityMetricsEvent;
-import android.net.IConnectivityMetricsLogger;
-
+import java.util.List;
 import junit.framework.TestCase;
-import org.junit.Before;
-import org.junit.Test;
-
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+
 import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import java.util.List;
-
-public class IpConnectivityLogTest extends TestCase {
+public class ConnectivityMetricsLoggerTest extends TestCase {
 
     // use same Parcel object everywhere for pointer equality
     static final Bundle FAKE_EV = new Bundle();
+    static final int FAKE_COMPONENT = 1;
+    static final int FAKE_EVENT = 2;
 
     @Mock IConnectivityMetricsLogger mService;
     ArgumentCaptor<ConnectivityMetricsEvent> evCaptor;
+    ArgumentCaptor<ConnectivityMetricsEvent[]> evArrayCaptor;
 
-    IpConnectivityLog mLog;
+    ConnectivityMetricsLogger mLog;
 
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         evCaptor = ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
-        mLog = new IpConnectivityLog(mService);
+        evArrayCaptor = ArgumentCaptor.forClass(ConnectivityMetricsEvent[].class);
+        mLog = new ConnectivityMetricsLogger(mService);
     }
 
     public void testLogEvents() throws Exception {
-        assertTrue(mLog.log(1, FAKE_EV));
-        assertTrue(mLog.log(2, FAKE_EV));
-        assertTrue(mLog.log(3, FAKE_EV));
+        mLog.logEvent(1, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV);
+        mLog.logEvent(2, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV);
+        mLog.logEvent(3, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV);
 
         List<ConnectivityMetricsEvent> gotEvents = verifyEvents(3);
         assertEventsEqual(expectedEvent(1), gotEvents.get(0));
@@ -67,13 +63,21 @@
     public void testLogEventTriggerThrottling() throws Exception {
         when(mService.logEvent(any())).thenReturn(1234L);
 
-        assertFalse(mLog.log(1, FAKE_EV));
+        mLog.logEvent(1, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV);
+        mLog.logEvent(2, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV);
+
+        List<ConnectivityMetricsEvent> gotEvents = verifyEvents(1);
+        assertEventsEqual(expectedEvent(1), gotEvents.get(0));
     }
 
     public void testLogEventFails() throws Exception {
         when(mService.logEvent(any())).thenReturn(-1L); // Error.
 
-        assertFalse(mLog.log(1, FAKE_EV));
+        mLog.logEvent(1, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV);
+        mLog.logEvent(2, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV);
+
+        List<ConnectivityMetricsEvent> gotEvents = verifyEvents(1);
+        assertEventsEqual(expectedEvent(1), gotEvents.get(0));
     }
 
     public void testLogEventWhenThrottling() throws Exception {
@@ -81,61 +85,30 @@
 
         // No events are logged. The service is only called once
         // After that, throttling state is maintained locally.
-        assertFalse(mLog.log(1, FAKE_EV));
-        assertFalse(mLog.log(2, FAKE_EV));
+        mLog.logEvent(1, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV);
+        mLog.logEvent(2, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV);
 
         List<ConnectivityMetricsEvent> gotEvents = verifyEvents(1);
         assertEventsEqual(expectedEvent(1), gotEvents.get(0));
     }
 
     public void testLogEventRecoverFromThrottling() throws Exception {
-        final long throttleTimeout = System.currentTimeMillis() + 50;
+        final long throttleTimeout = System.currentTimeMillis() + 10;
         when(mService.logEvent(any())).thenReturn(throttleTimeout, 0L);
 
-        assertFalse(mLog.log(1, FAKE_EV));
-        new Thread() {
-            public void run() {
-                busySpinLog();
-            }
-        }.start();
+        mLog.logEvent(1, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV);
+        mLog.logEvent(2, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV);
+        mLog.logEvent(3, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV);
+        Thread.sleep(100);
+        mLog.logEvent(53, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV);
 
-        List<ConnectivityMetricsEvent> gotEvents = verifyEvents(2, 200);
+        List<ConnectivityMetricsEvent> gotEvents = verifyEvents(1);
         assertEventsEqual(expectedEvent(1), gotEvents.get(0));
-        assertEventsEqual(expectedEvent(2), gotEvents.get(1));
-    }
 
-    public void testLogEventRecoverFromThrottlingWithMultipleCallers() throws Exception {
-        final long throttleTimeout = System.currentTimeMillis() + 50;
-        when(mService.logEvent(any())).thenReturn(throttleTimeout, 0L);
-
-        assertFalse(mLog.log(1, FAKE_EV));
-        final int nCallers = 10;
-        for (int i = 0; i < nCallers; i++) {
-            new Thread() {
-                public void run() {
-                    busySpinLog();
-                }
-            }.start();
-        }
-
-        List<ConnectivityMetricsEvent> gotEvents = verifyEvents(1 + nCallers, 200);
-        assertEventsEqual(expectedEvent(1), gotEvents.get(0));
-        for (int i = 0; i < nCallers; i++) {
-            assertEventsEqual(expectedEvent(2), gotEvents.get(1 + i));
-        }
-    }
-
-    void busySpinLog() {
-        final long timeout = 200;
-        final long stop = System.currentTimeMillis() + timeout;
-        try {
-            while (System.currentTimeMillis() < stop) {
-                if (mLog.log(2, FAKE_EV)) {
-                    return;
-                }
-                Thread.sleep(10);
-            }
-        } catch (InterruptedException e) { }
+        verify(mService, times(1)).logEvents(evArrayCaptor.capture());
+        ConnectivityMetricsEvent[] gotOtherEvents = evArrayCaptor.getAllValues().get(0);
+        assertEquals(ConnectivityMetricsLogger.TAG_SKIPPED_EVENTS, gotOtherEvents[0].eventTag);
+        assertEventsEqual(expectedEvent(53), gotOtherEvents[1]);
     }
 
     List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception {
@@ -143,13 +116,8 @@
         return evCaptor.getAllValues();
     }
 
-    List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
-        verify(mService, timeout(timeoutMs).times(n)).logEvent(evCaptor.capture());
-        return evCaptor.getAllValues();
-    }
-
     static ConnectivityMetricsEvent expectedEvent(int timestamp) {
-        return new ConnectivityMetricsEvent((long)timestamp, 0, 0, FAKE_EV);
+        return new ConnectivityMetricsEvent((long)timestamp, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV);
     }
 
     /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 340be62..257341b 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -596,7 +596,7 @@
 
         @Override
         protected CaptivePortalProbeResult isCaptivePortal() {
-            return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl);
+            return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index e72a8dc..9c241d7 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.accounts;
 
+import static android.database.sqlite.SQLiteDatabase.deleteDatabase;
+import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -24,7 +26,7 @@
 import android.accounts.AccountManagerInternal;
 import android.accounts.AuthenticatorDescription;
 import android.app.AppOpsManager;
-import android.app.Notification;
+import android.app.INotificationManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -38,16 +40,14 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.test.AndroidTestCase;
 import android.test.mock.MockContext;
-import android.test.mock.MockPackageManager;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 
-import com.android.server.LocalServices;
-
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -55,29 +55,38 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Comparator;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 public class AccountManagerServiceTest extends AndroidTestCase {
     private static final String TAG = AccountManagerServiceTest.class.getSimpleName();
 
-    static final String PREN_DB = "pren.db";
-    static final String DE_DB = "de.db";
-    static final String CE_DB = "ce.db";
+    private static final String PREN_DB = "pren.db";
+    private static final String DE_DB = "de.db";
+    private static final String CE_DB = "ce.db";
     private AccountManagerService mAms;
+    private TestInjector mTestInjector;
 
     @Override
     protected void setUp() throws Exception {
         Context realTestContext = getContext();
-        Context mockContext = new MyMockContext(realTestContext);
+        MyMockContext mockContext = new MyMockContext(realTestContext);
         setContext(mockContext);
-        mAms = createAccountManagerService(mockContext, realTestContext);
+        mTestInjector = new TestInjector(realTestContext, mockContext);
+        mAms = new AccountManagerService(mTestInjector);
     }
 
     @Override
     protected void tearDown() throws Exception {
-        SQLiteDatabase.deleteDatabase(new File(mAms.getCeDatabaseName(UserHandle.USER_SYSTEM)));
-        SQLiteDatabase.deleteDatabase(new File(mAms.getDeDatabaseName(UserHandle.USER_SYSTEM)));
-        SQLiteDatabase.deleteDatabase(new File(mAms.getPreNDatabaseName(UserHandle.USER_SYSTEM)));
-        LocalServices.removeServiceForTest(AccountManagerInternal.class);
+        // Let async logging tasks finish, otherwise they may crash due to db being removed
+        CountDownLatch cdl = new CountDownLatch(1);
+        mAms.mHandler.post(() -> {
+            deleteDatabase(new File(mTestInjector.getCeDatabaseName(UserHandle.USER_SYSTEM)));
+            deleteDatabase(new File(mTestInjector.getDeDatabaseName(UserHandle.USER_SYSTEM)));
+            deleteDatabase(new File(mTestInjector.getPreNDatabaseName(UserHandle.USER_SYSTEM)));
+            cdl.countDown();
+        });
+        cdl.await(1, TimeUnit.SECONDS);
         super.tearDown();
     }
 
@@ -230,7 +239,7 @@
 
         Context originalContext = ((MyMockContext)getContext()).mTestContext;
         // create a separate instance of AMS. It initially assumes that user0 is locked
-        AccountManagerService ams2 = createAccountManagerService(getContext(), originalContext);
+        AccountManagerService ams2 = new AccountManagerService(mTestInjector);
 
         // Verify that account can be removed when user is locked
         ams2.removeAccountInternal(a1);
@@ -239,7 +248,7 @@
         assertEquals("Only a2 should be returned", a2, accounts[0]);
 
         // Verify that CE db file is unchanged and still has 2 accounts
-        String ceDatabaseName = mAms.getCeDatabaseName(UserHandle.USER_SYSTEM);
+        String ceDatabaseName = mTestInjector.getCeDatabaseName(UserHandle.USER_SYSTEM);
         int accountsNumber = readNumberOfAccountsFromDbFile(originalContext, ceDatabaseName);
         assertEquals("CE database should still have 2 accounts", 2, accountsNumber);
 
@@ -254,7 +263,7 @@
 
     @SmallTest
     public void testPreNDatabaseMigration() throws Exception {
-        String preNDatabaseName = mAms.getPreNDatabaseName(UserHandle.USER_SYSTEM);
+        String preNDatabaseName = mTestInjector.getPreNDatabaseName(UserHandle.USER_SYSTEM);
         Context originalContext = ((MyMockContext) getContext()).mTestContext;
         PreNTestDatabaseHelper.createV4Database(originalContext, preNDatabaseName);
         // Assert that database was created with 1 account
@@ -275,8 +284,8 @@
                 new File(preNDatabaseName).exists());
 
         // Verify that ce/de files are present
-        String deDatabaseName = mAms.getDeDatabaseName(UserHandle.USER_SYSTEM);
-        String ceDatabaseName = mAms.getCeDatabaseName(UserHandle.USER_SYSTEM);
+        String deDatabaseName = mTestInjector.getDeDatabaseName(UserHandle.USER_SYSTEM);
+        String ceDatabaseName = mTestInjector.getCeDatabaseName(UserHandle.USER_SYSTEM);
         assertTrue("DE database file should be created at " + deDatabaseName,
                 new File(deDatabaseName).exists());
         assertTrue("CE database file should be created at " + ceDatabaseName,
@@ -291,13 +300,6 @@
         }
     }
 
-    private AccountManagerService createAccountManagerService(Context mockContext,
-            Context realContext) {
-        LocalServices.removeServiceForTest(AccountManagerInternal.class);
-        return new MyAccountManagerService(mockContext,
-                new MyMockPackageManager(), new MockAccountAuthenticatorCache(), realContext);
-    }
-
     private void unlockSystemUser() {
         mAms.onUserUnlocked(newIntentForUser(UserHandle.USER_SYSTEM));
     }
@@ -366,6 +368,8 @@
             this.mAppOpsManager = mock(AppOpsManager.class);
             this.mUserManager = mock(UserManager.class);
             this.mPackageManager = mock(PackageManager.class);
+            when(mPackageManager.checkSignatures(anyInt(), anyInt()))
+                    .thenReturn(PackageManager.SIGNATURE_MATCH);
             final UserInfo ui = new UserInfo(UserHandle.USER_SYSTEM, "user0", 0);
             when(mUserManager.getUserInfo(eq(ui.id))).thenReturn(ui);
         }
@@ -381,6 +385,11 @@
         }
 
         @Override
+        public String getPackageName() {
+            return mTestContext.getPackageName();
+        }
+
+        @Override
         public Object getSystemService(String name) {
             if (Context.APP_OPS_SERVICE.equals(name)) {
                 return mAppOpsManager;
@@ -427,47 +436,45 @@
         }
     }
 
-    static class MyMockPackageManager extends MockPackageManager {
-        @Override
-        public int checkSignatures(final int uid1, final int uid2) {
-            return PackageManager.SIGNATURE_MATCH;
+    static class TestInjector extends AccountManagerService.Injector {
+        private Context mRealContext;
+        TestInjector(Context realContext, MyMockContext mockContext) {
+            super(mockContext);
+            mRealContext = realContext;
         }
 
         @Override
-        public void addOnPermissionsChangeListener(
-                OnPermissionsChangedListener listener) {
-        }
-    }
-
-    static class MyAccountManagerService extends AccountManagerService {
-        private Context mRealTestContext;
-        MyAccountManagerService(Context context, PackageManager packageManager,
-                IAccountAuthenticatorCache authenticatorCache, Context realTestContext) {
-            super(context, packageManager, authenticatorCache);
-            this.mRealTestContext = realTestContext;
+        Looper getMessageHandlerLooper() {
+            return Looper.getMainLooper();
         }
 
         @Override
-        protected void installNotification(final int notificationId, final Notification n, UserHandle user) {
+        void addLocalService(AccountManagerInternal service) {
         }
 
         @Override
-        protected void cancelNotification(final int id, UserHandle user) {
+        IAccountAuthenticatorCache getAccountAuthenticatorCache() {
+            return new MockAccountAuthenticatorCache();
         }
 
         @Override
         protected String getCeDatabaseName(int userId) {
-            return new File(mRealTestContext.getCacheDir(), CE_DB).getPath();
+            return new File(mRealContext.getCacheDir(), CE_DB).getPath();
         }
 
         @Override
         protected String getDeDatabaseName(int userId) {
-            return new File(mRealTestContext.getCacheDir(), DE_DB).getPath();
+            return new File(mRealContext.getCacheDir(), DE_DB).getPath();
         }
 
         @Override
         String getPreNDatabaseName(int userId) {
-            return new File(mRealTestContext.getCacheDir(), PREN_DB).getPath();
+            return new File(mRealContext.getCacheDir(), PREN_DB).getPath();
+        }
+
+        @Override
+        INotificationManager getNotificationManager() {
+            return mock(INotificationManager.class);
         }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java b/services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java
new file mode 100644
index 0000000..b47d17e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import static android.support.test.InstrumentationRegistry.getInstrumentation;
+
+import android.app.Activity;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
+import android.app.ITaskStackListener;
+import android.content.Context;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.UiDevice;
+
+import com.android.internal.annotations.GuardedBy;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class TaskStackChangedListenerTest extends ITaskStackListener.Stub {
+
+    private IActivityManager mService;
+
+    private static final Object sLock = new Object();
+    @GuardedBy("sLock")
+    private static boolean sTaskStackChangedCalled;
+    private static boolean sActivityBResumed;
+
+    @Before
+    public void setUp() throws Exception {
+        mService = ActivityManagerNative.getDefault();
+        mService.registerTaskStackListener(this);
+    }
+
+    @Test
+    public void testTaskStackChanged_afterFinish() throws Exception {
+        Context ctx = InstrumentationRegistry.getContext();
+        ctx.startActivity(new Intent(ctx, ActivityA.class));
+        UiDevice.getInstance(getInstrumentation()).waitForIdle();
+        synchronized (sLock) {
+            Assert.assertTrue(sTaskStackChangedCalled);
+        }
+        Assert.assertTrue(sActivityBResumed);
+    }
+
+    @Override
+    public void onTaskStackChanged() throws RemoteException {
+        synchronized (sLock) {
+            sTaskStackChangedCalled = true;
+        }
+    }
+
+    @Override
+    public void onActivityPinned() throws RemoteException {
+    }
+
+    @Override
+    public void onPinnedActivityRestartAttempt() throws RemoteException {
+    }
+
+    @Override
+    public void onPinnedStackAnimationEnded() throws RemoteException {
+    }
+
+    @Override
+    public void onActivityForcedResizable(String packageName, int taskId) throws RemoteException {
+    }
+
+    @Override
+    public void onActivityDismissingDockedStack() throws RemoteException {
+    }
+
+    public static class ActivityA extends Activity {
+
+        private boolean mActivityBLaunched = false;
+
+        @Override
+        protected void onPostResume() {
+            super.onPostResume();
+            if (mActivityBLaunched) {
+                return;
+            }
+            mActivityBLaunched = true;
+            finish();
+            startActivity(new Intent(this, ActivityB.class));
+        }
+    }
+
+    public static class ActivityB extends Activity {
+
+        @Override
+        protected void onPostResume() {
+            super.onPostResume();
+            synchronized (sLock) {
+                sTaskStackChangedCalled = false;
+            }
+            sActivityBResumed = true;
+            finish();
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
new file mode 100644
index 0000000..aed3635
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity;
+
+import android.net.ConnectivityMetricsEvent;
+import android.net.metrics.ApfProgramEvent;
+import android.net.metrics.ApfStats;
+import android.net.metrics.DefaultNetworkEvent;
+import android.net.metrics.DhcpClientEvent;
+import android.net.metrics.DhcpErrorEvent;
+import android.net.metrics.DnsEvent;
+import android.net.metrics.IpManagerEvent;
+import android.net.metrics.IpReachabilityEvent;
+import android.net.metrics.NetworkEvent;
+import android.net.metrics.RaEvent;
+import android.net.metrics.ValidationProbeEvent;
+import com.google.protobuf.nano.MessageNano;
+import java.util.Arrays;
+import junit.framework.TestCase;
+
+import static com.android.server.connectivity.metrics.IpConnectivityLogClass.IpConnectivityLog;
+import static com.android.server.connectivity.MetricsTestUtil.aBool;
+import static com.android.server.connectivity.MetricsTestUtil.aByteArray;
+import static com.android.server.connectivity.MetricsTestUtil.aLong;
+import static com.android.server.connectivity.MetricsTestUtil.aString;
+import static com.android.server.connectivity.MetricsTestUtil.aType;
+import static com.android.server.connectivity.MetricsTestUtil.anInt;
+import static com.android.server.connectivity.MetricsTestUtil.anIntArray;
+import static com.android.server.connectivity.MetricsTestUtil.b;
+import static com.android.server.connectivity.MetricsTestUtil.describeIpEvent;
+import static com.android.server.connectivity.MetricsTestUtil.ipEv;
+
+public class IpConnectivityEventBuilderTest extends TestCase {
+
+    public void testDefaultNetworkEventSerialization() {
+        ConnectivityMetricsEvent ev = describeIpEvent(
+                aType(DefaultNetworkEvent.class),
+                anInt(102),
+                anIntArray(1, 2, 3),
+                anInt(101),
+                aBool(true),
+                aBool(false));
+
+        String want = joinLines(
+                "dropped_events: 0",
+                "events <",
+                "  default_network_event <",
+                "    network_id <",
+                "      network_id: 102",
+                "    >",
+                "    previous_network_id <",
+                "      network_id: 101",
+                "    >",
+                "    previous_network_ip_support: 1",
+                "    transport_types: 1",
+                "    transport_types: 2",
+                "    transport_types: 3",
+                "  >",
+                "  time_ms: 1",
+                ">");
+
+        verifySerialization(want, ev);
+    }
+
+    public void testDhcpClientEventSerialization() {
+        ConnectivityMetricsEvent ev = describeIpEvent(
+                aType(DhcpClientEvent.class),
+                aString("wlan0"),
+                aString("SomeState"),
+                anInt(192));
+
+        String want = joinLines(
+                "dropped_events: 0",
+                "events <",
+                "  dhcp_event <",
+                "    duration_ms: 192",
+                "    error_code: 0",
+                "    if_name: \"wlan0\"",
+                "    state_transition: \"SomeState\"",
+                "  >",
+                "  time_ms: 1",
+                ">");
+
+        verifySerialization(want, ev);
+    }
+
+    public void testDhcpErrorEventSerialization() {
+        ConnectivityMetricsEvent ev = describeIpEvent(
+                aType(DhcpErrorEvent.class),
+                aString("wlan0"),
+                anInt(DhcpErrorEvent.L4_NOT_UDP));
+
+        String want = joinLines(
+                "dropped_events: 0",
+                "events <",
+                "  dhcp_event <",
+                "    duration_ms: 0",
+                "    error_code: 50397184",
+                "    if_name: \"wlan0\"",
+                "    state_transition: \"\"",
+                "  >",
+                "  time_ms: 1",
+                ">");
+
+        verifySerialization(want, ev);
+    }
+
+    public void testDnsEventSerialization() {
+        ConnectivityMetricsEvent ev = describeIpEvent(
+                aType(DnsEvent.class),
+                anInt(101),
+                aByteArray(b(1), b(1), b(2), b(1), b(1), b(1), b(2), b(2)),
+                aByteArray(b(0), b(0), b(22), b(3), b(1), b(0), b(200), b(178)),
+                anIntArray(3456, 267, 1230, 45, 2111, 450, 638, 1300));
+
+        String want = joinLines(
+                "dropped_events: 0",
+                "events <",
+                "  dns_lookup_batch <",
+                "    event_types: 1",
+                "    event_types: 1",
+                "    event_types: 2",
+                "    event_types: 1",
+                "    event_types: 1",
+                "    event_types: 1",
+                "    event_types: 2",
+                "    event_types: 2",
+                "    latencies_ms: 3456",
+                "    latencies_ms: 267",
+                "    latencies_ms: 1230",
+                "    latencies_ms: 45",
+                "    latencies_ms: 2111",
+                "    latencies_ms: 450",
+                "    latencies_ms: 638",
+                "    latencies_ms: 1300",
+                "    network_id <",
+                "      network_id: 101",
+                "    >",
+                "    return_codes: 0",
+                "    return_codes: 0",
+                "    return_codes: 22",
+                "    return_codes: 3",
+                "    return_codes: 1",
+                "    return_codes: 0",
+                "    return_codes: 200",
+                "    return_codes: 178",
+                "  >",
+                "  time_ms: 1",
+                ">");
+
+        verifySerialization(want, ev);
+    }
+
+    public void testIpManagerEventSerialization() {
+        ConnectivityMetricsEvent ev = describeIpEvent(
+                aType(IpManagerEvent.class),
+                aString("wlan0"),
+                anInt(IpManagerEvent.PROVISIONING_OK),
+                aLong(5678));
+
+        String want = joinLines(
+                "dropped_events: 0",
+                "events <",
+                "  ip_provisioning_event <",
+                "    event_type: 1",
+                "    if_name: \"wlan0\"",
+                "    latency_ms: 5678",
+                "  >",
+                "  time_ms: 1",
+                ">");
+
+        verifySerialization(want, ev);
+    }
+
+    public void testIpReachabilityEventSerialization() {
+        ConnectivityMetricsEvent ev = describeIpEvent(
+                aType(IpReachabilityEvent.class),
+                aString("wlan0"),
+                anInt(IpReachabilityEvent.NUD_FAILED));
+
+        String want = joinLines(
+                "dropped_events: 0",
+                "events <",
+                "  ip_reachability_event <",
+                "    event_type: 512",
+                "    if_name: \"wlan0\"",
+                "  >",
+                "  time_ms: 1",
+                ">");
+
+        verifySerialization(want, ev);
+    }
+
+    public void testNetworkEventSerialization() {
+        ConnectivityMetricsEvent ev = describeIpEvent(
+                aType(NetworkEvent.class),
+                anInt(100),
+                anInt(5),
+                aLong(20410));
+
+        String want = joinLines(
+                "dropped_events: 0",
+                "events <",
+                "  network_event <",
+                "    event_type: 5",
+                "    latency_ms: 20410",
+                "    network_id <",
+                "      network_id: 100",
+                "    >",
+                "  >",
+                "  time_ms: 1",
+                ">");
+
+        verifySerialization(want, ev);
+    }
+
+    public void testValidationProbeEventSerialization() {
+        ConnectivityMetricsEvent ev = describeIpEvent(
+                aType(ValidationProbeEvent.class),
+                anInt(120),
+                aLong(40730),
+                anInt(ValidationProbeEvent.PROBE_HTTP),
+                anInt(204));
+
+        String want = joinLines(
+                "dropped_events: 0",
+                "events <",
+                "  time_ms: 1",
+                "  validation_probe_event <",
+                "    latency_ms: 40730",
+                "    network_id <",
+                "      network_id: 120",
+                "    >",
+                "    probe_result: 204",
+                "    probe_type: 1",
+                "  >",
+                ">");
+
+        verifySerialization(want, ev);
+    }
+
+    public void testApfProgramEventSerialization() {
+        ConnectivityMetricsEvent ev = describeIpEvent(
+                aType(ApfProgramEvent.class),
+                aLong(200),
+                anInt(7),
+                anInt(9),
+                anInt(2048),
+                anInt(3));
+
+        String want = joinLines(
+                "dropped_events: 0",
+                "events <",
+                "  apf_program_event <",
+                "    current_ras: 9",
+                "    drop_multicast: true",
+                "    filtered_ras: 7",
+                "    has_ipv4_addr: true",
+                "    lifetime: 200",
+                "    program_length: 2048",
+                "  >",
+                "  time_ms: 1",
+                ">");
+
+        verifySerialization(want, ev);
+    }
+
+    public void testApfStatsSerialization() {
+        ConnectivityMetricsEvent ev = describeIpEvent(
+                aType(ApfStats.class),
+                aLong(45000),
+                anInt(10),
+                anInt(2),
+                anInt(2),
+                anInt(1),
+                anInt(2),
+                anInt(4),
+                anInt(2048));
+
+        String want = joinLines(
+                "dropped_events: 0",
+                "events <",
+                "  apf_statistics <",
+                "    dropped_ras: 2",
+                "    duration_ms: 45000",
+                "    matching_ras: 2",
+                "    max_program_size: 2048",
+                "    parse_errors: 2",
+                "    program_updates: 4",
+                "    received_ras: 10",
+                "    zero_lifetime_ras: 1",
+                "  >",
+                "  time_ms: 1",
+                ">");
+
+        verifySerialization(want, ev);
+    }
+
+    public void testRaEventSerialization() {
+        ConnectivityMetricsEvent ev = describeIpEvent(
+                aType(RaEvent.class),
+                aLong(2000),
+                aLong(400),
+                aLong(300),
+                aLong(-1),
+                aLong(1000),
+                aLong(-1));
+
+        String want = joinLines(
+                "dropped_events: 0",
+                "events <",
+                "  ra_event <",
+                "    dnssl_lifetime: -1",
+                "    prefix_preferred_lifetime: 300",
+                "    prefix_valid_lifetime: 400",
+                "    rdnss_lifetime: 1000",
+                "    route_info_lifetime: -1",
+                "    router_lifetime: 2000",
+                "  >",
+                "  time_ms: 1",
+                ">");
+
+        verifySerialization(want, ev);
+    }
+
+    static void verifySerialization(String want, ConnectivityMetricsEvent... input) {
+        try {
+            byte[] got = IpConnectivityEventBuilder.serialize(0, Arrays.asList(input));
+            IpConnectivityLog log = new IpConnectivityLog();
+            MessageNano.mergeFrom(log, got);
+            assertEquals(want, log.toString());
+        } catch (Exception e) {
+            fail(e.toString());
+        }
+    }
+
+    static String joinLines(String ... elems) {
+        StringBuilder b = new StringBuilder();
+        for (String s : elems) {
+            b.append(s);
+            b.append("\n");
+        }
+        return b.toString();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityMetricsTest.java b/services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityMetricsTest.java
new file mode 100644
index 0000000..3fc89b9
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity;
+
+import android.content.Context;
+import android.net.ConnectivityMetricsEvent;
+import android.net.IIpConnectivityMetrics;
+import android.net.metrics.ApfStats;
+import android.net.metrics.DefaultNetworkEvent;
+import android.net.metrics.DhcpClientEvent;
+import android.net.metrics.IpConnectivityLog;
+import android.net.metrics.IpManagerEvent;
+import android.net.metrics.IpReachabilityEvent;
+import android.net.metrics.RaEvent;
+import android.net.metrics.ValidationProbeEvent;
+import android.os.Parcelable;
+import android.util.Base64;
+import com.android.server.connectivity.metrics.IpConnectivityLogClass;
+import com.google.protobuf.nano.MessageNano;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import junit.framework.TestCase;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+public class IpConnectivityMetricsTest extends TestCase {
+    static final IpReachabilityEvent FAKE_EV =
+            new IpReachabilityEvent("wlan0", IpReachabilityEvent.NUD_FAILED);
+
+    @Mock Context mCtx;
+    @Mock IIpConnectivityMetrics mMockService;
+
+    IpConnectivityMetrics mService;
+
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mService = new IpConnectivityMetrics(mCtx);
+    }
+
+    public void testLoggingEvents() throws Exception {
+        IpConnectivityLog logger = new IpConnectivityLog(mMockService);
+
+        assertTrue(logger.log(1, FAKE_EV));
+        assertTrue(logger.log(2, FAKE_EV));
+        assertTrue(logger.log(3, FAKE_EV));
+
+        List<ConnectivityMetricsEvent> got = verifyEvents(3);
+        assertEventsEqual(expectedEvent(1), got.get(0));
+        assertEventsEqual(expectedEvent(2), got.get(1));
+        assertEventsEqual(expectedEvent(3), got.get(2));
+    }
+
+    public void testLoggingEventsWithMultipleCallers() throws Exception {
+        IpConnectivityLog logger = new IpConnectivityLog(mMockService);
+
+        final int nCallers = 10;
+        final int nEvents = 10;
+        for (int n = 0; n < nCallers; n++) {
+            final int i = n;
+            new Thread() {
+                public void run() {
+                    for (int j = 0; j < nEvents; j++) {
+                        assertTrue(logger.log(i * 100 + j, FAKE_EV));
+                    }
+                }
+            }.start();
+        }
+
+        List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 100);
+        Collections.sort(got, EVENT_COMPARATOR);
+        Iterator<ConnectivityMetricsEvent> iter = got.iterator();
+        for (int i = 0; i < nCallers; i++) {
+            for (int j = 0; j < nEvents; j++) {
+                int expectedTimestamp = i * 100 + j;
+                assertEventsEqual(expectedEvent(expectedTimestamp), iter.next());
+            }
+        }
+    }
+
+    public void testBufferFlushing() {
+        String output1 = getdump("flush");
+        assertEquals("", output1);
+
+        new IpConnectivityLog(mService.impl).log(1, FAKE_EV);
+        String output2 = getdump("flush");
+        assertFalse("".equals(output2));
+
+        String output3 = getdump("flush");
+        assertEquals("", output3);
+    }
+
+    public void testEndToEndLogging() {
+        IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
+
+        Parcelable[] events = {
+            new IpReachabilityEvent("wlan0", IpReachabilityEvent.NUD_FAILED),
+            new DhcpClientEvent("wlan0", "SomeState", 192),
+            new DefaultNetworkEvent(102, new int[]{1,2,3}, 101, true, false),
+            new IpManagerEvent("wlan0", IpManagerEvent.PROVISIONING_OK, 5678),
+            new ValidationProbeEvent(120, 40730, ValidationProbeEvent.PROBE_HTTP, 204),
+            new ApfStats(45000, 10, 2, 2, 1, 2, 4, 2048),
+            new RaEvent(2000, 400, 300, -1, 1000, -1)
+        };
+
+        for (int i = 0; i < events.length; i++) {
+            logger.log(100 * (i + 1), events[i]);
+        }
+
+        String want = joinLines(
+                "dropped_events: 0",
+                "events <",
+                "  ip_reachability_event <",
+                "    event_type: 512",
+                "    if_name: \"wlan0\"",
+                "  >",
+                "  time_ms: 100",
+                ">",
+                "events <",
+                "  dhcp_event <",
+                "    duration_ms: 192",
+                "    error_code: 0",
+                "    if_name: \"wlan0\"",
+                "    state_transition: \"SomeState\"",
+                "  >",
+                "  time_ms: 200",
+                ">",
+                "events <",
+                "  default_network_event <",
+                "    network_id <",
+                "      network_id: 102",
+                "    >",
+                "    previous_network_id <",
+                "      network_id: 101",
+                "    >",
+                "    previous_network_ip_support: 1",
+                "    transport_types: 1",
+                "    transport_types: 2",
+                "    transport_types: 3",
+                "  >",
+                "  time_ms: 300",
+                ">",
+                "events <",
+                "  ip_provisioning_event <",
+                "    event_type: 1",
+                "    if_name: \"wlan0\"",
+                "    latency_ms: 5678",
+                "  >",
+                "  time_ms: 400",
+                ">",
+                "events <",
+                "  time_ms: 500",
+                "  validation_probe_event <",
+                "    latency_ms: 40730",
+                "    network_id <",
+                "      network_id: 120",
+                "    >",
+                "    probe_result: 204",
+                "    probe_type: 1",
+                "  >",
+                ">",
+                "events <",
+                "  apf_statistics <",
+                "    dropped_ras: 2",
+                "    duration_ms: 45000",
+                "    matching_ras: 2",
+                "    max_program_size: 2048",
+                "    parse_errors: 2",
+                "    program_updates: 4",
+                "    received_ras: 10",
+                "    zero_lifetime_ras: 1",
+                "  >",
+                "  time_ms: 600",
+                ">",
+                "events <",
+                "  ra_event <",
+                "    dnssl_lifetime: -1",
+                "    prefix_preferred_lifetime: 300",
+                "    prefix_valid_lifetime: 400",
+                "    rdnss_lifetime: 1000",
+                "    route_info_lifetime: -1",
+                "    router_lifetime: 2000",
+                "  >",
+                "  time_ms: 700",
+                ">");
+
+        verifySerialization(want, getdump("flush"));
+    }
+
+    String getdump(String ... command) {
+        StringWriter buffer = new StringWriter();
+        PrintWriter writer = new PrintWriter(buffer);
+        mService.impl.dump(null, writer, command);
+        return buffer.toString();
+    }
+
+    List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
+        ArgumentCaptor<ConnectivityMetricsEvent> captor =
+                ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
+        verify(mMockService, timeout(timeoutMs).times(n)).logEvent(captor.capture());
+        return captor.getAllValues();
+    }
+
+    List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception {
+        return verifyEvents(n, 10);
+    }
+
+    static void verifySerialization(String want, String output) {
+        try {
+            byte[] got = Base64.decode(output, Base64.DEFAULT);
+            IpConnectivityLogClass.IpConnectivityLog log =
+                    new IpConnectivityLogClass.IpConnectivityLog();
+            MessageNano.mergeFrom(log, got);
+            assertEquals(want, log.toString());
+        } catch (Exception e) {
+            fail(e.toString());
+        }
+    }
+
+    static String joinLines(String ... elems) {
+        StringBuilder b = new StringBuilder();
+        for (String s : elems) {
+            b.append(s).append("\n");
+        }
+        return b.toString();
+    }
+
+    static ConnectivityMetricsEvent expectedEvent(int timestamp) {
+        return new ConnectivityMetricsEvent((long)timestamp, 0, 0, FAKE_EV);
+    }
+
+    /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
+    static void assertEventsEqual(ConnectivityMetricsEvent expected, ConnectivityMetricsEvent got) {
+        assertEquals(expected.timestamp, got.timestamp);
+        assertEquals(expected.componentTag, got.componentTag);
+        assertEquals(expected.eventTag, got.eventTag);
+        assertEquals(expected.data, got.data);
+    }
+
+    static final Comparator<ConnectivityMetricsEvent> EVENT_COMPARATOR =
+        new Comparator<ConnectivityMetricsEvent>() {
+            @Override
+            public int compare(ConnectivityMetricsEvent ev1, ConnectivityMetricsEvent ev2) {
+                return (int) (ev1.timestamp - ev2.timestamp);
+            }
+        };
+}
diff --git a/services/tests/servicestests/src/com/android/server/connectivity/MetricsTestUtil.java b/services/tests/servicestests/src/com/android/server/connectivity/MetricsTestUtil.java
new file mode 100644
index 0000000..e201012
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/connectivity/MetricsTestUtil.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity;
+
+import android.net.ConnectivityMetricsEvent;
+import android.net.ConnectivityMetricsLogger;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+abstract public class MetricsTestUtil {
+    private MetricsTestUtil() {
+    }
+
+    static ConnectivityMetricsEvent ipEv(Parcelable p) {
+        return ev(ConnectivityMetricsLogger.COMPONENT_TAG_CONNECTIVITY, p);
+    }
+
+    static ConnectivityMetricsEvent telephonyEv() {
+        return ev(ConnectivityMetricsLogger.COMPONENT_TAG_TELEPHONY, new Bundle());
+    }
+
+    static ConnectivityMetricsEvent ev(int tag, Parcelable p) {
+        return new ConnectivityMetricsEvent(1L, tag, 0, p);
+    }
+
+    // Utiliy interface for describing the content of a Parcel. This relies on
+    // the implementation defails of Parcelable and on the fact that the fully
+    // qualified Parcelable class names are written as string in the Parcels.
+    interface ParcelField {
+        void write(Parcel p);
+    }
+
+    static ConnectivityMetricsEvent describeIpEvent(ParcelField... fs) {
+        Parcel p = Parcel.obtain();
+        for (ParcelField f : fs) {
+            f.write(p);
+        }
+        p.setDataPosition(0);
+        return ipEv(p.readParcelable(ClassLoader.getSystemClassLoader()));
+    }
+
+    static ParcelField aType(Class<?> c) {
+        return new ParcelField() {
+            public void write(Parcel p) {
+                p.writeString(c.getName());
+            }
+        };
+    }
+
+    static ParcelField aBool(boolean b) {
+        return aByte((byte) (b ? 1 : 0));
+    }
+
+    static ParcelField aByte(byte b) {
+        return new ParcelField() {
+            public void write(Parcel p) {
+                p.writeByte(b);
+            }
+        };
+    }
+
+    static ParcelField anInt(int i) {
+        return new ParcelField() {
+            public void write(Parcel p) {
+                p.writeInt(i);
+            }
+        };
+    }
+
+    static ParcelField aLong(long l) {
+        return new ParcelField() {
+            public void write(Parcel p) {
+                p.writeLong(l);
+            }
+        };
+    }
+
+    static ParcelField aString(String s) {
+        return new ParcelField() {
+            public void write(Parcel p) {
+                p.writeString(s);
+            }
+        };
+    }
+
+    static ParcelField aByteArray(byte... ary) {
+        return new ParcelField() {
+            public void write(Parcel p) {
+                p.writeByteArray(ary);
+            }
+        };
+    }
+
+    static ParcelField anIntArray(int... ary) {
+        return new ParcelField() {
+            public void write(Parcel p) {
+                p.writeIntArray(ary);
+            }
+        };
+    }
+
+    static byte b(int i) {
+        return (byte) i;
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/connectivity/NetdEventListenerServiceTest.java b/services/tests/servicestests/src/com/android/server/connectivity/NetdEventListenerServiceTest.java
index 11cf528..63d5d9fb 100644
--- a/services/tests/servicestests/src/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -66,7 +66,7 @@
         }
     }
 
-    NetdEventListenerService mNetdService;
+    NetdEventListenerService mNetdEventListenerService;
 
     @Mock ConnectivityManager mCm;
     @Mock IpConnectivityLog mLog;
@@ -77,7 +77,7 @@
         MockitoAnnotations.initMocks(this);
         mCallbackCaptor = ArgumentCaptor.forClass(NetworkCallback.class);
         mEvCaptor = ArgumentCaptor.forClass(DnsEvent.class);
-        mNetdService = new NetdEventListenerService(mCm, mLog);
+        mNetdEventListenerService = new NetdEventListenerService(mCm, mLog);
 
         verify(mCm, times(1)).registerNetworkCallback(any(), mCallbackCaptor.capture());
     }
@@ -131,7 +131,7 @@
         new Thread() {
             public void run() {
                 while (System.currentTimeMillis() < stop) {
-                    mNetdService.dump(pw);
+                    mNetdEventListenerService.dump(pw);
                 }
             }
         }.start();
@@ -158,7 +158,7 @@
 
     void log(int netId, int[] latencies) {
         for (int l : latencies) {
-            mNetdService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l);
+            mNetdEventListenerService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l);
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
index c80ca6c..b4b74b3 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
@@ -131,7 +131,7 @@
 
         doReturn(ai).when(mMockContext.ipackageManager).getApplicationInfo(
                 eq(admin.getPackageName()),
-                eq(PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
+                anyInt(),
                 eq(UserHandle.getUserId(packageUid)));
 
         // Set up queryBroadcastReceivers().
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
index 3c99174..25f9100 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
@@ -68,7 +68,7 @@
                     /* fdin*/ null,
                     /* fdout*/ fd.getFileDescriptor(),
                     /* fderr*/ fd.getFileDescriptor(),
-                        args, rr);
+                        args, null, rr);
             }
             return readAll(out);
         } finally {
diff --git a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java b/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
index 56a170c..afb1197 100644
--- a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
@@ -46,6 +46,7 @@
 import android.content.res.Configuration;
 import android.media.AudioManager;
 import android.net.Uri;
+import android.net.wifi.WifiManager;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.Looper;
@@ -97,6 +98,7 @@
     private @Mock NotificationManager mNm;
     private @Mock ActivityManagerInternal mAmi;
     private @Mock AudioManager mAudioManager;
+    private @Mock WifiManager mWifiManager;
     private @Mock LockPatternUtils mLockPatternUtils;
     private MockPreloadAppsInstaller mPreloadAppsInstaller;
     private MockContentResolver mContentResolver;
@@ -227,6 +229,7 @@
         final UserInfo userInfo = new UserInfo(TEST_DEMO_USER, "demo_user",
                 UserInfo.FLAG_DEMO | UserInfo.FLAG_EPHEMERAL);
         when(mUm.getUserInfo(TEST_DEMO_USER)).thenReturn(userInfo);
+        when(mWifiManager.isWifiEnabled()).thenReturn(false);
         final int minVolume = -111;
         for (int stream : RetailDemoModeService.VOLUME_STREAMS_TO_MUTE) {
             when(mAudioManager.getStreamMinVolume(stream)).thenReturn(minVolume);
@@ -238,6 +241,7 @@
             verify(mAudioManager).setStreamVolume(stream, minVolume, 0);
         }
         verify(mLockPatternUtils).setLockScreenDisabled(true, TEST_DEMO_USER);
+        verify(mWifiManager).setWifiEnabled(true);
     }
 
     private void setCameraPackage(String pkgName) {
@@ -321,6 +325,11 @@
         }
 
         @Override
+        WifiManager getWifiManager() {
+            return mWifiManager;
+        }
+
+        @Override
         void switchUser(int userId) {
             if (mLatch != null) {
                 mLatch.countDown();
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
index 973f1b9..6eb347b 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
@@ -19,6 +19,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import android.content.res.Configuration;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -28,6 +29,8 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static org.junit.Assert.assertEquals;
@@ -178,25 +181,6 @@
     }
 
     @Test
-    public void testDetachFromDisplay() throws Exception {
-        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
-        final TestWindowContainer root = builder.setLayer(0).build();
-
-        final TestWindowContainer child1 = root.addChildWindow(builder.setCanDetach(true));
-        final TestWindowContainer child2 = root.addChildWindow();
-        final TestWindowContainer child11 = child1.addChildWindow();
-        final TestWindowContainer child12 = child1.addChildWindow(builder.setCanDetach(true));
-        final TestWindowContainer child21 = child2.addChildWindow();
-
-        assertTrue(root.detachFromDisplay());
-        assertTrue(child1.detachFromDisplay());
-        assertFalse(child11.detachFromDisplay());
-        assertTrue(child12.detachFromDisplay());
-        assertFalse(child2.detachFromDisplay());
-        assertFalse(child21.detachFromDisplay());
-    }
-
-    @Test
     public void testIsAnimating() throws Exception {
         final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
         final TestWindowContainer root = builder.setLayer(0).build();
@@ -396,10 +380,163 @@
         assertEquals(1, child2223.compareTo(child21));
     }
 
+    @Test
+    public void testConfigurationInit() throws Exception {
+        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+
+        // Check root container initial config.
+        final TestWindowContainer root = builder.setLayer(0).build();
+        assertEquals(Configuration.EMPTY, root.getOverrideConfiguration());
+        assertEquals(Configuration.EMPTY, root.getMergedOverrideConfiguration());
+        assertEquals(Configuration.EMPTY, root.getConfiguration());
+
+        // Check child initial config.
+        final TestWindowContainer child1 = root.addChildWindow();
+        assertEquals(Configuration.EMPTY, child1.getOverrideConfiguration());
+        assertEquals(Configuration.EMPTY, child1.getMergedOverrideConfiguration());
+        assertEquals(Configuration.EMPTY, child1.getConfiguration());
+
+        // Check child initial config if root has overrides.
+        final Configuration rootOverrideConfig = new Configuration();
+        rootOverrideConfig.fontScale = 1.3f;
+        root.onOverrideConfigurationChanged(rootOverrideConfig);
+        final TestWindowContainer child2 = root.addChildWindow();
+        assertEquals(Configuration.EMPTY, child2.getOverrideConfiguration());
+        assertEquals(rootOverrideConfig, child2.getMergedOverrideConfiguration());
+        assertEquals(rootOverrideConfig, child2.getConfiguration());
+
+        // Check child initial config if root has parent config set.
+        final Configuration rootParentConfig = new Configuration();
+        rootParentConfig.fontScale = 0.8f;
+        rootParentConfig.orientation = SCREEN_ORIENTATION_LANDSCAPE;
+        root.onConfigurationChanged(rootParentConfig);
+        final Configuration rootFullConfig = new Configuration(rootParentConfig);
+        rootFullConfig.updateFrom(rootOverrideConfig);
+
+        final TestWindowContainer child3 = root.addChildWindow();
+        assertEquals(Configuration.EMPTY, child3.getOverrideConfiguration());
+        assertEquals(rootOverrideConfig, child3.getMergedOverrideConfiguration());
+        assertEquals(rootFullConfig, child3.getConfiguration());
+    }
+
+    @Test
+    public void testConfigurationChangeOnAddRemove() throws Exception {
+        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+
+        // Init root's config.
+        final TestWindowContainer root = builder.setLayer(0).build();
+        final Configuration rootOverrideConfig = new Configuration();
+        rootOverrideConfig.fontScale = 1.3f;
+        root.onOverrideConfigurationChanged(rootOverrideConfig);
+
+        // Init child's config.
+        final TestWindowContainer child = root.addChildWindow();
+        final Configuration childOverrideConfig = new Configuration();
+        childOverrideConfig.densityDpi = 320;
+        child.onOverrideConfigurationChanged(childOverrideConfig);
+
+        // Check configuration update when child is removed from parent.
+        root.removeChild(child);
+        assertEquals(childOverrideConfig, child.getOverrideConfiguration());
+        assertEquals(childOverrideConfig, child.getMergedOverrideConfiguration());
+        assertEquals(childOverrideConfig, child.getConfiguration());
+
+        // It may be paranoia... but let's check if parent's config didn't change after removal.
+        assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
+        assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
+        assertEquals(rootOverrideConfig, root.getConfiguration());
+
+        // Check configuration update when child is added to parent.
+        final Configuration mergedOverrideConfig = new Configuration(root.getConfiguration());
+        mergedOverrideConfig.updateFrom(childOverrideConfig);
+        root.addChildWindow(child);
+        assertEquals(childOverrideConfig, child.getOverrideConfiguration());
+        assertEquals(mergedOverrideConfig, child.getMergedOverrideConfiguration());
+        assertEquals(mergedOverrideConfig, child.getConfiguration());
+    }
+
+    @Test
+    public void testConfigurationChangePropagation() throws Exception {
+        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+
+        // Builds 3-level vertical hierarchy with one window container on each level.
+        // In addition to different overrides on each level, everyone in hierarchy will have one
+        // common overridden value - orientation;
+
+        // Init root's config.
+        final TestWindowContainer root = builder.setLayer(0).build();
+        final Configuration rootOverrideConfig = new Configuration();
+        rootOverrideConfig.fontScale = 1.3f;
+        rootOverrideConfig.orientation = SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+        root.onOverrideConfigurationChanged(rootOverrideConfig);
+
+        // Init children.
+        final TestWindowContainer child1 = root.addChildWindow();
+        final Configuration childOverrideConfig1 = new Configuration();
+        childOverrideConfig1.densityDpi = 320;
+        childOverrideConfig1.orientation = SCREEN_ORIENTATION_LANDSCAPE;
+        child1.onOverrideConfigurationChanged(childOverrideConfig1);
+
+        final TestWindowContainer child2 = child1.addChildWindow();
+        final Configuration childOverrideConfig2 = new Configuration();
+        childOverrideConfig2.screenWidthDp = 150;
+        childOverrideConfig2.orientation = SCREEN_ORIENTATION_PORTRAIT;
+        child2.onOverrideConfigurationChanged(childOverrideConfig2);
+
+        // Check configuration on all levels when root override is updated.
+        rootOverrideConfig.smallestScreenWidthDp = 200;
+        root.onOverrideConfigurationChanged(rootOverrideConfig);
+
+        final Configuration mergedOverrideConfig1 = new Configuration(rootOverrideConfig);
+        mergedOverrideConfig1.updateFrom(childOverrideConfig1);
+        final Configuration mergedConfig1 = new Configuration(mergedOverrideConfig1);
+
+        final Configuration mergedOverrideConfig2 = new Configuration(mergedOverrideConfig1);
+        mergedOverrideConfig2.updateFrom(childOverrideConfig2);
+        final Configuration mergedConfig2 = new Configuration(mergedOverrideConfig2);
+
+        assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
+        assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
+        assertEquals(rootOverrideConfig, root.getConfiguration());
+
+        assertEquals(childOverrideConfig1, child1.getOverrideConfiguration());
+        assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration());
+        assertEquals(mergedConfig1, child1.getConfiguration());
+
+        assertEquals(childOverrideConfig2, child2.getOverrideConfiguration());
+        assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration());
+        assertEquals(mergedConfig2, child2.getConfiguration());
+
+        // Check configuration on all levels when root parent config is updated.
+        final Configuration rootParentConfig = new Configuration();
+        rootParentConfig.screenHeightDp = 100;
+        rootParentConfig.orientation = SCREEN_ORIENTATION_REVERSE_PORTRAIT;
+        root.onConfigurationChanged(rootParentConfig);
+        final Configuration mergedRootConfig = new Configuration(rootParentConfig);
+        mergedRootConfig.updateFrom(rootOverrideConfig);
+
+        mergedConfig1.setTo(mergedRootConfig);
+        mergedConfig1.updateFrom(mergedOverrideConfig1);
+
+        mergedConfig2.setTo(mergedConfig1);
+        mergedConfig2.updateFrom(mergedOverrideConfig2);
+
+        assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
+        assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
+        assertEquals(mergedRootConfig, root.getConfiguration());
+
+        assertEquals(childOverrideConfig1, child1.getOverrideConfiguration());
+        assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration());
+        assertEquals(mergedConfig1, child1.getConfiguration());
+
+        assertEquals(childOverrideConfig2, child2.getOverrideConfiguration());
+        assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration());
+        assertEquals(mergedConfig2, child2.getConfiguration());
+    }
+
     /* Used so we can gain access to some protected members of the {@link WindowContainer} class */
     private class TestWindowContainer extends WindowContainer<TestWindowContainer> {
         private final int mLayer;
-        private final boolean mCanDetach;
         private boolean mIsAnimating;
         private boolean mIsVisible;
         private boolean mFillsParent;
@@ -419,9 +556,8 @@
             return 1;
         };
 
-        TestWindowContainer(int layer, boolean canDetach, boolean isAnimating, boolean isVisible) {
+        TestWindowContainer(int layer, boolean isAnimating, boolean isVisible) {
             mLayer = layer;
-            mCanDetach = canDetach;
             mIsAnimating = isAnimating;
             mIsVisible = isVisible;
             mFillsParent = true;
@@ -455,11 +591,6 @@
         }
 
         @Override
-        boolean detachFromDisplay() {
-            return super.detachFromDisplay() || mCanDetach;
-        }
-
-        @Override
         boolean isAnimating() {
             return mIsAnimating || super.isAnimating();
         }
@@ -481,7 +612,6 @@
 
     private class TestWindowContainerBuilder {
         private int mLayer;
-        private boolean mCanDetach;
         private boolean mIsAnimating;
         private boolean mIsVisible;
 
@@ -494,11 +624,6 @@
             return this;
         }
 
-        TestWindowContainerBuilder setCanDetach(boolean canDetach) {
-            mCanDetach = canDetach;
-            return this;
-        }
-
         TestWindowContainerBuilder setIsAnimating(boolean isAnimating) {
             mIsAnimating = isAnimating;
             return this;
@@ -511,14 +636,13 @@
 
         TestWindowContainerBuilder reset() {
             mLayer = 0;
-            mCanDetach = false;
             mIsAnimating = false;
             mIsVisible = false;
             return this;
         }
 
         TestWindowContainer build() {
-            return new TestWindowContainer(mLayer, mCanDetach, mIsAnimating, mIsVisible);
+            return new TestWindowContainer(mLayer, mIsAnimating, mIsVisible);
         }
     }
 }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 411d881..deed6d4 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -182,6 +182,13 @@
     public static final String KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL = "support_swap_after_merge_bool";
 
     /**
+     * Since the default voicemail number is empty, if a SIM card does not have a voicemail number
+     * available the user cannot use voicemail. This flag allows the user to edit the voicemail
+     * number in such cases, and is false by default.
+     */
+    public static final String KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL= "editable_voicemail_number_bool";
+
+    /**
      * Determine whether the voicemail notification is persistent in the notification bar. If true,
      * the voicemail notifications cannot be dismissed from the notification bar.
      */
@@ -312,13 +319,23 @@
             "carrier_wfc_supports_wifi_only_bool";
 
     /**
-     * Default WFC_IMS_mode 0: WIFI_ONLY
-     *                      1: CELLULAR_PREFERRED
-     *                      2: WIFI_PREFERRED
+     * Default WFC_IMS_MODE for home network   0: WIFI_ONLY
+     *                                         1: CELLULAR_PREFERRED
+     *                                         2: WIFI_PREFERRED
      * @hide
      */
     public static final String KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT =
             "carrier_default_wfc_ims_mode_int";
+
+    /**
+     * Default WFC_IMS_MODE for roaming
+     * See {@link KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT} for valid values.
+     *
+     * @hide
+     */
+    public static final String KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT =
+            "carrier_default_wfc_ims_roaming_mode_int";
+
     /**
      * Default WFC_IMS_enabled: true VoWiFi by default is on
      *                          false VoWiFi by default is off
@@ -1011,6 +1028,18 @@
      */
     public static final String KEY_RCS_CONFIG_SERVER_URL_STRING = "rcs_config_server_url_string";
 
+    /**
+     * Determine whether user can change Wi-Fi Calling preference in roaming.
+     * {@code false} - roaming preference {@link KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT} is
+     *                 the same as home preference {@link KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT}
+     *                 and cannot be changed.
+     * {@code true}  - roaming preference can be changed by user independently.
+     *
+     * @hide
+     */
+    public static final String KEY_EDITABLE_WFC_ROAMING_MODE_BOOL =
+            "editable_wfc_roaming_mode_bool";
+
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
 
@@ -1034,6 +1063,7 @@
         sDefaults.putBoolean(KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_PROMOTE_WFC_ON_CALL_FAIL_BOOL, false);
         sDefaults.putInt(KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT, 2);
+        sDefaults.putInt(KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT, 2);
         sDefaults.putBoolean(KEY_CARRIER_FORCE_DISABLE_ETWS_CMAS_TEST_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, true);
@@ -1061,6 +1091,7 @@
         sDefaults.putBoolean(KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL, false);
         sDefaults.putBoolean(KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL, true);
         sDefaults.putBoolean(KEY_USE_HFA_FOR_PROVISIONING_BOOL, false);
+        sDefaults.putBoolean(KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL, false);
         sDefaults.putBoolean(KEY_USE_OTASP_FOR_PROVISIONING_BOOL, false);
         sDefaults.putBoolean(KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL, false);
         sDefaults.putBoolean(KEY_VOICE_PRIVACY_DISABLE_UI_BOOL, false);
@@ -1189,6 +1220,7 @@
         sDefaults.putBoolean(KEY_ENHANCED_4G_LTE_TITLE_VARIANT_BOOL, false);
         sDefaults.putBoolean(KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL, false);
         sDefaults.putStringArray(FILTERED_CNAP_NAMES_STRING_ARRAY, null);
+        sDefaults.putBoolean(KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false);
     }
 
     /**
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index f5e422d..0334254 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -226,6 +226,13 @@
      */
     public static final int DATA_LIMIT_REACHED = 55;
 
+    /**
+     * The emergency call was terminated because it was dialed on the wrong SIM slot.
+     * The call needs to be redialed the other slot.
+     * {@hide}
+     */
+    public static final int DIALED_ON_WRONG_SLOT = 56;
+
     //*********************************************************************************************
     // When adding a disconnect type:
     // 1) Please assign the new type the next id value below.
@@ -234,14 +241,14 @@
     // 4) Update toString() with the newly added disconnect type.
     // 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause.
     //
-    // NextId: 56
+    // NextId: 57
     //*********************************************************************************************
 
     /** Smallest valid value for call disconnect codes. */
     public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
 
     /** Largest valid value for call disconnect codes. */
-    public static final int MAXIMUM_VALID_VALUE = DATA_LIMIT_REACHED;
+    public static final int MAXIMUM_VALID_VALUE = DIALED_ON_WRONG_SLOT;
 
     /** Private constructor to avoid class instantiation. */
     private DisconnectCause() {
@@ -361,6 +368,8 @@
             return "DATA_DISABLED";
         case DATA_LIMIT_REACHED:
             return "DATA_LIMIT_REACHED";
+        case DIALED_ON_WRONG_SLOT:
+            return "DIALED_ON_WRONG_SLOT";
         default:
             return "INVALID: " + cause;
         }
diff --git a/telephony/java/android/telephony/RadioAccessFamily.java b/telephony/java/android/telephony/RadioAccessFamily.java
index b530a64..d657bae 100644
--- a/telephony/java/android/telephony/RadioAccessFamily.java
+++ b/telephony/java/android/telephony/RadioAccessFamily.java
@@ -29,32 +29,38 @@
 public class RadioAccessFamily implements Parcelable {
 
     // Radio Access Family
+    // 2G
     public static final int RAF_UNKNOWN = (1 <<  ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN);
+    public static final int RAF_GSM = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_GSM);
     public static final int RAF_GPRS = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_GPRS);
     public static final int RAF_EDGE = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EDGE);
-    public static final int RAF_UMTS = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_UMTS);
     public static final int RAF_IS95A = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_IS95A);
     public static final int RAF_IS95B = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_IS95B);
     public static final int RAF_1xRTT = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT);
+    // 3G
     public static final int RAF_EVDO_0 = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0);
     public static final int RAF_EVDO_A = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A);
-    public static final int RAF_HSDPA = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA);
-    public static final int RAF_HSUPA = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA);
-    public static final int RAF_HSPA = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSPA);
     public static final int RAF_EVDO_B = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B);
     public static final int RAF_EHRPD = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD);
-    public static final int RAF_LTE = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_LTE);
+    public static final int RAF_HSUPA = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA);
+    public static final int RAF_HSDPA = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA);
+    public static final int RAF_HSPA = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSPA);
     public static final int RAF_HSPAP = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP);
-    public static final int RAF_GSM = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_GSM);
+    public static final int RAF_UMTS = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_UMTS);
     public static final int RAF_TD_SCDMA = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA);
+    // 4G
+    public static final int RAF_LTE = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_LTE);
     public static final int RAF_LTE_CA = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA);
 
     // Grouping of RAFs
+    // 2G
     private static final int GSM = RAF_GSM | RAF_GPRS | RAF_EDGE;
-    private static final int HS = RAF_HSUPA | RAF_HSDPA | RAF_HSPA | RAF_HSPAP;
     private static final int CDMA = RAF_IS95A | RAF_IS95B | RAF_1xRTT;
+    // 3G
     private static final int EVDO = RAF_EVDO_0 | RAF_EVDO_A | RAF_EVDO_B | RAF_EHRPD;
+    private static final int HS = RAF_HSUPA | RAF_HSDPA | RAF_HSPA | RAF_HSPAP;
     private static final int WCDMA = HS | RAF_UMTS;
+    // 4G
     private static final int LTE = RAF_LTE | RAF_LTE_CA;
 
     /* Phone ID of phone */
@@ -239,6 +245,24 @@
         return raf;
     }
 
+    /**
+     * Returns the highest capability of the RadioAccessFamily (4G > 3G > 2G).
+     * @param raf The RadioAccessFamily that we wish to filter
+     * @return The highest radio capability
+     */
+    public static int getHighestRafCapability(int raf) {
+        if ((LTE & raf) > 0) {
+            return TelephonyManager.NETWORK_CLASS_4_G;
+        }
+        if ((EVDO|HS|WCDMA & raf) > 0) {
+            return TelephonyManager.NETWORK_CLASS_3_G;
+        }
+        if((GSM|CDMA & raf) > 0) {
+            return TelephonyManager.NETWORK_CLASS_2_G;
+        }
+        return TelephonyManager.NETWORK_CLASS_UNKNOWN;
+    }
+
     public static int getNetworkTypeFromRaf(int raf) {
         int type;
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 71ae187..5b63199 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1663,6 +1663,12 @@
         }
     }
 
+    /**
+     * Network Class Definitions.
+     * Do not change this order, it is used for sorting during emergency calling in
+     * {@link TelephonyConnectionService#getFirstPhoneForEmergencyCall()}. Any newer technologies
+     * should be added after the current definitions.
+     */
     /** Unknown network class. {@hide} */
     public static final int NETWORK_CLASS_UNKNOWN = 0;
     /** Class of broadly defined "2G" networks. {@hide} */
diff --git a/tests/VoiceInteraction/AndroidManifest.xml b/tests/VoiceInteraction/AndroidManifest.xml
index cbc6c76..5fdf0dd 100644
--- a/tests/VoiceInteraction/AndroidManifest.xml
+++ b/tests/VoiceInteraction/AndroidManifest.xml
@@ -1,6 +1,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.test.voiceinteraction">
 
+    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="25" />
+
     <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
     <uses-permission android:name="android.permission.READ_LOGS" />
 
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 1e7875d..75a3160 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -23,12 +23,8 @@
 // STATUST: mingw does seem to redefine UNKNOWN_ERROR from our enum value, so a cast is necessary.
 
 #if !defined(_WIN32)
-#  define ZD "%zd"
-#  define ZD_TYPE ssize_t
 #  define STATUST(x) x
 #else
-#  define ZD "%ld"
-#  define ZD_TYPE long
 #  define STATUST(x) (status_t)x
 #endif
 
diff --git a/tools/aapt/StringPool.cpp b/tools/aapt/StringPool.cpp
index 37a4933..866291a 100644
--- a/tools/aapt/StringPool.cpp
+++ b/tools/aapt/StringPool.cpp
@@ -14,12 +14,8 @@
 
 // SSIZE: mingw does not have signed size_t == ssize_t.
 #if !defined(_WIN32)
-#  define ZD "%zd"
-#  define ZD_TYPE ssize_t
 #  define SSIZE(x) x
 #else
-#  define ZD "%ld"
-#  define ZD_TYPE long
 #  define SSIZE(x) (signed size_t)x
 #endif
 
diff --git a/tools/aapt/StringPool.h b/tools/aapt/StringPool.h
index 625b0bf..253bcca 100644
--- a/tools/aapt/StringPool.h
+++ b/tools/aapt/StringPool.h
@@ -12,7 +12,6 @@
 
 #include <androidfw/ResourceTypes.h>
 #include <utils/String16.h>
-#include <utils/TypeHelpers.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -179,13 +178,5 @@
     Vector<size_t>                          mOriginalPosToNewPos;
 };
 
-// The entry types are trivially movable because all fields they contain, including
-// the vectors and strings, are trivially movable.
-namespace android {
-    ANDROID_TRIVIAL_MOVE_TRAIT(StringPool::entry);
-    ANDROID_TRIVIAL_MOVE_TRAIT(StringPool::entry_style_span);
-    ANDROID_TRIVIAL_MOVE_TRAIT(StringPool::entry_style);
-};
-
 #endif
 
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index 9ec706f..60114fb 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -77,6 +77,8 @@
 
 sources += Format.proto
 
+sourcesJni :=
+
 testSources := \
 	compile/IdAssigner_test.cpp \
 	compile/InlineXmlFormatParser_test.cpp \
@@ -176,6 +178,25 @@
 LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows)
 include $(BUILD_HOST_STATIC_LIBRARY)
 
+
+# ==========================================================
+# Build the host shared library: libaapt2_jni
+# ==========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := libaapt2_jni
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_MODULE_HOST_OS := darwin linux windows
+LOCAL_CFLAGS := $(cFlags)
+LOCAL_CFLAGS_darwin := $(cFlags_darwin)
+LOCAL_CFLAGS_windows := $(cFlags_windows)
+LOCAL_CPPFLAGS := $(cppFlags)
+LOCAL_C_INCLUDES := $(protoIncludes)
+LOCAL_SRC_FILES := $(sourcesJni)
+LOCAL_STATIC_LIBRARIES := libaapt2 $(hostStaticLibs)
+LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows)
+include $(BUILD_HOST_SHARED_LIBRARY)
+
+
 # ==========================================================
 # Build the host tests: libaapt2_tests
 # ==========================================================
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 8d93b7f..a0b2977 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -76,6 +76,7 @@
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
+import android.os.ShellCallback;
 import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
@@ -1180,7 +1181,7 @@
 
                 @Override
                 public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
-                  String[] args, ResultReceiver resultReceiver) {
+                  String[] args, ShellCallback shellCallback, ResultReceiver resultReceiver) {
                 }
             };
         }
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 9548d45..017525b 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -97,10 +97,6 @@
 
     String getCountryCode();
 
-    void setFrequencyBand(int band, boolean persist);
-
-    int getFrequencyBand();
-
     boolean isDualBandSupported();
 
     boolean saveConfiguration();
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index e9f5506c..8d819b9 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1401,40 +1401,6 @@
     }
 
     /**
-     * Set the operational frequency band.
-     * @param band  One of
-     *     {@link #WIFI_FREQUENCY_BAND_AUTO},
-     *     {@link #WIFI_FREQUENCY_BAND_5GHZ},
-     *     {@link #WIFI_FREQUENCY_BAND_2GHZ},
-     * @param persist {@code true} if this needs to be remembered
-     * @hide
-     */
-    public void setFrequencyBand(int band, boolean persist) {
-        try {
-            mService.setFrequencyBand(band, persist);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Get the operational frequency band.
-     * @return One of
-     *     {@link #WIFI_FREQUENCY_BAND_AUTO},
-     *     {@link #WIFI_FREQUENCY_BAND_5GHZ},
-     *     {@link #WIFI_FREQUENCY_BAND_2GHZ} or
-     *     {@code -1} on failure.
-     * @hide
-     */
-    public int getFrequencyBand() {
-        try {
-            return mService.getFrequencyBand();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Check if the chipset supports dual frequency band (2.4 GHz and 5 GHz)
      * @return {@code true} if supported, {@code false} otherwise.
      * @hide
diff --git a/wifi/java/android/net/wifi/nan/ConfigRequest.java b/wifi/java/android/net/wifi/nan/ConfigRequest.java
index 78e4052..bcd7932 100644
--- a/wifi/java/android/net/wifi/nan/ConfigRequest.java
+++ b/wifi/java/android/net/wifi/nan/ConfigRequest.java
@@ -16,87 +16,65 @@
 
 package android.net.wifi.nan;
 
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 /**
  * Defines a request object to configure a Wi-Fi NAN network. Built using
  * {@link ConfigRequest.Builder}. Configuration is requested using
- * {@link WifiNanManager#connect(android.os.Handler, ConfigRequest, WifiNanEventCallback)}.
+ * {@link WifiNanManager#attach(android.os.Handler, WifiNanAttachCallback)}.
  * Note that the actual achieved configuration may be different from the
  * requested configuration - since different applications may request different
  * configurations.
  *
- * @hide PROPOSED_NAN_API
+ * @hide
  */
 public final class ConfigRequest implements Parcelable {
     /**
      * Lower range of possible cluster ID.
-     *
-     * @hide
      */
     public static final int CLUSTER_ID_MIN = 0;
 
     /**
      * Upper range of possible cluster ID.
-     *
-     * @hide
      */
     public static final int CLUSTER_ID_MAX = 0xFFFF;
 
     /**
      * Indicates whether 5G band support is requested.
-     *
-     * @hide
      */
     public final boolean mSupport5gBand;
 
     /**
      * Specifies the desired master preference.
-     *
-     * @hide
      */
     public final int mMasterPreference;
 
     /**
      * Specifies the desired lower range of the cluster ID. Must be lower then
      * {@link ConfigRequest#mClusterHigh}.
-     *
-     * @hide
      */
     public final int mClusterLow;
 
     /**
      * Specifies the desired higher range of the cluster ID. Must be higher then
      * {@link ConfigRequest#mClusterLow}.
-     *
-     * @hide
      */
     public final int mClusterHigh;
 
-    /**
-     * Indicates whether we want to get callbacks when our identity is changed.
-     *
-     * @hide
-     */
-    public final boolean mEnableIdentityChangeCallback;
-
     private ConfigRequest(boolean support5gBand, int masterPreference, int clusterLow,
-            int clusterHigh, boolean enableIdentityChangeCallback) {
+            int clusterHigh) {
         mSupport5gBand = support5gBand;
         mMasterPreference = masterPreference;
         mClusterLow = clusterLow;
         mClusterHigh = clusterHigh;
-        mEnableIdentityChangeCallback = enableIdentityChangeCallback;
     }
 
     @Override
     public String toString() {
         return "ConfigRequest [mSupport5gBand=" + mSupport5gBand + ", mMasterPreference="
                 + mMasterPreference + ", mClusterLow=" + mClusterLow + ", mClusterHigh="
-                + mClusterHigh + ", mEnableIdentityChangeCallback=" + mEnableIdentityChangeCallback
-                + "]";
+                + mClusterHigh + "]";
     }
 
     @Override
@@ -110,7 +88,6 @@
         dest.writeInt(mMasterPreference);
         dest.writeInt(mClusterLow);
         dest.writeInt(mClusterHigh);
-        dest.writeInt(mEnableIdentityChangeCallback ? 1 : 0);
     }
 
     public static final Creator<ConfigRequest> CREATOR = new Creator<ConfigRequest>() {
@@ -125,9 +102,7 @@
             int masterPreference = in.readInt();
             int clusterLow = in.readInt();
             int clusterHigh = in.readInt();
-            boolean enableIdentityChangeCallback = in.readInt() != 0;
-            return new ConfigRequest(support5gBand, masterPreference, clusterLow, clusterHigh,
-                    enableIdentityChangeCallback);
+            return new ConfigRequest(support5gBand, masterPreference, clusterLow, clusterHigh);
         }
     };
 
@@ -144,43 +119,15 @@
         ConfigRequest lhs = (ConfigRequest) o;
 
         return mSupport5gBand == lhs.mSupport5gBand && mMasterPreference == lhs.mMasterPreference
-                && mClusterLow == lhs.mClusterLow && mClusterHigh == lhs.mClusterHigh
-                && mEnableIdentityChangeCallback == lhs.mEnableIdentityChangeCallback;
-    }
-
-    /**
-     * Checks for equality of two configuration - but only considering their
-     * on-the-air NAN configuration impact.
-     *
-     * @param o Object to compare to.
-     * @return true if configuration objects have the same on-the-air
-     *         configuration, false otherwise.
-     *
-     * @hide
-     */
-    public boolean equalsOnTheAir(Object o) {
-        if (this == o) {
-            return true;
-        }
-
-        if (!(o instanceof ConfigRequest)) {
-            return false;
-        }
-
-        ConfigRequest lhs = (ConfigRequest) o;
-
-        return mSupport5gBand == lhs.mSupport5gBand && mMasterPreference == lhs.mMasterPreference
                 && mClusterLow == lhs.mClusterLow && mClusterHigh == lhs.mClusterHigh;
     }
 
     /**
-     * Checks whether the configuration's settings which impact on-air behavior are non-default.
+     * Checks whether the configuration's settings are non-default.
      *
-     * @return true if any of the on-air-impacting settings are non-default.
-     *
-     * @hide
+     * @return true if any of the settings are non-default.
      */
-    public boolean isNonDefaultOnTheAir() {
+    public boolean isNonDefault() {
         return mSupport5gBand || mMasterPreference != 0 || mClusterLow != CLUSTER_ID_MIN
                 || mClusterHigh != CLUSTER_ID_MAX;
     }
@@ -193,7 +140,6 @@
         result = 31 * result + mMasterPreference;
         result = 31 * result + mClusterLow;
         result = 31 * result + mClusterHigh;
-        result = 31 * result + (mEnableIdentityChangeCallback ? 1 : 0);
 
         return result;
     }
@@ -201,8 +147,6 @@
     /**
      * Verifies that the contents of the ConfigRequest are valid. Otherwise
      * throws an IllegalArgumentException.
-     *
-     * @hide
      */
     public void validate() throws IllegalArgumentException {
         if (mMasterPreference < 0) {
@@ -239,7 +183,6 @@
         private int mMasterPreference = 0;
         private int mClusterLow = CLUSTER_ID_MIN;
         private int mClusterHigh = CLUSTER_ID_MAX;
-        private boolean mEnableIdentityChangeCallback = false;
 
         /**
          * Specify whether 5G band support is required in this request. Disabled by default.
@@ -248,8 +191,6 @@
          *
          * @return The builder to facilitate chaining
          *         {@code builder.setXXX(..).setXXX(..)}.
-         *
-         * @hide PROPOSED_NAN_SYSTEM_API
          */
         public Builder setSupport5gBand(boolean support5gBand) {
             mSupport5gBand = support5gBand;
@@ -264,8 +205,6 @@
          *
          * @return The builder to facilitate chaining
          *         {@code builder.setXXX(..).setXXX(..)}.
-         *
-         * @hide PROPOSED_NAN_SYSTEM_API
          */
         public Builder setMasterPreference(int masterPreference) {
             if (masterPreference < 0) {
@@ -293,8 +232,6 @@
          *
          * @return The builder to facilitate chaining
          *         {@code builder.setClusterLow(..).setClusterHigh(..)}.
-         *
-         * @hide PROPOSED_NAN_SYSTEM_API
          */
         public Builder setClusterLow(int clusterLow) {
             if (clusterLow < CLUSTER_ID_MIN) {
@@ -320,8 +257,6 @@
          *
          * @return The builder to facilitate chaining
          *         {@code builder.setClusterLow(..).setClusterHigh(..)}.
-         *
-         * @hide PROPOSED_NAN_SYSTEM_API
          */
         public Builder setClusterHigh(int clusterHigh) {
             if (clusterHigh < CLUSTER_ID_MIN) {
@@ -336,27 +271,6 @@
         }
 
         /**
-         * Indicate whether or not we want to enable the
-         * {@link WifiNanEventCallback#onIdentityChanged(byte[])} callback. A
-         * device identity is its Discovery MAC address which is randomized at regular intervals.
-         * An application may need to know the MAC address, e.g. when using OOB (out-of-band)
-         * discovery together with NAN connections.
-         * <p>
-         *     The callbacks are disabled by default since it may result in additional wake-ups
-         *     of the host -
-         *     increasing power.
-         *
-         * @param enableIdentityChangeCallback Enable the callback informing
-         *            listener when identity is changed.
-         * @return The builder to facilitate chaining
-         *         {@code builder.setXXX(..).setXXX(..)}.
-         */
-        public Builder setEnableIdentityChangeCallback(boolean enableIdentityChangeCallback) {
-            mEnableIdentityChangeCallback = enableIdentityChangeCallback;
-            return this;
-        }
-
-        /**
          * Build {@link ConfigRequest} given the current requests made on the
          * builder.
          */
@@ -366,8 +280,7 @@
                         "Invalid argument combination - must have Cluster Low <= Cluster High");
             }
 
-            return new ConfigRequest(mSupport5gBand, mMasterPreference, mClusterLow, mClusterHigh,
-                    mEnableIdentityChangeCallback);
+            return new ConfigRequest(mSupport5gBand, mMasterPreference, mClusterLow, mClusterHigh);
         }
     }
 }
diff --git a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl b/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
index 4e1f607..56baba9 100644
--- a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
+++ b/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
@@ -39,7 +39,7 @@
 
     // client API
     void connect(in IBinder binder, in String callingPackage, in IWifiNanEventCallback callback,
-            in ConfigRequest configRequest);
+            in ConfigRequest configRequest, boolean notifyOnIdentityChanged);
     void disconnect(int clientId, in IBinder binder);
 
     void publish(int clientId, in PublishConfig publishConfig,
@@ -50,8 +50,8 @@
     // session API
     void updatePublish(int clientId, int discoverySessionId, in PublishConfig publishConfig);
     void updateSubscribe(int clientId, int discoverySessionId, in SubscribeConfig subscribeConfig);
-    void sendMessage(int clientId, int discoverySessionId, int peerId, in byte[] message, int messageId,
-        int retryCount);
+    void sendMessage(int clientId, int discoverySessionId, int peerId, in byte[] message,
+        int messageId, int retryCount);
     void terminateSession(int clientId, int discoverySessionId);
     int startRanging(int clientId, int discoverySessionId, in RttManager.ParcelableRttParams parms);
 }
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.java b/wifi/java/android/net/wifi/nan/PublishConfig.java
index f988c0b..4b67f9a 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.java
+++ b/wifi/java/android/net/wifi/nan/PublishConfig.java
@@ -32,7 +32,8 @@
 /**
  * Defines the configuration of a NAN publish session. Built using
  * {@link PublishConfig.Builder}. A publish session is created using
- * {@link WifiNanManager#publish(PublishConfig, WifiNanDiscoverySessionCallback)} or updated using
+ * {@link WifiNanSession#publish(android.os.Handler, PublishConfig, WifiNanDiscoverySessionCallback)}
+ * or updated using
  * {@link WifiNanPublishDiscoverySession#updatePublish(PublishConfig)}.
  *
  * @hide PROPOSED_NAN_API
@@ -256,25 +257,6 @@
         }
 
         /**
-         * Specify service specific information for the publish session - a simple wrapper
-         * of {@link PublishConfig.Builder#setServiceSpecificInfo(byte[])}
-         * obtaining the data from a String.
-         * <p>
-         *     Optional. Empty by default.
-         *
-         * @param serviceSpecificInfoStr The service specific information string
-         *            to be included (as a byte array) in the publish
-         *            information.
-         *
-         * @return The builder to facilitate chaining
-         *         {@code builder.setXXX(..).setXXX(..)}.
-         */
-        public Builder setServiceSpecificInfo(@NonNull String serviceSpecificInfoStr) {
-            mServiceSpecificInfo = serviceSpecificInfoStr.getBytes();
-            return this;
-        }
-
-        /**
          * The match filter for a publish session. Used to determine whether a service
          * discovery occurred - in addition to relying on the service name.
          * <p>
@@ -320,10 +302,10 @@
          * will be broadcast. When the count is reached an event will be
          * generated for {@link WifiNanDiscoverySessionCallback#onSessionTerminated(int)}
          * with {@link WifiNanDiscoverySessionCallback#TERMINATE_REASON_DONE} [unless
-         * {@link #setEnableTerminateNotification(boolean)} disables the callback].
+         * {@link #setTerminateNotificationEnabled(boolean)} disables the callback].
          * <p>
          *     Optional. 0 by default - indicating the session doesn't terminate on its own.
-         *     Session will be terminated when {@link WifiNanDiscoveryBaseSession#terminate()} is
+         *     Session will be terminated when {@link WifiNanDiscoveryBaseSession#destroy()} is
          *     called.
          *
          * @param publishCount Number of publish packets to broadcast.
@@ -346,10 +328,10 @@
          * an event will be generated for
          * {@link WifiNanDiscoverySessionCallback#onSessionTerminated(int)} with
          * {@link WifiNanDiscoverySessionCallback#TERMINATE_REASON_DONE}  [unless
-         * {@link #setEnableTerminateNotification(boolean)} disables the callback].
+         * {@link #setTerminateNotificationEnabled(boolean)} disables the callback].
          * <p>
          *     Optional. 0 by default - indicating the session doesn't terminate on its own.
-         *     Session will be terminated when {@link WifiNanDiscoveryBaseSession#terminate()} is
+         *     Session will be terminated when {@link WifiNanDiscoveryBaseSession#destroy()} is
          *     called.
          *
          * @param ttlSec Lifetime of a publish session in seconds.
@@ -376,7 +358,7 @@
          * @return The builder to facilitate chaining
          *         {@code builder.setXXX(..).setXXX(..)}.
          */
-        public Builder setEnableTerminateNotification(boolean enable) {
+        public Builder setTerminateNotificationEnabled(boolean enable) {
             mEnableTerminateNotification = enable;
             return this;
         }
diff --git a/wifi/java/android/net/wifi/nan/SubscribeConfig.java b/wifi/java/android/net/wifi/nan/SubscribeConfig.java
index 47f9398..4352fcf 100644
--- a/wifi/java/android/net/wifi/nan/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/nan/SubscribeConfig.java
@@ -32,7 +32,8 @@
 /**
  * Defines the configuration of a NAN subscribe session. Built using
  * {@link SubscribeConfig.Builder}. Subscribe is done using
- * {@link WifiNanManager#subscribe(SubscribeConfig, WifiNanDiscoverySessionCallback)} or
+ * {@link WifiNanSession#subscribe(android.os.Handler, SubscribeConfig, WifiNanDiscoverySessionCallback)}
+ * or
  * {@link WifiNanSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
  *
  * @hide PROPOSED_NAN_API
@@ -288,25 +289,6 @@
         }
 
         /**
-         * Specify service specific information for the subscribe session - a simple wrapper
-         * of {@link SubscribeConfig.Builder#setServiceSpecificInfo(byte[])}
-         * obtaining the data from a String.
-         * <p>
-         *     Optional. Empty by default.
-         *
-         * @param serviceSpecificInfoStr The service specific information string
-         *            to be included (as a byte array) in the subscribe
-         *            information.
-         *
-         * @return The builder to facilitate chaining
-         *         {@code builder.setXXX(..).setXXX(..)}.
-         */
-        public Builder setServiceSpecificInfo(@NonNull String serviceSpecificInfoStr) {
-            mServiceSpecificInfo = serviceSpecificInfoStr.getBytes();
-            return this;
-        }
-
-        /**
          * The match filter for a subscribe session. Used to determine whether a service
          * discovery occurred - in addition to relying on the service name.
          * <p>
@@ -354,7 +336,7 @@
          * with {@link WifiNanDiscoverySessionCallback#TERMINATE_REASON_DONE}.
          * <p>
          *     Optional. 0 by default - indicating the session doesn't terminate on its own.
-         *     Session will be terminated when {@link WifiNanDiscoveryBaseSession#terminate()} is
+         *     Session will be terminated when {@link WifiNanDiscoveryBaseSession#destroy()} is
          *     called.
          *
          * @param subscribeCount Number of subscribe packets to broadcast.
@@ -379,7 +361,7 @@
          * {@link WifiNanDiscoverySessionCallback#TERMINATE_REASON_DONE}.
          * <p>
          *     Optional. 0 by default - indicating the session doesn't terminate on its own.
-         *     Session will be terminated when {@link WifiNanDiscoveryBaseSession#terminate()} is
+         *     Session will be terminated when {@link WifiNanDiscoveryBaseSession#destroy()} is
          *     called.
          *
          * @param ttlSec Lifetime of a subscribe session in seconds.
@@ -399,7 +381,7 @@
          * Sets the match style of the subscription - how are matches from a
          * single match session (corresponding to the same publish action on the
          * peer) reported to the host (using the
-         * {@link WifiNanDiscoverySessionCallback#onMatch(int, byte[], byte[])}
+         * {@link WifiNanDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])}
          * ). The options are: only report the first match and ignore the rest
          * {@link SubscribeConfig#MATCH_STYLE_FIRST_ONLY} or report every single
          * match {@link SubscribeConfig#MATCH_STYLE_ALL} (the default).
@@ -428,7 +410,7 @@
          * @return The builder to facilitate chaining
          *         {@code builder.setXXX(..).setXXX(..)}.
          */
-        public Builder setEnableTerminateNotification(boolean enable) {
+        public Builder setTerminateNotificationEnabled(boolean enable) {
             mEnableTerminateNotification = enable;
             return this;
         }
diff --git a/wifi/java/android/net/wifi/nan/WifiNanAttachCallback.java b/wifi/java/android/net/wifi/nan/WifiNanAttachCallback.java
new file mode 100644
index 0000000..d8c310b
--- /dev/null
+++ b/wifi/java/android/net/wifi/nan/WifiNanAttachCallback.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.nan;
+
+/**
+ * Base class for NAN attach callbacks. Should be extended by applications and set when calling
+ * {@link WifiNanManager#attach(android.os.Handler, WifiNanAttachCallback)}. These are callbacks
+ * applying to the NAN connection as a whole - not to specific publish or subscribe sessions -
+ * for that see {@link WifiNanDiscoverySessionCallback}.
+ *
+ * @hide PROPOSED_NAN_API
+ */
+public class WifiNanAttachCallback {
+    /**
+     * Called when NAN attach operation
+     * {@link WifiNanManager#attach(android.os.Handler, WifiNanAttachCallback)}
+     * is completed and that we can now start discovery sessions or connections.
+     *
+     * @param session The NAN object on which we can execute further NAN operations - e.g.
+     *                discovery, connections.
+     */
+    public void onAttached(WifiNanSession session) {
+        /* empty */
+    }
+
+    /**
+     * Called when NAN attach operation
+     * {@link WifiNanManager#attach(android.os.Handler, WifiNanAttachCallback)} failed.
+     */
+    public void onAttachFailed() {
+        /* empty */
+    }
+}
diff --git a/wifi/java/android/net/wifi/nan/WifiNanDiscoveryBaseSession.java b/wifi/java/android/net/wifi/nan/WifiNanDiscoveryBaseSession.java
index c2f3735..17e974b 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanDiscoveryBaseSession.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanDiscoveryBaseSession.java
@@ -16,7 +16,9 @@
 
 package android.net.wifi.nan;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.net.wifi.RttManager;
 import android.util.Log;
 
@@ -30,12 +32,12 @@
  * {@link WifiNanPublishDiscoverySession} and {@link WifiNanSubscribeDiscoverySession}. This
  * class provides functionality common to both publish and subscribe discovery sessions:
  * <ul>
- *     <li>Sending messages: {@link #sendMessage(int, byte[], int)} or
- *     {@link #sendMessage(int, byte[], int, int)} methods.
+ *     <li>Sending messages: {@link #sendMessage(Object, int, byte[])} or
+ *     {@link #sendMessage(Object, int, byte[], int)} methods.
  *     <li>Creating a network-specifier when requesting a NAN connection:
- *     {@link #createNetworkSpecifier(int, int, byte[])}.
+ *     {@link #createNetworkSpecifier(int, Object, byte[])}.
  * </ul>
- * The {@link #terminate()} method must be called to terminate discovery sessions once they are
+ * The {@link #destroy()} method must be called to destroy discovery sessions once they are
  * no longer needed.
  *
  * @hide PROPOSED_NAN_API
@@ -60,7 +62,7 @@
 
     /**
      * Return the maximum permitted retry count when sending messages using
-     * {@link #sendMessage(int, byte[], int, int)}.
+     * {@link #sendMessage(Object, int, byte[], int)}.
      *
      * @return Maximum retry count when sending messages.
      */
@@ -79,24 +81,24 @@
         mClientId = clientId;
         mSessionId = sessionId;
 
-        mCloseGuard.open("terminate");
+        mCloseGuard.open("destroy");
     }
 
     /**
-     * Terminate the publish or subscribe session - free any resources, and stop
+     * Destroy the publish or subscribe session - free any resources, and stop
      * transmitting packets on-air (for an active session) or listening for
      * matches (for a passive session). The session may not be used for any
-     * additional operations after termination.
+     * additional operations after its destruction.
      * <p>
      *     This operation must be done on a session which is no longer needed. Otherwise system
-     *     resources will continue to be utilized until the application terminates. The only
+     *     resources will continue to be utilized until the application exits. The only
      *     exception is a session for which we received a termination callback,
      *     {@link WifiNanDiscoverySessionCallback#onSessionTerminated(int)}.
      */
-    public void terminate() {
+    public void destroy() {
         WifiNanManager mgr = mMgr.get();
         if (mgr == null) {
-            Log.w(TAG, "terminate: called post GC on WifiNanManager");
+            Log.w(TAG, "destroy: called post GC on WifiNanManager");
             return;
         }
         mgr.terminateSession(mClientId, mSessionId);
@@ -127,7 +129,7 @@
         try {
             if (!mTerminated) {
                 mCloseGuard.warnIfOpen();
-                terminate();
+                destroy();
             }
         } finally {
             super.finalize();
@@ -137,31 +139,33 @@
     /**
      * Sends a message to the specified destination. NAN messages are transmitted in the context
      * of a discovery session - executed subsequent to a publish/subscribe
-     * {@link WifiNanDiscoverySessionCallback#onMatch(int, byte[], byte[])} event.
+     * {@link WifiNanDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} event.
      * <p>
      *     NAN messages are not guaranteed delivery. Callbacks on
      *     {@link WifiNanDiscoverySessionCallback} indicate message was transmitted successfully,
-     *     {@link WifiNanDiscoverySessionCallback#onMessageSendSuccess(int)}, or transmission failed
+     *     {@link WifiNanDiscoverySessionCallback#onMessageSent(int)}, or transmission failed
      *     (possibly after several retries) -
-     *     {@link WifiNanDiscoverySessionCallback#onMessageSendFail(int, int)}.
+     *     {@link WifiNanDiscoverySessionCallback#onMessageSendFailed(int)}.
      * <p>
      *     The peer will get a callback indicating a message was received using
-     *     {@link WifiNanDiscoverySessionCallback#onMessageReceived(int, byte[])}.
+     *     {@link WifiNanDiscoverySessionCallback#onMessageReceived(Object, byte[])}.
      *
-     * @param peerId The peer's ID for the message. Must be a result of an
-     *            {@link WifiNanDiscoverySessionCallback#onMatch(int, byte[], byte[])} or
-     *            {@link WifiNanDiscoverySessionCallback#onMessageReceived(int, byte[])} events.
-     * @param message The message to be transmitted.
+     * @param peerHandle The peer's handle for the message. Must be a result of an
+     *        {@link WifiNanDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])}
+     *        or
+     *        {@link WifiNanDiscoverySessionCallback#onMessageReceived(Object, byte[])} events.
      * @param messageId An arbitrary integer used by the caller to identify the message. The same
      *            integer ID will be returned in the callbacks indicating message send success or
      *            failure. The {@code messageId} is not used internally by the NAN service - it
      *                  can be arbitrary and non-unique.
+     * @param message The message to be transmitted.
      * @param retryCount An integer specifying how many additional service-level (as opposed to PHY
      *            or MAC level) retries should be attempted if there is no ACK from the receiver
      *            (note: no retransmissions are attempted in other failure cases). A value of 0
      *            indicates no retries. Max permitted value is {@link #getMaxSendRetryCount()}.
      */
-    public void sendMessage(int peerId, @Nullable byte[] message, int messageId, int retryCount) {
+    public void sendMessage(@NonNull Object peerHandle, int messageId, @Nullable byte[] message,
+            int retryCount) {
         if (mTerminated) {
             Log.w(TAG, "sendMessage: called on terminated session");
             return;
@@ -172,44 +176,45 @@
                 return;
             }
 
-            mgr.sendMessage(mClientId, mSessionId, peerId, message, messageId, retryCount);
+            mgr.sendMessage(mClientId, mSessionId, peerHandle, message, messageId, retryCount);
         }
     }
 
     /**
      * Sends a message to the specified destination. NAN messages are transmitted in the context
      * of a discovery session - executed subsequent to a publish/subscribe
-     * {@link WifiNanDiscoverySessionCallback#onMatch(int, byte[], byte[])} event.
+     * {@link WifiNanDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} event.
      * <p>
      *     NAN messages are not guaranteed delivery. Callbacks on
      *     {@link WifiNanDiscoverySessionCallback} indicate message was transmitted successfully,
-     *     {@link WifiNanDiscoverySessionCallback#onMessageSendSuccess(int)}, or transmission failed
+     *     {@link WifiNanDiscoverySessionCallback#onMessageSent(int)}, or transmission failed
      *     (possibly after several retries) -
-     *     {@link WifiNanDiscoverySessionCallback#onMessageSendFail(int, int)}.
+     *     {@link WifiNanDiscoverySessionCallback#onMessageSendFailed(int)}.
      * <p>
      *     The peer will get a callback indicating a message was received using
-     *     {@link WifiNanDiscoverySessionCallback#onMessageReceived(int, byte[])}.
-     * Equivalent to {@link #sendMessage(int, byte[], int, int)} with a {@code retryCount} of
+     *     {@link WifiNanDiscoverySessionCallback#onMessageReceived(Object, byte[])}.
+     * Equivalent to {@link #sendMessage(Object, int, byte[], int)} with a {@code retryCount} of
      * 0.
      *
-     * @param peerId The peer's ID for the message. Must be a result of an
-     *            {@link WifiNanDiscoverySessionCallback#onMatch(int, byte[], byte[])} or
-     *            {@link WifiNanDiscoverySessionCallback#onMessageReceived(int, byte[])} events.
-     * @param message The message to be transmitted.
+     * @param peerHandle The peer's handle for the message. Must be a result of an
+     *        {@link WifiNanDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])}
+     *        or
+     *        {@link WifiNanDiscoverySessionCallback#onMessageReceived(Object, byte[])} events.
      * @param messageId An arbitrary integer used by the caller to identify the message. The same
      *            integer ID will be returned in the callbacks indicating message send success or
      *            failure. The {@code messageId} is not used internally by the NAN service - it
      *                  can be arbitrary and non-unique.
+     * @param message The message to be transmitted.
      */
-    public void sendMessage(int peerId, @Nullable byte[] message, int messageId) {
-        sendMessage(peerId, message, messageId, 0);
+    public void sendMessage(@NonNull Object peerHandle, int messageId, @Nullable byte[] message) {
+        sendMessage(peerHandle, messageId, message, 0);
     }
 
     /**
      * Start a ranging operation with the specified peers. The peer IDs are obtained from an
-     * {@link WifiNanDiscoverySessionCallback#onMatch(int, byte[], byte[])} or
-     * {@link WifiNanDiscoverySessionCallback#onMessageReceived(int, byte[])} operation - can only
-     * range devices which are part of an ongoing discovery session.
+     * {@link WifiNanDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} or
+     * {@link WifiNanDiscoverySessionCallback#onMessageReceived(Object, byte[])} operation - can
+     * only range devices which are part of an ongoing discovery session.
      *
      * @param params   RTT parameters - each corresponding to a specific peer ID (the array sizes
      *                 must be identical). The
@@ -249,12 +254,12 @@
      * @param role The role of this device:
      * {@link WifiNanManager#WIFI_NAN_DATA_PATH_ROLE_INITIATOR} or
      * {@link WifiNanManager#WIFI_NAN_DATA_PATH_ROLE_RESPONDER}
-     * @param peerId The peer ID obtained through
-     * {@link WifiNanDiscoverySessionCallback#onMatch(int, byte[], byte[])} or
-     * {@link WifiNanDiscoverySessionCallback#onMessageReceived(int, byte[])}. On a RESPONDER this
-     *              value is used to gate the acceptance of a connection request from only that
-     *              peer. A RESPONDER may specified a 0 - indicating that it will accept
-     *              connection requests from any device.
+     * @param peerHandle The peer's handle obtained through
+     * {@link WifiNanDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} or
+     * {@link WifiNanDiscoverySessionCallback#onMessageReceived(Object, byte[])}. On a RESPONDER
+     *               this value is used to gate the acceptance of a connection request from only
+     *               that peer. A RESPONDER may specified a null - indicating that it will accept
+     *               connection requests from any device.
      * @param token An arbitrary token (message) to be used to match connection initiation request
      *              to a responder setup. A RESPONDER is set up with a {@code token} which must
      *              be matched by the token provided by the INITIATOR. A null token is permitted
@@ -266,8 +271,8 @@
      * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,android.net.ConnectivityManager.NetworkCallback)}
      * [or other varieties of that API].
      */
-    public String createNetworkSpecifier(@WifiNanManager.DataPathRole int role, int peerId,
-            @Nullable byte[] token) {
+    public String createNetworkSpecifier(@WifiNanManager.DataPathRole int role,
+            @Nullable Object peerHandle, @Nullable byte[] token) {
         if (mTerminated) {
             Log.w(TAG, "createNetworkSpecifier: called on terminated session");
             return null;
@@ -278,7 +283,7 @@
                 return null;
             }
 
-            return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerId, token);
+            return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, token);
         }
     }
 }
diff --git a/wifi/java/android/net/wifi/nan/WifiNanDiscoverySessionCallback.java b/wifi/java/android/net/wifi/nan/WifiNanDiscoverySessionCallback.java
index 685e152..271f420 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanDiscoverySessionCallback.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanDiscoverySessionCallback.java
@@ -26,8 +26,9 @@
  * Base class for NAN session events callbacks. Should be extended by
  * applications wanting notifications. The callbacks are set when a
  * publish or subscribe session is created using
- * {@link WifiNanManager#publish(PublishConfig, WifiNanDiscoverySessionCallback)} or
- * {@link WifiNanManager#subscribe(SubscribeConfig, WifiNanDiscoverySessionCallback)} .
+ * {@link WifiNanSession#publish(android.os.Handler, PublishConfig, WifiNanDiscoverySessionCallback)}
+ * or
+ * {@link WifiNanSession#subscribe(android.os.Handler, SubscribeConfig, WifiNanDiscoverySessionCallback)} .
  * <p>
  * A single callback is set at session creation - it cannot be replaced.
  *
@@ -36,53 +37,12 @@
 public class WifiNanDiscoverySessionCallback {
     /** @hide */
     @IntDef({
-            REASON_NO_RESOURCES, REASON_INVALID_ARGS, REASON_NO_MATCH_SESSION,
-            REASON_TX_FAIL, REASON_OTHER })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface SessionReasonCodes {
-    }
-
-    /** @hide */
-    @IntDef({
             TERMINATE_REASON_DONE, TERMINATE_REASON_FAIL })
     @Retention(RetentionPolicy.SOURCE)
     public @interface SessionTerminateCodes {
     }
 
     /**
-     * Indicates no resources to execute the requested operation.
-     * Failure reason flag for {@link WifiNanDiscoverySessionCallback} callbacks.
-     */
-    public static final int REASON_NO_RESOURCES = 0;
-
-    /**
-     * Indicates invalid argument in the requested operation.
-     * Failure reason flag for {@link WifiNanDiscoverySessionCallback} callbacks.
-     */
-    public static final int REASON_INVALID_ARGS = 1;
-
-    /**
-     * Indicates a message is transmitted without a match (a discovery) or received message
-     * from peer occurring first.
-     * Failure reason flag for {@link WifiNanDiscoverySessionCallback} callbacks.
-     */
-    public static final int REASON_NO_MATCH_SESSION = 2;
-
-    /**
-     * Indicates transmission failure: this may be due to local transmission
-     * failure or to no ACK received - remote device didn't receive the
-     * sent message. Failure reason flag for
-     * {@link WifiNanDiscoverySessionCallback#onMessageSendFail(int, int)} callback.
-     */
-    public static final int REASON_TX_FAIL = 3;
-
-    /**
-     * Indicates an unspecified error occurred during the operation.
-     * Failure reason flag for {@link WifiNanDiscoverySessionCallback} callbacks.
-     */
-    public static final int REASON_OTHER = 4;
-
-    /**
      * Indicates that publish or subscribe session is done - all the
      * requested operations (per {@link PublishConfig} or
      * {@link SubscribeConfig}) have been executed. Failure reason flag for
@@ -100,7 +60,8 @@
 
     /**
      * Called when a publish operation is started successfully in response to a
-     * {@link WifiNanManager#publish(PublishConfig, WifiNanDiscoverySessionCallback)} operation.
+     * {@link WifiNanSession#publish(android.os.Handler, PublishConfig, WifiNanDiscoverySessionCallback)}
+     * operation.
      *
      * @param session The {@link WifiNanPublishDiscoverySession} used to control the
      *            discovery session.
@@ -111,7 +72,8 @@
 
     /**
      * Called when a subscribe operation is started successfully in response to a
-     * {@link WifiNanManager#subscribe(SubscribeConfig, WifiNanDiscoverySessionCallback)} operation.
+     * {@link WifiNanSession#subscribe(android.os.Handler, SubscribeConfig, WifiNanDiscoverySessionCallback)}
+     * operation.
      *
      * @param session The {@link WifiNanSubscribeDiscoverySession} used to control the
      *            discovery session.
@@ -121,36 +83,34 @@
     }
 
     /**
-     * Called when a publish or subscribe discovery session configuration is update request
+     * Called when a publish or subscribe discovery session configuration update request
      * succeeds. Called in response to
      * {@link WifiNanPublishDiscoverySession#updatePublish(PublishConfig)} or
      * {@link WifiNanSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
      */
-    public void onSessionConfigSuccess() {
+    public void onSessionConfigUpdated() {
         /* empty */
     }
 
     /**
      * Called when a publish or subscribe discovery session cannot be created:
-     * {@link WifiNanManager#publish(PublishConfig, WifiNanDiscoverySessionCallback)} or
-     * {@link WifiNanManager#subscribe(SubscribeConfig, WifiNanDiscoverySessionCallback)},
+     * {@link WifiNanSession#publish(android.os.Handler, PublishConfig, WifiNanDiscoverySessionCallback)}
+     * or
+     * {@link WifiNanSession#subscribe(android.os.Handler, SubscribeConfig, WifiNanDiscoverySessionCallback)},
      * or when a configuration update fails:
      * {@link WifiNanPublishDiscoverySession#updatePublish(PublishConfig)} or
      * {@link WifiNanSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
      * <p>
      *     For discovery session updates failure leaves the session running with its previous
      *     configuration - the discovery session is not terminated.
-     *
-     * @param reason The failure reason using
-     *            {@code WifiNanDiscoverySessionCallback.REASON_*} codes.
      */
-    public void onSessionConfigFail(@SessionReasonCodes int reason) {
+    public void onSessionConfigFailed() {
         /* empty */
     }
 
     /**
      * Called when a discovery session (publish or subscribe) terminates. Termination may be due
-     * to user-request (either directly through {@link WifiNanDiscoveryBaseSession#terminate()} or
+     * to user-request (either directly through {@link WifiNanDiscoveryBaseSession#destroy()} or
      * application-specified expiration, e.g. {@link PublishConfig.Builder#setPublishCount(int)}
      * or {@link SubscribeConfig.Builder#setTtlSec(int)}) or due to a failure.
      *
@@ -163,62 +123,60 @@
 
     /**
      * Called when a discovery (publish or subscribe) operation results in a
-     * match - when a peer is discovered.
+     * service discovery.
      *
-     * @param peerId The ID of the peer matching our discovery operation.
+     * @param peerHandle An opaque handle to the peer matching our discovery operation.
      * @param serviceSpecificInfo The service specific information (arbitrary
      *            byte array) provided by the peer as part of its discovery
      *            configuration.
      * @param matchFilter The filter (Tx on advertiser and Rx on listener) which
-     *            resulted in this match.
+     *            resulted in this service discovery.
      */
-    public void onMatch(int peerId, byte[] serviceSpecificInfo, byte[] matchFilter) {
+    public void onServiceDiscovered(Object peerHandle, byte[] serviceSpecificInfo,
+            byte[] matchFilter) {
         /* empty */
     }
 
     /**
-     * Called in response to {@link WifiNanDiscoveryBaseSession#sendMessage(int, byte[], int)}
-     * when a message is transmitted successfully - when it was received successfully by the peer
-     * (corresponds to an ACK being received).
+     * Called in response to {@link WifiNanDiscoveryBaseSession#sendMessage(Object, int, byte[])}
+     * when a message is transmitted successfully - i.e. when it was received successfully by the
+     * peer (corresponds to an ACK being received).
      * <p>
      * Note that either this callback or
-     * {@link WifiNanDiscoverySessionCallback#onMessageSendFail(int, int)} will be
+     * {@link WifiNanDiscoverySessionCallback#onMessageSendFailed(int)} will be
      * received - never both.
      *
      * @param messageId The arbitrary message ID specified when sending the message.
      */
-    public void onMessageSendSuccess(@SuppressWarnings("unused") int messageId) {
+    public void onMessageSent(@SuppressWarnings("unused") int messageId) {
         /* empty */
     }
 
     /**
      * Called when message transmission fails - when no ACK is received from the peer.
      * Retries when ACKs are not received are done by hardware, MAC, and in the NAN stack (using
-     * the {@link WifiNanDiscoveryBaseSession#sendMessage(int, byte[], int, int)} method) - this
+     * the {@link WifiNanDiscoveryBaseSession#sendMessage(Object, int, byte[], int)} method) - this
      * event is received after all retries are exhausted.
      * <p>
      * Note that either this callback or
-     * {@link WifiNanDiscoverySessionCallback#onMessageSendSuccess(int)} will be received
+     * {@link WifiNanDiscoverySessionCallback#onMessageSent(int)} will be received
      * - never both.
      *
      * @param messageId The arbitrary message ID specified when sending the message.
-     * @param reason The failure reason using
-     *            {@code WifiNanDiscoverySessionCallback.REASON_*} codes.
      */
-    public void onMessageSendFail(@SuppressWarnings("unused") int messageId,
-            @SessionReasonCodes int reason) {
+    public void onMessageSendFailed(@SuppressWarnings("unused") int messageId) {
         /* empty */
     }
 
     /**
      * Called when a message is received from a discovery session peer - in response to the
-     * peer's {@link WifiNanDiscoveryBaseSession#sendMessage(int, byte[], int)} or
-     * {@link WifiNanDiscoveryBaseSession#sendMessage(int, byte[], int, int)}.
+     * peer's {@link WifiNanDiscoveryBaseSession#sendMessage(Object, int, byte[])} or
+     * {@link WifiNanDiscoveryBaseSession#sendMessage(Object, int, byte[], int)}.
      *
-     * @param peerId The ID of the peer sending the message.
+     * @param peerHandle An opaque handle to the peer matching our discovery operation.
      * @param message A byte array containing the message.
      */
-    public void onMessageReceived(int peerId, byte[] message) {
+    public void onMessageReceived(Object peerHandle, byte[] message) {
         /* empty */
     }
 }
diff --git a/wifi/java/android/net/wifi/nan/WifiNanEventCallback.java b/wifi/java/android/net/wifi/nan/WifiNanEventCallback.java
deleted file mode 100644
index 28c5ca2..0000000
--- a/wifi/java/android/net/wifi/nan/WifiNanEventCallback.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.nan;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Base class for NAN events callbacks. Should be extended by applications and set when calling
- * {@link WifiNanManager#connect(android.os.Handler, WifiNanEventCallback)}. These are callbacks
- * applying to the NAN connection as a whole - not to specific publish or subscribe sessions -
- * for that see {@link WifiNanDiscoverySessionCallback}.
- *
- * @hide PROPOSED_NAN_API
- */
-public class WifiNanEventCallback {
-    /** @hide */
-    @IntDef({
-            REASON_INVALID_ARGS, REASON_ALREADY_CONNECTED_INCOMPAT_CONFIG, REASON_OTHER
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface EventReasonCodes {
-    }
-
-    /**
-     * Indicates invalid argument in the requested operation. Failure reason flag for
-     * {@link WifiNanEventCallback#onConnectFail(int)}.
-     */
-    public static final int REASON_INVALID_ARGS = 1000;
-
-    /**
-     * Indicates that a {@link ConfigRequest} passed in
-     * {@link WifiNanManager#connect(android.os.Handler, ConfigRequest, WifiNanEventCallback)}
-     * couldn't be applied since other connections already exist with an incompatible
-     * configurations. Failure reason flag for {@link WifiNanEventCallback#onConnectFail(int)}.
-     */
-    public static final int REASON_ALREADY_CONNECTED_INCOMPAT_CONFIG = 1001;
-
-    /**
-     * Indicates an unspecified error occurred during the operation. Failure reason flag for
-     * {@link WifiNanEventCallback#onConnectFail(int)}.
-     */
-    public static final int REASON_OTHER = 1002;
-
-    /**
-     * Called when NAN connect operation
-     * {@link WifiNanManager#connect(android.os.Handler, WifiNanEventCallback)}
-     * is completed and that we can now start discovery sessions or connections.
-     *
-     * @param session The NAN connection on which we can execute further NAN operations - e.g.
-     *                discovery, connections.
-     */
-    public void onConnectSuccess(WifiNanSession session) {
-        /* empty */
-    }
-
-    /**
-     * Called when NAN connect operation
-     * {@link WifiNanManager#connect(android.os.Handler, WifiNanEventCallback)} failed.
-     *
-     * @param reason Failure reason code, see
-     *            {@code WifiNanEventCallback.REASON_*}.
-     */
-    public void onConnectFail(@EventReasonCodes int reason) {
-        /* empty */
-    }
-
-    /**
-     * Called when NAN identity (the MAC address representing our NAN discovery interface) has
-     * changed. Change may be due to device joining a cluster, starting a cluster, or discovery
-     * interface change (addresses are randomized at regular intervals). The implication is that
-     * peers you've been communicating with may no longer recognize you and you need to
-     * re-establish your identity - e.g. by starting a discovery session. This actual MAC address
-     * of the interface may also be useful if the application uses alternative (non-NAN)
-     * discovery but needs to set up a NAN connection. The provided NAN discovery interface MAC
-     * address can then be used in
-     * {@link WifiNanManager#createNetworkSpecifier(int, byte[], byte[])}.
-     * <p>
-     *     This callback is only called if the NAN connection enables it using
-     *     {@link ConfigRequest.Builder#setEnableIdentityChangeCallback(boolean)} in
-     *     {@link WifiNanManager#connect(android.os.Handler, ConfigRequest, WifiNanEventCallback)}
-     *     . It is disabled by default since it may result in additional wake-ups of the host -
-     *     increasing power.
-     *
-     * @param mac The MAC address of the NAN discovery interface. The application must have the
-     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} to get the actual MAC address,
-     *            otherwise all 0's will be provided.
-     */
-    public void onIdentityChanged(byte[] mac) {
-        /* empty */
-    }
-}
diff --git a/wifi/java/android/net/wifi/nan/WifiNanIdentityChangedListener.java b/wifi/java/android/net/wifi/nan/WifiNanIdentityChangedListener.java
new file mode 100644
index 0000000..7cb928f
--- /dev/null
+++ b/wifi/java/android/net/wifi/nan/WifiNanIdentityChangedListener.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.nan;
+
+/**
+ * Base class for a listener which is called with the MAC address of the NAN interface whenever
+ * it is changed. Change may be due to device joining a cluster, starting a cluster, or discovery
+ * interface change (addresses are randomized at regular intervals). The implication is that
+ * peers you've been communicating with may no longer recognize you and you need to re-establish
+ * your identity - e.g. by starting a discovery session. This actual MAC address of the
+ * interface may also be useful if the application uses alternative (non-NAN) discovery but needs
+ * to set up a NAN connection. The provided NAN discovery interface MAC address can then be used
+ * in {@link WifiNanSession#createNetworkSpecifier(int, byte[], byte[])}.
+ *
+ * @hide PROPOSED_NAN_API
+ */
+public class WifiNanIdentityChangedListener {
+    /**
+     * @param mac The MAC address of the NAN discovery interface. The application must have the
+     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} to get the actual MAC address,
+     *            otherwise all 0's will be provided.
+     */
+    public void onIdentityChanged(byte[] mac) {
+        /* empty */
+    }
+}
diff --git a/wifi/java/android/net/wifi/nan/WifiNanManager.java b/wifi/java/android/net/wifi/nan/WifiNanManager.java
index b300d81..705ba4a 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanManager.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanManager.java
@@ -56,38 +56,38 @@
  * The class provides access to:
  * <ul>
  * <li>Initialize a NAN cluster (peer-to-peer synchronization). Refer to
- * {@link #connect(Handler, WifiNanEventCallback)}. <li>Create discovery sessions (publish or
- * subscribe sessions). Refer to
- * {@link WifiNanSession#publish(PublishConfig, WifiNanDiscoverySessionCallback)} and
- * {@link WifiNanSession#subscribe(SubscribeConfig, WifiNanDiscoverySessionCallback)}. <li>Create
- * a NAN network specifier to be used with
+ * {@link #attach(Handler, WifiNanAttachCallback)}.
+ * <li>Create discovery sessions (publish or subscribe sessions). Refer to
+ * {@link WifiNanSession#publish(Handler, PublishConfig, WifiNanDiscoverySessionCallback)} and
+ * {@link WifiNanSession#subscribe(Handler, SubscribeConfig, WifiNanDiscoverySessionCallback)}.
+ * <li>Create a NAN network specifier to be used with
  * {@link ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback)}
  * to set-up a NAN connection with a peer. Refer to
- * {@link WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, int, byte[])} and
+ * {@link WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])} and
  * {@link WifiNanSession#createNetworkSpecifier(int, byte[], byte[])}.
  * </ul>
  * <p>
  *     NAN may not be usable when Wi-Fi is disabled (and other conditions). To validate that
- *     the functionality is available use the {@link #isUsageEnabled()} function. To track
+ *     the functionality is available use the {@link #isAvailable()} function. To track
  *     changes in NAN usability register for the {@link #ACTION_WIFI_NAN_STATE_CHANGED} broadcast.
  *     Note that this broadcast is not sticky - you should register for it and then check the
  *     above API to avoid a race condition.
  * <p>
- *     An application must use {@link #connect(Handler, WifiNanEventCallback)} to initialize a NAN
+ *     An application must use {@link #attach(Handler, WifiNanAttachCallback)} to initialize a NAN
  *     cluster - before making any other NAN operation. NAN cluster membership is a device-wide
  *     operation - the API guarantees that the device is in a cluster or joins a NAN cluster (or
- *     starts one if none can be found). Information about connection success (or failure) are
- *     returned in callbacks of {@link WifiNanEventCallback}. Proceed with NAN discovery or
- *     connection setup only after receiving confirmation that NAN connection succeeded -
- *     {@link WifiNanEventCallback#onConnectSuccess(WifiNanSession)}. When an application is
- *     finished using NAN it <b>must</b> use the {@link WifiNanSession#disconnect()} API
- *     to indicate to the NAN service that the device may disconnect from the NAN cluster. The
- *     device will actually disconnect from the NAN cluster once the last application disconnects.
+ *     starts one if none can be found). Information about attach success (or failure) are
+ *     returned in callbacks of {@link WifiNanAttachCallback}. Proceed with NAN discovery or
+ *     connection setup only after receiving confirmation that NAN attach succeeded -
+ *     {@link WifiNanAttachCallback#onAttached(WifiNanSession)}. When an application is
+ *     finished using NAN it <b>must</b> use the {@link WifiNanSession#destroy()} API
+ *     to indicate to the NAN service that the device may detach from the NAN cluster. The
+ *     device will actually disable NAN once the last application detaches.
  * <p>
- *     Once a NAN connection is confirmed use the
- *     {@link WifiNanSession#publish(PublishConfig, WifiNanDiscoverySessionCallback)} or
- *     {@link WifiNanSession#subscribe(SubscribeConfig, WifiNanDiscoverySessionCallback)} to
- *     create publish or subscribe NAN discovery sessions. Events are called on the provided
+ *     Once a NAN attach is confirmed use the
+ *     {@link WifiNanSession#publish(Handler, PublishConfig, WifiNanDiscoverySessionCallback)} or
+ *     {@link WifiNanSession#subscribe(Handler, SubscribeConfig, WifiNanDiscoverySessionCallback)}
+ *     to create publish or subscribe NAN discovery sessions. Events are called on the provided
  *     callback object {@link WifiNanDiscoverySessionCallback}. Specifically, the
  *     {@link WifiNanDiscoverySessionCallback#onPublishStarted(WifiNanPublishDiscoverySession)}
  *     and
@@ -97,9 +97,9 @@
  *     the session {@link WifiNanPublishDiscoverySession#updatePublish(PublishConfig)} and
  *     {@link WifiNanSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. Sessions can also
  *     be used to send messages using the
- *     {@link WifiNanDiscoveryBaseSession#sendMessage(int, byte[], int)} APIs. When an application
- *     is finished with a discovery session it <b>must</b> terminate it using the
- *     {@link WifiNanDiscoveryBaseSession#terminate()} API.
+ *     {@link WifiNanDiscoveryBaseSession#sendMessage(Object, int, byte[])} APIs. When an
+ *     application is finished with a discovery session it <b>must</b> terminate it using the
+ *     {@link WifiNanDiscoveryBaseSession#destroy()} API.
  * <p>
  *    Creating connections between NAN devices is managed by the standard
  *    {@link ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback)}.
@@ -109,7 +109,7 @@
  *        {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_NAN}.
  *        <li>{@link NetworkRequest.Builder#setNetworkSpecifier(String)} using
  *        {@link WifiNanSession#createNetworkSpecifier(int, byte[], byte[])} or
- *        {@link WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, int, byte[])}.
+ *        {@link WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])}.
  *    </ul>
  *
  * @hide PROPOSED_NAN_API
@@ -197,43 +197,15 @@
     public static final String NETWORK_SPECIFIER_KEY_TOKEN = "token";
 
     /**
-     * Broadcast intent action to indicate whether Wi-Fi NAN is enabled or
-     * disabled. An extra {@link #EXTRA_WIFI_STATE} provides the state
-     * information as int using {@link #WIFI_NAN_STATE_DISABLED} and
-     * {@link #WIFI_NAN_STATE_ENABLED} constants. This broadcast is <b>not</b> sticky,
-     * use the {@link #isUsageEnabled()} API after registering the broadcast to check the current
-     * state of Wi-Fi NAN.
-     *
-     * @see #EXTRA_WIFI_STATE
+     * Broadcast intent action to indicate that the state of Wi-Fi NAN availability has changed.
+     * Use the {@link #isAvailable()} to query the current status.
+     * This broadcast is <b>not</b> sticky, use the {@link #isAvailable()} API after registering
+     * the broadcast to check the current state of Wi-Fi NAN.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_WIFI_NAN_STATE_CHANGED =
             "android.net.wifi.nan.action.WIFI_NAN_STATE_CHANGED";
 
-    /**
-     * The lookup key for an int value indicating whether Wi-Fi NAN is enabled or
-     * disabled. Retrieve it with
-     * {@link android.content.Intent#getIntExtra(String,int)}.
-     *
-     * @see #WIFI_NAN_STATE_DISABLED
-     * @see #WIFI_NAN_STATE_ENABLED
-     */
-    public static final String EXTRA_WIFI_STATE = "android.net.wifi.nan.extra.WIFI_STATE";
-
-    /**
-     * Wi-Fi NAN is disabled.
-     *
-     * @see #ACTION_WIFI_NAN_STATE_CHANGED
-     */
-    public static final int WIFI_NAN_STATE_DISABLED = 1;
-
-    /**
-     * Wi-Fi NAN is enabled.
-     *
-     * @see #ACTION_WIFI_NAN_STATE_CHANGED
-     */
-    public static final int WIFI_NAN_STATE_ENABLED = 2;
-
     /** @hide */
     @IntDef({
             WIFI_NAN_DATA_PATH_ROLE_INITIATOR, WIFI_NAN_DATA_PATH_ROLE_RESPONDER})
@@ -245,7 +217,7 @@
      * Connection creation role is that of INITIATOR. Used to create a network specifier string
      * when requesting a NAN network.
      *
-     * @see WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, int, byte[])
+     * @see WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])
      * @see WifiNanSession#createNetworkSpecifier(int, byte[], byte[])
      */
     public static final int WIFI_NAN_DATA_PATH_ROLE_INITIATOR = 0;
@@ -254,7 +226,7 @@
      * Connection creation role is that of RESPONDER. Used to create a network specifier string
      * when requesting a NAN network.
      *
-     * @see WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, int, byte[])
+     * @see WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])
      * @see WifiNanSession#createNetworkSpecifier(int, byte[], byte[])
      */
     public static final int WIFI_NAN_DATA_PATH_ROLE_RESPONDER = 1;
@@ -274,9 +246,9 @@
     }
 
     /**
-     * Enable the usage of the NAN API. Doesn't actually turn on NAN cluster formation - that only
-     * happens when a connection is made. {@link #ACTION_WIFI_NAN_STATE_CHANGED} broadcast will be
-     * triggered.
+     * Enable the usage of the NAN API. Doesn't actually turn on NAN cluster formation - that
+     * only happens when an attach is attempted. {@link #ACTION_WIFI_NAN_STATE_CHANGED} broadcast
+     * will be triggered.
      *
      * @hide
      */
@@ -289,7 +261,7 @@
     }
 
     /**
-     * Disable the usage of the NAN API. All attempts to connect() will be rejected. All open
+     * Disable the usage of the NAN API. All attempts to attach() will be rejected. All open
      * connections and sessions will be terminated. {@link #ACTION_WIFI_NAN_STATE_CHANGED} broadcast
      * will be triggered.
      *
@@ -304,13 +276,13 @@
     }
 
     /**
-     * Returns the current status of NAN API: whether or not usage is enabled. To track changes
+     * Returns the current status of NAN API: whether or not NAN is available. To track changes
      * in the state of NAN API register for the {@link #ACTION_WIFI_NAN_STATE_CHANGED} broadcast.
      *
-     * @return A boolean indicating whether the app can use the NAN API (true)
-     *         or not (false).
+     * @return A boolean indicating whether the app can use the NAN API at this time (true) or
+     * not (false).
      */
-    public boolean isUsageEnabled() {
+    public boolean isAvailable() {
         try {
             return mService.isUsageEnabled();
         } catch (RemoteException e) {
@@ -319,50 +291,68 @@
     }
 
     /**
-     * Connect to the Wi-Fi NAN service - enabling the application to create discovery session or
-     * create connection to peers. The device will connect to an existing cluster if it can find
+     * Attach to the Wi-Fi NAN service - enabling the application to create discovery sessions or
+     * create connections to peers. The device will attach to an existing cluster if it can find
      * one or create a new cluster (if it is the first to enable NAN in its vicinity). Results
-     * (e.g. successful connection to a cluster) are provided to the {@code callback} object.
-     * An application <b>must</b> call {@link WifiNanSession#disconnect()} when done with the
-     * Wi-Fi NAN connection.
+     * (e.g. successful attach to a cluster) are provided to the {@code attachCallback} object.
+     * An application <b>must</b> call {@link WifiNanSession#destroy()} when done with the
+     * Wi-Fi NAN object.
      * <p>
-     * Note: a NAN cluster is a shared resource - if the device is already connected to a cluster
-     * than this function will simply indicate success immediately.
+     * Note: a NAN cluster is a shared resource - if the device is already attached to a cluster
+     * then this function will simply indicate success immediately using the same {@code
+     * attachCallback}.
      *
-     * @param handler The Handler on whose thread to execute all callbacks related to the
-     *            connection - including all sessions opened as part of this
-     *            connection. If a null is provided then the application's main thread will be used.
-     * @param callback A callback extended from {@link WifiNanEventCallback}.
+     * @param handler The Handler on whose thread to execute the callbacks of the {@code
+     * attachCallback} object. If a null is provided then the application's main thread will be
+     *                used.
+     * @param attachCallback A callback for attach events, extended from
+     * {@link WifiNanAttachCallback}.
      */
-    public void connect(@Nullable Handler handler, @NonNull WifiNanEventCallback callback) {
-        connect(handler, null, callback);
+    public void attach(@Nullable Handler handler, @NonNull WifiNanAttachCallback attachCallback) {
+        attach(handler, null, attachCallback, null);
     }
 
     /**
-     * Connect to the Wi-Fi NAN service - enabling the application to create discovery session or
-     * create connection to peers. The device will connect to an existing cluster if it can find
+     * Attach to the Wi-Fi NAN service - enabling the application to create discovery sessions or
+     * create connections to peers. The device will attach to an existing cluster if it can find
      * one or create a new cluster (if it is the first to enable NAN in its vicinity). Results
-     * (e.g. successful connection to a cluster) are provided to the {@code callback} object.
-     * An application <b>must</b> call {@link WifiNanSession#disconnect()} when done with the
-     * Wi-Fi NAN connection. Allows requesting a specific configuration using
-     * {@link ConfigRequest}. If not necessary (default configuration should usually work) use
-     * the {@link #connect(Handler, WifiNanEventCallback)} method instead.
+     * (e.g. successful attach to a cluster) are provided to the {@code attachCallback} object.
+     * An application <b>must</b> call {@link WifiNanSession#destroy()} when done with the
+     * Wi-Fi NAN object.
      * <p>
-     * Note: a NAN cluster is a shared resource - if the device is already connected to a cluster
-     * than this function will simply indicate success immediately.
+     * Note: a NAN cluster is a shared resource - if the device is already attached to a cluster
+     * then this function will simply indicate success immediately using the same {@code
+     * attachCallback}.
+     * <p>
+     * This version of the API attaches a listener to receive the MAC address of the NAN interface
+     * on startup and whenever it is updated (it is randomized at regular intervals for privacy).
+     * The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
+     * permission to execute this attach request. Otherwise, use the
+     * {@link #attach(Handler, WifiNanAttachCallback)} version. Note that aside from permission
+     * requirements this listener will wake up the host at regular intervals causing higher power
+     * consumption, do not use it unless the information is necessary (e.g. for OOB discovery).
      *
-     * @param handler The Handler on whose thread to execute all callbacks related to the
-     *            connection - including all sessions opened as part of this
-     *            connection. If a null is provided then the application's main thread will be used.
-     * @param configRequest The requested NAN configuration.
-     * @param callback A callback extended from {@link WifiNanEventCallback}.
+     * @param handler The Handler on whose thread to execute the callbacks of the {@code
+     * attachCallback} and {@code identityChangedListener} objects. If a null is provided then the
+     *                application's main thread will be used.
+     * @param attachCallback A callback for attach events, extended from
+     * {@link WifiNanAttachCallback}.
+     * @param identityChangedListener A listener for changed identity, extended from
+     * {@link WifiNanIdentityChangedListener}.
      */
-    public void connect(@Nullable Handler handler, @Nullable ConfigRequest configRequest,
-            @NonNull WifiNanEventCallback callback) {
+    public void attach(@Nullable Handler handler, @NonNull WifiNanAttachCallback attachCallback,
+            @NonNull WifiNanIdentityChangedListener identityChangedListener) {
+        attach(handler, null, attachCallback, identityChangedListener);
+    }
+
+    /** @hide */
+    public void attach(Handler handler, ConfigRequest configRequest,
+            WifiNanAttachCallback attachCallback,
+            WifiNanIdentityChangedListener identityChangedListener) {
         if (VDBG) {
-            Log.v(TAG,
-                    "connect(): handler=" + handler + ", callback=" + callback + ", configRequest="
-                            + configRequest);
+            Log.v(TAG, "attach(): handler=" + handler + ", callback=" + attachCallback
+                    + ", configRequest=" + configRequest + ", identityChangedListener="
+                    + identityChangedListener);
         }
 
         synchronized (mLock) {
@@ -371,8 +361,9 @@
             try {
                 Binder binder = new Binder();
                 mService.connect(binder, mContext.getOpPackageName(),
-                        new WifiNanEventCallbackProxy(this, looper, binder, callback),
-                        configRequest);
+                        new WifiNanEventCallbackProxy(this, looper, binder, attachCallback,
+                                identityChangedListener), configRequest,
+                        identityChangedListener != null);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -466,16 +457,22 @@
     }
 
     /** @hide */
-    public void sendMessage(int clientId, int sessionId, int peerId, byte[] message, int messageId,
-            int retryCount) {
+    public void sendMessage(int clientId, int sessionId, Object peerHandle, byte[] message,
+            int messageId, int retryCount) {
+        if (peerHandle == null) {
+            throw new IllegalArgumentException(
+                    "sendMessage: invalid peerHandle - must be non-null");
+        }
+
         if (VDBG) {
-            Log.v(TAG,
-                    "sendMessage(): clientId=" + clientId + ", sessionId=" + sessionId + ", peerId="
-                            + peerId + ", messageId=" + messageId + ", retryCount=" + retryCount);
+            Log.v(TAG, "sendMessage(): clientId=" + clientId + ", sessionId=" + sessionId
+                    + ", peerHandle=" + ((OpaquePeerHandle) peerHandle).peerId + ", messageId="
+                    + messageId + ", retryCount=" + retryCount);
         }
 
         try {
-            mService.sendMessage(clientId, sessionId, peerId, message, messageId, retryCount);
+            mService.sendMessage(clientId, sessionId, ((OpaquePeerHandle) peerHandle).peerId,
+                    message, messageId, retryCount);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -503,19 +500,20 @@
     }
 
     /** @hide */
-    public String createNetworkSpecifier(int clientId, int role, int sessionId, int peerId,
+    public String createNetworkSpecifier(int clientId, int role, int sessionId, Object peerHandle,
             byte[] token) {
         if (VDBG) {
             Log.v(TAG, "createNetworkSpecifier: role=" + role + ", sessionId=" + sessionId
-                    + ", peerId=" + peerId + ", token=" + token);
+                    + ", peerHandle=" + ((peerHandle == null) ? peerHandle
+                    : ((OpaquePeerHandle) peerHandle).peerId) + ", token=" + token);
         }
 
         int type;
-        if (token != null && peerId != 0) {
+        if (token != null && peerHandle != null) {
             type = NETWORK_SPECIFIER_TYPE_1A;
-        } else if (token == null && peerId != 0) {
+        } else if (token == null && peerHandle != null) {
             type = NETWORK_SPECIFIER_TYPE_1B;
-        } else if (token != null && peerId == 0) {
+        } else if (token != null && peerHandle == null) {
             type = NETWORK_SPECIFIER_TYPE_1C;
         } else {
             type = NETWORK_SPECIFIER_TYPE_1D;
@@ -532,10 +530,10 @@
                 throw new IllegalArgumentException(
                         "createNetworkSpecifier: Invalid null token - not permitted on INITIATOR");
             }
-            if (peerId == 0) {
+            if (peerHandle == null) {
                 throw new IllegalArgumentException(
-                        "createNetworkSpecifier: Invalid peer ID (value of 0) - not permitted on "
-                                + "INITIATOR");
+                        "createNetworkSpecifier: Invalid peer handle (value of null) - not "
+                                + "permitted on INITIATOR");
             }
         }
 
@@ -546,8 +544,8 @@
             json.put(NETWORK_SPECIFIER_KEY_ROLE, role);
             json.put(NETWORK_SPECIFIER_KEY_CLIENT_ID, clientId);
             json.put(NETWORK_SPECIFIER_KEY_SESSION_ID, sessionId);
-            if (peerId != 0) {
-                json.put(NETWORK_SPECIFIER_KEY_PEER_ID, peerId);
+            if (peerHandle != null) {
+                json.put(NETWORK_SPECIFIER_KEY_PEER_ID, ((OpaquePeerHandle) peerHandle).peerId);
             }
             if (token != null) {
                 json.put(NETWORK_SPECIFIER_KEY_TOKEN,
@@ -561,8 +559,8 @@
     }
 
     /** @hide */
-    public String createNetworkSpecifier(int clientId, @DataPathRole int role, @Nullable byte[] peer,
-            @Nullable byte[] token) {
+    public String createNetworkSpecifier(int clientId, @DataPathRole int role,
+            @Nullable byte[] peer, @Nullable byte[] token) {
         if (VDBG) {
             Log.v(TAG, "createNetworkSpecifier: role=" + role + ", token=" + token);
         }
@@ -648,13 +646,14 @@
         }
 
         /**
-         * Constructs a {@link WifiNanEventCallback} using the specified looper.
+         * Constructs a {@link WifiNanAttachCallback} using the specified looper.
          * All callbacks will delivered on the thread of the specified looper.
          *
          * @param looper The looper on which to execute the callbacks.
          */
         WifiNanEventCallbackProxy(WifiNanManager mgr, Looper looper, Binder binder,
-                final WifiNanEventCallback originalCallback) {
+                final WifiNanAttachCallback attachCallback,
+                final WifiNanIdentityChangedListener identityChangedListener) {
             mNanManager = new WeakReference<>(mgr);
             mLooper = looper;
             mBinder = binder;
@@ -675,15 +674,15 @@
 
                     switch (msg.what) {
                         case CALLBACK_CONNECT_SUCCESS:
-                            originalCallback.onConnectSuccess(
-                                    new WifiNanSession(mgr, mBinder, mLooper, msg.arg1));
+                            attachCallback.onAttached(
+                                    new WifiNanSession(mgr, mBinder, msg.arg1));
                             break;
                         case CALLBACK_CONNECT_FAIL:
                             mNanManager.clear();
-                            originalCallback.onConnectFail(msg.arg1);
+                            attachCallback.onAttachFailed();
                             break;
                         case CALLBACK_IDENTITY_CHANGED:
-                            originalCallback.onIdentityChanged((byte[]) msg.obj);
+                            identityChangedListener.onIdentityChanged((byte[]) msg.obj);
                             break;
                         case CALLBACK_RANGING_SUCCESS: {
                             RttManager.RttListener listener = getAndRemoveRangingListener(msg.arg1);
@@ -732,7 +731,7 @@
 
         @Override
         public void onConnectFail(int reason) {
-            if (VDBG) Log.v(TAG, "onConfigFailed: reason=" + reason);
+            if (VDBG) Log.v(TAG, "onConnectFail: reason=" + reason);
 
             Message msg = mHandler.obtainMessage(CALLBACK_CONNECT_FAIL);
             msg.arg1 = reason;
@@ -834,10 +833,10 @@
                             onProxySessionStarted(msg.arg1);
                             break;
                         case CALLBACK_SESSION_CONFIG_SUCCESS:
-                            mOriginalCallback.onSessionConfigSuccess();
+                            mOriginalCallback.onSessionConfigUpdated();
                             break;
                         case CALLBACK_SESSION_CONFIG_FAIL:
-                            mOriginalCallback.onSessionConfigFail(msg.arg1);
+                            mOriginalCallback.onSessionConfigFailed();
                             if (mSession == null) {
                                 /*
                                  * creation failed (as opposed to update
@@ -850,19 +849,20 @@
                             onProxySessionTerminated(msg.arg1);
                             break;
                         case CALLBACK_MATCH:
-                            mOriginalCallback.onMatch(
-                                    msg.arg1,
+                            mOriginalCallback.onServiceDiscovered(
+                                    new OpaquePeerHandle(msg.arg1),
                                     msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE),
                                     msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE2));
                             break;
                         case CALLBACK_MESSAGE_SEND_SUCCESS:
-                            mOriginalCallback.onMessageSendSuccess(msg.arg1);
+                            mOriginalCallback.onMessageSent(msg.arg1);
                             break;
                         case CALLBACK_MESSAGE_SEND_FAIL:
-                            mOriginalCallback.onMessageSendFail(msg.arg1, msg.arg2);
+                            mOriginalCallback.onMessageSendFailed(msg.arg1);
                             break;
                         case CALLBACK_MESSAGE_RECEIVED:
-                            mOriginalCallback.onMessageReceived(msg.arg1, (byte[]) msg.obj);
+                            mOriginalCallback.onMessageReceived(new OpaquePeerHandle(msg.arg1),
+                                    (byte[]) msg.obj);
                             break;
                     }
                 }
@@ -992,4 +992,13 @@
             mOriginalCallback.onSessionTerminated(reason);
         }
     }
+
+    /** @hide */
+    public static class OpaquePeerHandle {
+        public OpaquePeerHandle(int peerId) {
+            this.peerId = peerId;
+        }
+
+        public int peerId;
+    }
 }
diff --git a/wifi/java/android/net/wifi/nan/WifiNanPublishDiscoverySession.java b/wifi/java/android/net/wifi/nan/WifiNanPublishDiscoverySession.java
index c1731bb..75c6cb7 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanPublishDiscoverySession.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanPublishDiscoverySession.java
@@ -21,8 +21,8 @@
 
 /**
  * A class representing a NAN publish session. Created when
- * {@link WifiNanManager#publish(PublishConfig, WifiNanDiscoverySessionCallback)} is called and a
- * discovery session is created and returned in
+ * {@link WifiNanSession#publish(android.os.Handler, PublishConfig, WifiNanDiscoverySessionCallback)}
+ * is called and a discovery session is created and returned in
  * {@link WifiNanDiscoverySessionCallback#onPublishStarted(WifiNanPublishDiscoverySession)}. See
  * baseline functionality of all discovery sessions in {@link WifiNanDiscoveryBaseSession}. This
  * object allows updating an existing/running publish discovery session using
@@ -44,9 +44,9 @@
      * at creation is still used. The results of the configuration are returned using
      * {@link WifiNanDiscoverySessionCallback}:
      * <ul>
-     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigSuccess()}: configuration
+     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigUpdated()}: configuration
      *     update succeeded.
-     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFail(int)}: configuration
+     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFailed()}: configuration
      *     update failed. The publish discovery session is still running using its previous
      *     configuration (i.e. update failure does not terminate the session).
      * </ul>
diff --git a/wifi/java/android/net/wifi/nan/WifiNanSession.java b/wifi/java/android/net/wifi/nan/WifiNanSession.java
index f9e6017..5fb2c06 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanSession.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanSession.java
@@ -41,39 +41,37 @@
 
     private final WeakReference<WifiNanManager> mMgr;
     private final Binder mBinder;
-    private final Looper mLooper;
     private final int mClientId;
 
     private boolean mTerminated = true;
     private final CloseGuard mCloseGuard = CloseGuard.get();
 
     /** @hide */
-    public WifiNanSession(WifiNanManager manager, Binder binder, Looper looper, int clientId) {
+    public WifiNanSession(WifiNanManager manager, Binder binder, int clientId) {
         if (VDBG) Log.v(TAG, "New session created: manager=" + manager + ", clientId=" + clientId);
 
         mMgr = new WeakReference<>(manager);
         mBinder = binder;
-        mLooper = looper;
         mClientId = clientId;
         mTerminated = false;
 
-        mCloseGuard.open("disconnect");
+        mCloseGuard.open("destroy");
     }
 
     /**
-     * Disconnect from the Wi-Fi NAN service and, if no other applications are connected to NAN,
-     * also disconnect from the NAN cluster. This method destroys all outstanding operations -
-     * i.e. all publish and subscribes are terminated, and any outstanding data-links are
-     * shut-down. However, it is good practice to terminate these discovery sessions and
-     * connections explicitly before a disconnect.
+     * Destroy the Wi-Fi NAN service session and, if no other applications are attached to NAN,
+     * also disable NAN. This method destroys all outstanding operations - i.e. all publish and
+     * subscribes are terminated, and any outstanding data-links are shut-down. However, it is
+     * good practice to destroy these discovery sessions and connections explicitly before a
+     * session-wide destroy.
      * <p>
-     * An application may re-connect after a disconnect using
-     * {@link WifiNanManager#connect(Handler, WifiNanEventCallback)} .
+     * An application may re-attach after a destroy using
+     * {@link WifiNanManager#attach(Handler, WifiNanAttachCallback)} .
      */
-    public void disconnect() {
+    public void destroy() {
         WifiNanManager mgr = mMgr.get();
         if (mgr == null) {
-            Log.w(TAG, "disconnect: called post GC on WifiNanManager");
+            Log.w(TAG, "destroy: called post GC on WifiNanManager");
             return;
         }
         mgr.disconnect(mClientId, mBinder);
@@ -88,7 +86,7 @@
         try {
             if (!mTerminated) {
                 mCloseGuard.warnIfOpen();
-                disconnect();
+                destroy();
             }
         } finally {
             super.finalize();
@@ -100,10 +98,11 @@
      * the specified {@code publishConfig} configuration. The results of the publish operation
      * are routed to the callbacks of {@link WifiNanDiscoverySessionCallback}:
      * <ul>
-     *     <li>{@link WifiNanDiscoverySessionCallback#onPublishStarted(WifiNanPublishDiscoverySession)}
+     *     <li>
+     *     {@link WifiNanDiscoverySessionCallback#onPublishStarted(WifiNanPublishDiscoverySession)}
      *     is called when the publish session is created and provides a handle to the session.
      *     Further operations on the publish session can be executed on that object.
-     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFail(int)} is called if the
+     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFailed()} is called if the
      *     publish operation failed.
      * </ul>
      * <p>
@@ -111,16 +110,18 @@
      * on the {@code callback} object. The resulting publish session can be modified using
      * {@link WifiNanPublishDiscoverySession#updatePublish(PublishConfig)}.
      * <p>
-     *      An application must use the {@link WifiNanDiscoveryBaseSession#terminate()} to
+     *      An application must use the {@link WifiNanDiscoveryBaseSession#destroy()} to
      *      terminate the publish discovery session once it isn't needed. This will free
      *      resources as well terminate any on-air transmissions.
      *
+     * @param handler The Handler on whose thread to execute the callbacks of the {@code
+     * callback} object. If a null is provided then the application's main thread will be used.
      * @param publishConfig The {@link PublishConfig} specifying the
      *            configuration of the requested publish session.
      * @param callback A {@link WifiNanDiscoverySessionCallback} derived object to be used for
      *                 session event callbacks.
      */
-    public void publish(@NonNull PublishConfig publishConfig,
+    public void publish(@Nullable Handler handler, @NonNull PublishConfig publishConfig,
             @NonNull WifiNanDiscoverySessionCallback callback) {
         WifiNanManager mgr = mMgr.get();
         if (mgr == null) {
@@ -131,7 +132,8 @@
             Log.e(TAG, "publish: called after termination");
             return;
         }
-        mgr.publish(mClientId, mLooper, publishConfig, callback);
+        mgr.publish(mClientId, (handler == null) ? Looper.getMainLooper() : handler.getLooper(),
+                publishConfig, callback);
     }
 
     /**
@@ -139,10 +141,11 @@
      * the specified {@code subscribeConfig} configuration. The results of the subscribe
      * operation are routed to the callbacks of {@link WifiNanDiscoverySessionCallback}:
      * <ul>
-     *     <li>{@link WifiNanDiscoverySessionCallback#onSubscribeStarted(WifiNanSubscribeDiscoverySession)}
+     *     <li>
+     *  {@link WifiNanDiscoverySessionCallback#onSubscribeStarted(WifiNanSubscribeDiscoverySession)}
      *     is called when the subscribe session is created and provides a handle to the session.
      *     Further operations on the subscribe session can be executed on that object.
-     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFail(int)} is called if the
+     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFailed()} is called if the
      *     subscribe operation failed.
      * </ul>
      * <p>
@@ -150,16 +153,18 @@
      * on the {@code callback} object. The resulting subscribe session can be modified using
      * {@link WifiNanSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
      * <p>
-     *      An application must use the {@link WifiNanDiscoveryBaseSession#terminate()} to
+     *      An application must use the {@link WifiNanDiscoveryBaseSession#destroy()} to
      *      terminate the subscribe discovery session once it isn't needed. This will free
      *      resources as well terminate any on-air transmissions.
      *
+     * @param handler The Handler on whose thread to execute the callbacks of the {@code
+     * callback} object. If a null is provided then the application's main thread will be used.
      * @param subscribeConfig The {@link SubscribeConfig} specifying the
      *            configuration of the requested subscribe session.
      * @param callback A {@link WifiNanDiscoverySessionCallback} derived object to be used for
      *                 session event callbacks.
      */
-    public void subscribe(@NonNull SubscribeConfig subscribeConfig,
+    public void subscribe(@Nullable Handler handler, @NonNull SubscribeConfig subscribeConfig,
             @NonNull WifiNanDiscoverySessionCallback callback) {
         WifiNanManager mgr = mMgr.get();
         if (mgr == null) {
@@ -170,7 +175,8 @@
             Log.e(TAG, "publish: called after termination");
             return;
         }
-        mgr.subscribe(mClientId, mLooper, subscribeConfig, callback);
+        mgr.subscribe(mClientId, (handler == null) ? Looper.getMainLooper() : handler.getLooper(),
+                subscribeConfig, callback);
     }
 
     /**
@@ -182,7 +188,7 @@
      *     This API is targeted for applications which can obtain the peer MAC address using OOB
      *     (out-of-band) discovery. NAN discovery does not provide the MAC address of the peer -
      *     when using NAN discovery use the alternative network specifier method -
-     *     {@link WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, int, byte[])}.
+     *     {@link WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])}.
      *
      * @param role  The role of this device:
      *              {@link WifiNanManager#WIFI_NAN_DATA_PATH_ROLE_INITIATOR} or
diff --git a/wifi/java/android/net/wifi/nan/WifiNanSubscribeDiscoverySession.java b/wifi/java/android/net/wifi/nan/WifiNanSubscribeDiscoverySession.java
index b8d77aa..f5b4c0c 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanSubscribeDiscoverySession.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanSubscribeDiscoverySession.java
@@ -21,8 +21,8 @@
 
 /**
  * A class representing a NAN subscribe session. Created when
- * {@link WifiNanManager#subscribe(SubscribeConfig, WifiNanDiscoverySessionCallback)} is called
- * and a discovery session is created and returned in
+ * {@link WifiNanSession#subscribe(android.os.Handler, SubscribeConfig, WifiNanDiscoverySessionCallback)}
+ * is called and a discovery session is created and returned in
  * {@link WifiNanDiscoverySessionCallback#onSubscribeStarted(WifiNanSubscribeDiscoverySession)}.
  * See baseline functionality of all discovery sessions in {@link WifiNanDiscoveryBaseSession}.
  * This object allows updating an existing/running subscribe discovery session using
@@ -46,9 +46,9 @@
      * at creation is still used. The results of the configuration are returned using
      * {@link WifiNanDiscoverySessionCallback}:
      * <ul>
-     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigSuccess()}: configuration
+     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigUpdated()}: configuration
      *     update succeeded.
-     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFail(int)}: configuration
+     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFailed()}: configuration
      *     update failed. The subscribe discovery session is still running using its previous
      *     configuration (i.e. update failure does not terminate the session).
      * </ul>
diff --git a/wifi/tests/Android.mk b/wifi/tests/Android.mk
new file mode 100644
index 0000000..5850fee
--- /dev/null
+++ b/wifi/tests/Android.mk
@@ -0,0 +1,61 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+# Make test APK
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+# This list is generated from the java source files in this module
+# The list is a comma separated list of class names with * matching zero or more characters.
+# Example:
+#   Input files: src/com/android/server/wifi/Test.java src/com/android/server/wifi/AnotherTest.java
+#   Generated exclude list: com.android.server.wifi.Test*,com.android.server.wifi.AnotherTest*
+
+# Filter all src files to just java files
+local_java_files := $(filter %.java,$(LOCAL_SRC_FILES))
+# Transform java file names into full class names.
+# This only works if the class name matches the file name and the directory structure
+# matches the package.
+local_classes := $(subst /,.,$(patsubst src/%.java,%,$(local_java_files)))
+# Utility variables to allow replacing a space with a comma
+comma:= ,
+empty:=
+space:= $(empty) $(empty)
+# Convert class name list to jacoco exclude list
+# This appends a * to all classes and replace the space separators with commas.
+# These patterns will match all classes in this module and their inner classes.
+jacoco_exclude := $(subst $(space),$(comma),$(patsubst %,%*,$(local_classes)))
+
+jacoco_include := android.net.wifi.*
+
+LOCAL_JACK_COVERAGE_INCLUDE_FILTER := $(jacoco_include)
+LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := $(jacoco_exclude)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+	android-support-test \
+	mockito-target-minus-junit4 \
+	frameworks-base-testutils \
+
+LOCAL_JAVA_LIBRARIES := \
+	android.test.runner \
+
+LOCAL_PACKAGE_NAME := FrameworksWifiApiTests
+
+include $(BUILD_PACKAGE)
diff --git a/wifi/tests/AndroidManifest.xml b/wifi/tests/AndroidManifest.xml
new file mode 100644
index 0000000..4eaca2b
--- /dev/null
+++ b/wifi/tests/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.net.wifi.test">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <activity android:label="WifiTestDummyLabel"
+                  android:name="WifiTestDummyName">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.net.wifi.test"
+        android:label="Frameworks Wifi API Tests">
+    </instrumentation>
+
+</manifest>
diff --git a/wifi/tests/README.md b/wifi/tests/README.md
new file mode 100644
index 0000000..b418abd
--- /dev/null
+++ b/wifi/tests/README.md
@@ -0,0 +1,50 @@
+# Wifi Unit Tests
+This package contains unit tests for the android wifi framework APIs based on the
+[Android Testing Support Library](http://developer.android.com/tools/testing-support-library/index.html).
+The test cases are built using the [JUnit](http://junit.org/) and [Mockito](http://mockito.org/)
+libraries.
+
+## Running Tests
+The easiest way to run tests is simply run
+
+```
+frameworks/base/wifi/tests/runtests.sh
+```
+
+`runtests.sh` will build the test project and all of its dependencies and push the APK to the
+connected device. It will then run the tests on the device.
+
+To pick up changes in framework/base, you will need to:
+1. rebuild the framework library 'make -j32'
+2. sync over the updated library to the device 'adb sync'
+3. restart framework on the device 'adb shell stop' then 'adb shell start'
+
+To enable syncing data to the device for first time after clean reflash:
+1. adb disable-verity
+2. adb reboot
+3. adb remount
+
+See below for a few example of options to limit which tests are run.
+See the
+[AndroidJUnitRunner Documentation](https://developer.android.com/reference/android/support/test/runner/AndroidJUnitRunner.html)
+for more details on the supported options.
+
+```
+runtests.sh -e package android.net.wifi
+runtests.sh -e class android.net.wifi.WifiScannerTest
+```
+
+If you manually build and push the test APK to the device you can run tests using
+
+```
+adb shell am instrument -w 'android.net.wifi.test/android.support.test.runner.AndroidJUnitRunner'
+```
+
+## Adding Tests
+Tests can be added by adding classes to the src directory. JUnit4 style test cases can
+be written by simply annotating test methods with `org.junit.Test`.
+
+## Debugging Tests
+If you are trying to debug why tests are not doing what you expected, you can add android log
+statements and use logcat to view them. The beginning and end of every tests is automatically logged
+with the tag `TestRunner`.
diff --git a/wifi/tests/runtests.sh b/wifi/tests/runtests.sh
new file mode 100755
index 0000000..ebcc2a2
--- /dev/null
+++ b/wifi/tests/runtests.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+if [ -z $ANDROID_BUILD_TOP ]; then
+  echo "You need to source and lunch before you can use this script"
+  exit 1
+fi
+
+echo "Running tests"
+
+set -e # fail early
+
+echo "+ mmma -j32 $ANDROID_BUILD_TOP/frameworks/base/wifi/tests"
+# NOTE Don't actually run the command above since this shell doesn't inherit functions from the
+#      caller.
+make -j32 -C $ANDROID_BUILD_TOP -f build/core/main.mk MODULES-IN-frameworks-base-wifi-tests
+
+set -x # print commands
+
+adb root
+adb wait-for-device
+
+adb install -r -g "$OUT/data/app/FrameworksWifiApiTests/FrameworksWifiApiTests.apk"
+
+adb shell am instrument -w "$@" 'android.net.wifi.test/android.support.test.runner.AndroidJUnitRunner'
diff --git a/wifi/tests/src/android/net/wifi/FakeKeys.java b/wifi/tests/src/android/net/wifi/FakeKeys.java
new file mode 100644
index 0000000..0c73070
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/FakeKeys.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.net.wifi;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+/**
+ * A class containing test certificates.
+ */
+public class FakeKeys {
+    private static final String CA_CERT0_STRING = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIDKDCCAhCgAwIBAgIJAILlFdwzLVurMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV\n" +
+            "BAMTB0VBUCBDQTEwHhcNMTYwMTEyMTE1MDE1WhcNMjYwMTA5MTE1MDE1WjASMRAw\n" +
+            "DgYDVQQDEwdFQVAgQ0ExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\n" +
+            "znAPUz26Msae4ws43czR41/J2QtrSIZUKmVUsVumDbYHrPNvTXKSMXAcewORDQYX\n" +
+            "RqvHvpn8CscB1+oGXZvHwxj4zV0WKoK2zeXkau3vcyl3HIKupJfq2TEACefVjj0t\n" +
+            "JW+X35PGWp9/H5zIUNVNVjS7Ums84IvKhRB8512PB9UyHagXYVX5GWpAcVpyfrlR\n" +
+            "FI9Qdhh+Pbk0uyktdbf/CdfgHOoebrTtwRljM0oDtX+2Cv6j0wBK7hD8pPvf1+uy\n" +
+            "GzczigAU/4Kw7eZqydf9B+5RupR+IZipX41xEiIrKRwqi517WWzXcjaG2cNbf451\n" +
+            "xpH5PnV3i1tq04jMGQUzFwIDAQABo4GAMH4wHQYDVR0OBBYEFIwX4vs8BiBcScod\n" +
+            "5noZHRM8E4+iMEIGA1UdIwQ7MDmAFIwX4vs8BiBcScod5noZHRM8E4+ioRakFDAS\n" +
+            "MRAwDgYDVQQDEwdFQVAgQ0ExggkAguUV3DMtW6swDAYDVR0TBAUwAwEB/zALBgNV\n" +
+            "HQ8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAFfQqOTA7Rv7K+luQ7pnas4BYwHE\n" +
+            "9GEP/uohv6KOy0TGQFbrRTjFoLVNB9BZ1ymMDZ0/TIwIUc7wi7a8t5mEqYH153wW\n" +
+            "aWooiSjyLLhuI4sNrNCOtisdBq2r2MFXt6h0mAQYOPv8R8K7/fgSxGFqzhyNmmVL\n" +
+            "1qBJldx34SpwsTALQVPb4hGwJzZfr1PcpEQx6xMnTl8xEWZE3Ms99uaUxbQqIwRu\n" +
+            "LgAOkNCmY2m89VhzaHJ1uV85AdM/tD+Ysmlnnjt9LRCejbBipjIGjOXrg1JP+lxV\n" +
+            "muM4vH+P/mlmxsPPz0d65b+EGmJZpoLkO/tdNNvCYzjJpTEWpEsO6NMhKYo=\n" +
+            "-----END CERTIFICATE-----\n";
+    public static final X509Certificate CA_CERT0 = loadCertificate(CA_CERT0_STRING);
+
+    private static final String CA_CERT1_STRING = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIDKDCCAhCgAwIBAgIJAOM5SzKO2pzCMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV\n" +
+            "BAMTB0VBUCBDQTAwHhcNMTYwMTEyMDAxMDQ3WhcNMjYwMTA5MDAxMDQ3WjASMRAw\n" +
+            "DgYDVQQDEwdFQVAgQ0EwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\n" +
+            "89ug+IEKVQXnJGKg5g4uVHg6J/8iRUxR5k2eH5o03hrJNMfN2D+cBe/wCiZcnWbI\n" +
+            "GbGZACWm2nQth2wy9Zgm2LOd3b4ocrHYls3XLq6Qb5Dd7a0JKU7pdGufiNVEkrmF\n" +
+            "EB+N64wgwH4COTvCiN4erp5kyJwkfqAl2xLkZo0C464c9XoyQOXbmYD9A8v10wZu\n" +
+            "jyNsEo7Nr2USyw+qhjWSbFbEirP77Tvx+7pJQJwdtk1V9Tn73T2dGF2WHYejei9S\n" +
+            "mcWpdIUqsu9etYH+zDmtu7I1xlkwiaVsNr2+D+qaCJyOYqrDTKVNK5nmbBPXDWZc\n" +
+            "NoDbTOoqquX7xONpq9M6jQIDAQABo4GAMH4wHQYDVR0OBBYEFAZ3A2S4qJZZwuNY\n" +
+            "wkJ6mAdc0gVdMEIGA1UdIwQ7MDmAFAZ3A2S4qJZZwuNYwkJ6mAdc0gVdoRakFDAS\n" +
+            "MRAwDgYDVQQDEwdFQVAgQ0EwggkA4zlLMo7anMIwDAYDVR0TBAUwAwEB/zALBgNV\n" +
+            "HQ8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAHmdMwEhtys4d0E+t7owBmoVR+lU\n" +
+            "hMCcRtWs8YKX5WIM2kTweT0h/O1xwE1mWmRv/IbDAEb8od4BjAQLhIcolStr2JaO\n" +
+            "9ZzyxjOnNzqeErh/1DHDbb/moPpqfeJ8YiEz7nH/YU56Q8iCPO7TsgS0sNNE7PfN\n" +
+            "IUsBW0yHRgpQ4OxWmiZG2YZWiECRzAC0ecPzo59N5iH4vLQIMTMYquiDeMPQnn1e\n" +
+            "NDGxG8gCtDKIaS6tMg3a28MvWB094pr2ETou8O1C8Ji0Y4hE8QJmSdT7I4+GZjgW\n" +
+            "g94DZ5RiL7sdp3vC48CXOmeT61YBIvhGUsE1rPhXqkpqQ3Z3C4TFF0jXZZc=\n" +
+            "-----END CERTIFICATE-----\n";
+    public static final X509Certificate CA_CERT1 = loadCertificate(CA_CERT1_STRING);
+
+
+    private static X509Certificate loadCertificate(String blob) {
+        try {
+            final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+            InputStream stream = new ByteArrayInputStream(blob.getBytes(StandardCharsets.UTF_8));
+
+            return (X509Certificate) certFactory.generateCertificate(stream);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
new file mode 100644
index 0000000..0d964b7
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.net.wifi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNull;
+
+import android.net.wifi.WifiEnterpriseConfig.Eap;
+import android.net.wifi.WifiEnterpriseConfig.Phase2;
+import android.os.Parcel;
+import android.security.Credentials;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.security.cert.X509Certificate;
+
+
+/**
+ * Unit tests for {@link android.net.wifi.WifiEnterpriseConfig}.
+ */
+@SmallTest
+public class WifiEnterpriseConfigTest {
+    // Maintain a ground truth of the keystore uri prefix which is expected by wpa_supplicant.
+    public static final String KEYSTORE_URI = "keystore://";
+    public static final String CA_CERT_PREFIX = KEYSTORE_URI + Credentials.CA_CERTIFICATE;
+    public static final String KEYSTORES_URI = "keystores://";
+
+    private WifiEnterpriseConfig mEnterpriseConfig;
+
+    @Before
+    public void setUp() throws Exception {
+        mEnterpriseConfig = new WifiEnterpriseConfig();
+    }
+
+    @Test
+    public void testGetEmptyCaCertificate() {
+        // A newly-constructed WifiEnterpriseConfig object should have no CA certificate.
+        assertNull(mEnterpriseConfig.getCaCertificate());
+        assertNull(mEnterpriseConfig.getCaCertificates());
+        // Setting CA certificate to null explicitly.
+        mEnterpriseConfig.setCaCertificate(null);
+        assertNull(mEnterpriseConfig.getCaCertificate());
+        // Setting CA certificate to null using setCaCertificates().
+        mEnterpriseConfig.setCaCertificates(null);
+        assertNull(mEnterpriseConfig.getCaCertificates());
+        // Setting CA certificate to zero-length array.
+        mEnterpriseConfig.setCaCertificates(new X509Certificate[0]);
+        assertNull(mEnterpriseConfig.getCaCertificates());
+    }
+
+    @Test
+    public void testSetGetSingleCaCertificate() {
+        X509Certificate cert0 = FakeKeys.CA_CERT0;
+        mEnterpriseConfig.setCaCertificate(cert0);
+        assertEquals(mEnterpriseConfig.getCaCertificate(), cert0);
+    }
+
+    @Test
+    public void testSetGetMultipleCaCertificates() {
+        X509Certificate cert0 = FakeKeys.CA_CERT0;
+        X509Certificate cert1 = FakeKeys.CA_CERT1;
+        mEnterpriseConfig.setCaCertificates(new X509Certificate[] {cert0, cert1});
+        X509Certificate[] result = mEnterpriseConfig.getCaCertificates();
+        assertEquals(result.length, 2);
+        assertTrue(result[0] == cert0 && result[1] == cert1);
+    }
+
+    @Test
+    public void testSaveSingleCaCertificateAlias() {
+        final String alias = "single_alias 0";
+        mEnterpriseConfig.setCaCertificateAliases(new String[] {alias});
+        assertEquals(getCaCertField(), CA_CERT_PREFIX + alias);
+    }
+
+    @Test
+    public void testLoadSingleCaCertificateAlias() {
+        final String alias = "single_alias 1";
+        setCaCertField(CA_CERT_PREFIX + alias);
+        String[] aliases = mEnterpriseConfig.getCaCertificateAliases();
+        assertEquals(aliases.length, 1);
+        assertEquals(aliases[0], alias);
+    }
+
+    @Test
+    public void testSaveMultipleCaCertificates() {
+        final String alias0 = "single_alias 0";
+        final String alias1 = "single_alias 1";
+        mEnterpriseConfig.setCaCertificateAliases(new String[] {alias0, alias1});
+        assertEquals(getCaCertField(), String.format("%s%s %s",
+                KEYSTORES_URI,
+                WifiEnterpriseConfig.encodeCaCertificateAlias(Credentials.CA_CERTIFICATE + alias0),
+                WifiEnterpriseConfig.encodeCaCertificateAlias(Credentials.CA_CERTIFICATE + alias1)));
+    }
+
+    @Test
+    public void testLoadMultipleCaCertificates() {
+        final String alias0 = "single_alias 0";
+        final String alias1 = "single_alias 1";
+        setCaCertField(String.format("%s%s %s",
+                KEYSTORES_URI,
+                WifiEnterpriseConfig.encodeCaCertificateAlias(Credentials.CA_CERTIFICATE + alias0),
+                WifiEnterpriseConfig.encodeCaCertificateAlias(Credentials.CA_CERTIFICATE + alias1)));
+        String[] aliases = mEnterpriseConfig.getCaCertificateAliases();
+        assertEquals(aliases.length, 2);
+        assertEquals(aliases[0], alias0);
+        assertEquals(aliases[1], alias1);
+    }
+
+    private String getCaCertField() {
+        return mEnterpriseConfig.getFieldValue(WifiEnterpriseConfig.CA_CERT_KEY);
+    }
+
+    private void setCaCertField(String value) {
+        mEnterpriseConfig.setFieldValue(WifiEnterpriseConfig.CA_CERT_KEY, value);
+    }
+
+    // Retrieves the value for a specific key supplied to wpa_supplicant.
+    private class SupplicantConfigExtractor implements WifiEnterpriseConfig.SupplicantSaver {
+        private String mValue = null;
+        private String mKey;
+
+        SupplicantConfigExtractor(String key) {
+            mKey = key;
+        }
+
+        @Override
+        public boolean saveValue(String key, String value) {
+            if (key.equals(mKey)) {
+                mValue = value;
+            }
+            return true;
+        }
+
+        public String getValue() {
+            return mValue;
+        }
+    }
+
+    private String getSupplicantEapMethod() {
+        SupplicantConfigExtractor entryExtractor = new SupplicantConfigExtractor(
+                WifiEnterpriseConfig.EAP_KEY);
+        mEnterpriseConfig.saveToSupplicant(entryExtractor);
+        return entryExtractor.getValue();
+    }
+
+    private String getSupplicantPhase2Method() {
+        SupplicantConfigExtractor entryExtractor = new SupplicantConfigExtractor(
+                WifiEnterpriseConfig.PHASE2_KEY);
+        mEnterpriseConfig.saveToSupplicant(entryExtractor);
+        return entryExtractor.getValue();
+    }
+
+    /** Verifies the default value for EAP outer and inner methods */
+    @Test
+    public void eapInnerDefault() {
+        assertEquals(null, getSupplicantEapMethod());
+        assertEquals(null, getSupplicantPhase2Method());
+    }
+
+    /** Verifies that the EAP inner method is reset when we switch to TLS */
+    @Test
+    public void eapPhase2MethodForTls() {
+        // Initially select an EAP method that supports an phase2.
+        mEnterpriseConfig.setEapMethod(Eap.PEAP);
+        mEnterpriseConfig.setPhase2Method(Phase2.MSCHAPV2);
+        assertEquals("PEAP", getSupplicantEapMethod());
+        assertEquals("\"auth=MSCHAPV2\"", getSupplicantPhase2Method());
+
+        // Change the EAP method to another type which supports a phase2.
+        mEnterpriseConfig.setEapMethod(Eap.TTLS);
+        assertEquals("TTLS", getSupplicantEapMethod());
+        assertEquals("\"auth=MSCHAPV2\"", getSupplicantPhase2Method());
+
+        // Change the EAP method to TLS which does not support a phase2.
+        mEnterpriseConfig.setEapMethod(Eap.TLS);
+        assertEquals(null, getSupplicantPhase2Method());
+    }
+
+    /** Verfies that the EAP inner method is reset when we switch phase2 to NONE */
+    @Test
+    public void eapPhase2None() {
+        // Initially select an EAP method that supports an phase2.
+        mEnterpriseConfig.setEapMethod(Eap.PEAP);
+        mEnterpriseConfig.setPhase2Method(Phase2.MSCHAPV2);
+        assertEquals("PEAP", getSupplicantEapMethod());
+        assertEquals("\"auth=MSCHAPV2\"", getSupplicantPhase2Method());
+
+        // Change the phase2 method to NONE and ensure the value is cleared.
+        mEnterpriseConfig.setPhase2Method(Phase2.NONE);
+        assertEquals(null, getSupplicantPhase2Method());
+    }
+
+    /** Verfies that the correct "autheap" parameter is supplied for TTLS/GTC. */
+    @Test
+    public void peapGtcToTtls() {
+        mEnterpriseConfig.setEapMethod(Eap.PEAP);
+        mEnterpriseConfig.setPhase2Method(Phase2.GTC);
+        assertEquals("PEAP", getSupplicantEapMethod());
+        assertEquals("\"auth=GTC\"", getSupplicantPhase2Method());
+
+        mEnterpriseConfig.setEapMethod(Eap.TTLS);
+        assertEquals("TTLS", getSupplicantEapMethod());
+        assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method());
+    }
+
+    /** Verfies that the correct "auth" parameter is supplied for PEAP/GTC. */
+    @Test
+    public void ttlsGtcToPeap() {
+        mEnterpriseConfig.setEapMethod(Eap.TTLS);
+        mEnterpriseConfig.setPhase2Method(Phase2.GTC);
+        assertEquals("TTLS", getSupplicantEapMethod());
+        assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method());
+
+        mEnterpriseConfig.setEapMethod(Eap.PEAP);
+        assertEquals("PEAP", getSupplicantEapMethod());
+        assertEquals("\"auth=GTC\"", getSupplicantPhase2Method());
+    }
+
+    /** Verfies that the copy constructor preseves the inner method information. */
+    @Test
+    public void copyConstructor() {
+        WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+        enterpriseConfig.setEapMethod(Eap.TTLS);
+        enterpriseConfig.setPhase2Method(Phase2.GTC);
+        mEnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
+        assertEquals("TTLS", getSupplicantEapMethod());
+        assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method());
+    }
+
+    /** Verfies that parceling a WifiEnterpriseConfig preseves method information. */
+    @Test
+    public void parcelConstructor() {
+        WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+        enterpriseConfig.setEapMethod(Eap.TTLS);
+        enterpriseConfig.setPhase2Method(Phase2.GTC);
+        Parcel parcel = Parcel.obtain();
+        enterpriseConfig.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);  // Allow parcel to be read from the beginning.
+        mEnterpriseConfig = WifiEnterpriseConfig.CREATOR.createFromParcel(parcel);
+        assertEquals("TTLS", getSupplicantEapMethod());
+        assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method());
+    }
+
+    /** Verifies proper operation of the getKeyId() method. */
+    @Test
+    public void getKeyId() {
+        assertEquals("NULL", mEnterpriseConfig.getKeyId(null));
+        WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+        enterpriseConfig.setEapMethod(Eap.TTLS);
+        enterpriseConfig.setPhase2Method(Phase2.GTC);
+        assertEquals("TTLS_GTC", mEnterpriseConfig.getKeyId(enterpriseConfig));
+        mEnterpriseConfig.setEapMethod(Eap.PEAP);
+        mEnterpriseConfig.setPhase2Method(Phase2.MSCHAPV2);
+        assertEquals("PEAP_MSCHAPV2", mEnterpriseConfig.getKeyId(enterpriseConfig));
+    }
+
+    /** Verifies that passwords are not displayed in toString. */
+    @Test
+    public void passwordNotInToString() {
+        String password = "supersecret";
+        mEnterpriseConfig.setPassword(password);
+        assertFalse(mEnterpriseConfig.toString().contains(password));
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/WifiScannerTest.java b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
new file mode 100644
index 0000000..a829eb9
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.validateMockitoUsage;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.wifi.WifiScanner.BssidInfo;
+import android.net.wifi.WifiScanner.BssidListener;
+import android.os.Handler;
+import android.os.Message;
+import android.os.test.TestLooper;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.internal.util.test.BidirectionalAsyncChannelServer;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit tests for {@link android.net.wifi.WifiScanner}.
+ */
+@SmallTest
+public class WifiScannerTest {
+    @Mock
+    private Context mContext;
+    @Mock
+    private IWifiScanner mService;
+    @Mock
+    private BssidListener mBssidListener;
+
+    private WifiScanner mWifiScanner;
+    private TestLooper mLooper;
+    private Handler mHandler;
+
+    /**
+     * Setup before tests.
+     */
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mLooper = new TestLooper();
+        mHandler = mock(Handler.class);
+        BidirectionalAsyncChannelServer server = new BidirectionalAsyncChannelServer(
+                mContext, mLooper.getLooper(), mHandler);
+        when(mService.getMessenger()).thenReturn(server.getMessenger());
+        mWifiScanner = new WifiScanner(mContext, mService, mLooper.getLooper());
+        mLooper.dispatchAll();
+    }
+
+    /**
+     * Clean up after tests.
+     */
+    @After
+    public void cleanup() {
+        validateMockitoUsage();
+    }
+
+    private void verifySetHotlistMessage(Handler handler) {
+        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
+        verify(handler, atLeastOnce()).handleMessage(messageCaptor.capture());
+        assertEquals("message.what is not CMD_SET_HOTLIST",
+                WifiScanner.CMD_SET_HOTLIST,
+                messageCaptor.getValue().what);
+    }
+
+    /**
+     * Test duplicate listeners for bssid tracking.
+     */
+    @Test
+    public void testStartTrackingBssidsDuplicateListeners() throws Exception {
+        BssidInfo[] bssids = new BssidInfo[] {
+                new BssidInfo()
+        };
+
+        // First start tracking succeeds.
+        mWifiScanner.startTrackingBssids(bssids, -100, mBssidListener);
+        mLooper.dispatchAll();
+        verifySetHotlistMessage(mHandler);
+
+        // Second start tracking should fail.
+        mWifiScanner.startTrackingBssids(bssids, -100, mBssidListener);
+        mLooper.dispatchAll();
+        verify(mBssidListener).onFailure(eq(WifiScanner.REASON_DUPLICATE_REQEUST), anyString());
+    }
+}