Merge changes I4752bdf1,I37690cf2

* changes:
  Move Surface operations into existing transaction.
  Clear orientation variable until rotation is done.
diff --git a/Android.mk b/Android.mk
index ab06058..3b2d32d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -329,7 +329,10 @@
 	 )
 
 # include definition of libcore_to_document
-include $(LOCAL_PATH)/../../libcore/Docs.mk
+include libcore/Docs.mk
+
+# include definition of junit_to_document
+include external/junit/Common.mk
 
 non_base_dirs := \
 	../../external/apache-http/src/org/apache/http
@@ -353,7 +356,8 @@
 # Common sources for doc check and api check
 common_src_files := \
 	$(call find-other-html-files, $(html_dirs)) \
-	$(addprefix ../../libcore/, $(call libcore_to_document, $(LOCAL_PATH)/../../libcore))
+	$(addprefix ../../libcore/, $(call libcore_to_document, $(LOCAL_PATH)/../../libcore)) \
+	$(addprefix ../../external/junit/, $(call junit_to_document, $(LOCAL_PATH)/../../external/junit))
 
 # These are relative to frameworks/base
 framework_docs_LOCAL_SRC_FILES := \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 1cd5d01..939c117 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -126,6 +126,9 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libRS_intermediates)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libRSDriver_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/host/$(HOST_PREBUILT_TAG)/obj/STATIC_LIBRARIES/libRS_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/accessibilityservice/IEventListener.java)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/accessibilityservice/IEventListener.P)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/view/accessibility/IAccessibilityManager.P)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/api/16.txt b/api/16.txt
index cc67785..9e9f880 100644
--- a/api/16.txt
+++ b/api/16.txt
@@ -9513,7 +9513,7 @@
     method public abstract void onSensorChanged(int, float[]);
   }
 
-  public class SensorManager {
+  public abstract class SensorManager {
     method public static float getAltitude(float, float);
     method public static void getAngleChange(float[], float[], float[]);
     method public android.hardware.Sensor getDefaultSensor(int);
diff --git a/api/current.txt b/api/current.txt
index e4836a3..da28937 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -534,7 +534,7 @@
     field public static final int imeSubtypeLocale = 16843500; // 0x10102ec
     field public static final int imeSubtypeMode = 16843501; // 0x10102ed
     field public static final int immersive = 16843456; // 0x10102c0
-    field public static final int importantForAccessibility = 16843699; // 0x10103b3
+    field public static final int importantForAccessibility = 16843698; // 0x10103b2
     field public static final int inAnimation = 16843127; // 0x1010177
     field public static final int includeFontPadding = 16843103; // 0x101015f
     field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -936,7 +936,6 @@
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
     field public static final int supportsRtl = 16843688; // 0x10103a8
-    field public static final int supportsSentenceSpellCheck = 16843698; // 0x10103b2
     field public static final int supportsUploading = 16843419; // 0x101029b
     field public static final int switchMinWidth = 16843632; // 0x1010370
     field public static final int switchPadding = 16843633; // 0x1010371
@@ -2896,6 +2895,7 @@
   public class ActivityOptions {
     method public void join(android.app.ActivityOptions);
     method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
+    method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int);
     method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
     method public android.os.Bundle toBundle();
   }
@@ -3265,6 +3265,7 @@
     method public android.app.DownloadManager.Request addRequestHeader(java.lang.String, java.lang.String);
     method public void allowScanningByMediaScanner();
     method public android.app.DownloadManager.Request setAllowedNetworkTypes(int);
+    method public android.app.DownloadManager.Request setAllowedOverMetered(boolean);
     method public android.app.DownloadManager.Request setAllowedOverRoaming(boolean);
     method public android.app.DownloadManager.Request setDescription(java.lang.CharSequence);
     method public android.app.DownloadManager.Request setDestinationInExternalFilesDir(android.content.Context, java.lang.String, java.lang.String);
@@ -9017,6 +9018,8 @@
 
   public class SurfaceTexture {
     ctor public SurfaceTexture(int);
+    method public void attachToGLContext(int);
+    method public void detachFromGLContext();
     method public long getTimestamp();
     method public void getTransformMatrix(float[]);
     method public void release();
@@ -9779,7 +9782,7 @@
     method public abstract void onSensorChanged(int, float[]);
   }
 
-  public class SensorManager {
+  public abstract class SensorManager {
     method public static float getAltitude(float, float);
     method public static void getAngleChange(float[], float[], float[]);
     method public android.hardware.Sensor getDefaultSensor(int);
@@ -9795,8 +9798,8 @@
     method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int);
     method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, android.os.Handler);
     method public static boolean remapCoordinateSystem(float[], int, int, float[]);
-    method public deprecated void unregisterListener(android.hardware.SensorListener, int);
     method public deprecated void unregisterListener(android.hardware.SensorListener);
+    method public deprecated void unregisterListener(android.hardware.SensorListener, int);
     method public void unregisterListener(android.hardware.SensorEventListener, android.hardware.Sensor);
     method public void unregisterListener(android.hardware.SensorEventListener);
     field public static final int AXIS_MINUS_X = 129; // 0x81
@@ -10935,6 +10938,91 @@
     field public static final int STOP_VIDEO_RECORDING = 3; // 0x3
   }
 
+  public final class MediaCodec {
+    method public void configure(java.util.Map<java.lang.String, java.lang.Object>, android.view.Surface, android.media.MediaCrypto, int);
+    method public static android.media.MediaCodec createByCodecName(java.lang.String);
+    method public static android.media.MediaCodec createDecoderByType(java.lang.String);
+    method public static android.media.MediaCodec createEncoderByType(java.lang.String);
+    method public final int dequeueInputBuffer(long);
+    method public final int dequeueOutputBuffer(android.media.MediaCodec.BufferInfo, long);
+    method public final void flush();
+    method public java.nio.ByteBuffer[] getInputBuffers();
+    method public java.nio.ByteBuffer[] getOutputBuffers();
+    method public final java.util.Map<java.lang.String, java.lang.Object> getOutputFormat();
+    method public final void queueInputBuffer(int, int, int, long, int);
+    method public final void queueSecureInputBuffer(int, int, int[], int[], int, byte[], byte[], int, long, int);
+    method public final void release();
+    method public final void releaseOutputBuffer(int, boolean);
+    method public final void start();
+    method public final void stop();
+    field public static int CONFIGURE_FLAG_ENCODE;
+    field public static final int FLAG_CODECCONFIG = 2; // 0x2
+    field public static final int FLAG_EOS = 4; // 0x4
+    field public static final int FLAG_SYNCFRAME = 1; // 0x1
+    field public static final int INFO_OUTPUT_BUFFERS_CHANGED = -3; // 0xfffffffd
+    field public static final int INFO_OUTPUT_FORMAT_CHANGED = -2; // 0xfffffffe
+    field public static final int INFO_TRY_AGAIN_LATER = -1; // 0xffffffff
+    field public static final int MODE_AES_CTR = 1; // 0x1
+    field public static final int MODE_UNENCRYPTED = 0; // 0x0
+  }
+
+  public static final class MediaCodec.BufferInfo {
+    ctor public MediaCodec.BufferInfo();
+    method public void set(int, int, long, int);
+    field public int flags;
+    field public int offset;
+    field public long presentationTimeUs;
+    field public int size;
+  }
+
+  public final class MediaCodecList {
+    method public static final int countCodecs();
+    method public static final android.media.MediaCodecList.CodecCapabilities getCodecCapabilities(int, java.lang.String);
+    method public static final java.lang.String getCodecName(int);
+    method public static final java.lang.String[] getSupportedTypes(int);
+    method public static final boolean isEncoder(int);
+  }
+
+  public static final class MediaCodecList.CodecCapabilities {
+    ctor public MediaCodecList.CodecCapabilities();
+    field public int[] colorFormats;
+    field public android.media.MediaCodecList.CodecProfileLevel[] profileLevels;
+  }
+
+  public static final class MediaCodecList.CodecProfileLevel {
+    ctor public MediaCodecList.CodecProfileLevel();
+    field public int level;
+    field public int profile;
+  }
+
+  public final class MediaCrypto {
+    ctor public MediaCrypto(byte[], byte[]) throws java.lang.RuntimeException;
+    method public static final boolean isCryptoSchemeSupported(byte[]);
+    method public final void release();
+    method public final boolean requiresSecureDecoderComponent(java.lang.String);
+  }
+
+  public final class MediaExtractor {
+    ctor public MediaExtractor();
+    method public boolean advance();
+    method public int countTracks();
+    method public int getSampleFlags();
+    method public long getSampleTime();
+    method public int getSampleTrackIndex();
+    method public java.util.Map<java.lang.String, java.lang.Object> getTrackFormat(int);
+    method public int readSampleData(java.nio.ByteBuffer, int);
+    method public final void release();
+    method public void seekTo(long);
+    method public void selectTrack(int);
+    method public final void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
+    method public final void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>);
+    method public final void setDataSource(java.lang.String);
+    method public final void setDataSource(java.io.FileDescriptor);
+    method public final void setDataSource(java.io.FileDescriptor, long, long);
+    field public static final int SAMPLE_FLAG_ENCRYPTED = 2; // 0x2
+    field public static final int SAMPLE_FLAG_SYNC = 1; // 0x1
+  }
+
   public class MediaMetadataRetriever {
     ctor public MediaMetadataRetriever();
     method public java.lang.String extractMetadata(int);
@@ -11833,6 +11921,7 @@
     method public deprecated boolean getBackgroundDataSetting();
     method public android.net.NetworkInfo getNetworkInfo(int);
     method public int getNetworkPreference();
+    method public boolean isActiveNetworkMetered();
     method public static boolean isNetworkTypeValid(int);
     method public boolean requestRouteToHost(int, int);
     method public void setNetworkPreference(int);
@@ -12305,6 +12394,86 @@
 
 }
 
+package android.net.nsd {
+
+  public class DnsSdServiceInfo implements android.os.Parcelable {
+    ctor public DnsSdServiceInfo();
+    method public int describeContents();
+    method public java.net.InetAddress getHost();
+    method public int getPort();
+    method public java.lang.String getServiceName();
+    method public java.lang.String getServiceType();
+    method public void setHost(java.net.InetAddress);
+    method public void setPort(int);
+    method public void setServiceName(java.lang.String);
+    method public void setServiceType(java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class DnsSdTxtRecord implements android.os.Parcelable {
+    ctor public DnsSdTxtRecord();
+    ctor public DnsSdTxtRecord(byte[]);
+    ctor public DnsSdTxtRecord(android.net.nsd.DnsSdTxtRecord);
+    method public boolean contains(java.lang.String);
+    method public int describeContents();
+    method public java.lang.String get(java.lang.String);
+    method public byte[] getRawData();
+    method public int keyCount();
+    method public int remove(java.lang.String);
+    method public void set(java.lang.String, java.lang.String);
+    method public int size();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class NsdManager {
+    method public void deinitialize(android.net.nsd.NsdManager.Channel);
+    method public void discoverServices(android.net.nsd.NsdManager.Channel, java.lang.String, android.net.nsd.NsdManager.DnsSdDiscoveryListener);
+    method public void initialize(android.content.Context, android.os.Looper, android.net.nsd.NsdManager.ChannelListener);
+    method public void registerService(android.net.nsd.NsdManager.Channel, java.lang.String, java.lang.String, int, android.net.nsd.NsdManager.DnsSdRegisterListener);
+    method public void resolveService(android.net.nsd.NsdManager.Channel, java.lang.String, java.lang.String, android.net.nsd.NsdManager.DnsSdResolveListener);
+    method public void stopServiceDiscovery(android.net.nsd.NsdManager.Channel, android.net.nsd.NsdManager.ActionListener);
+    method public void unregisterService(android.net.nsd.NsdManager.Channel, int, android.net.nsd.NsdManager.ActionListener);
+    field public static final int ALREADY_ACTIVE = 3; // 0x3
+    field public static final int BUSY = 2; // 0x2
+    field public static final int ERROR = 0; // 0x0
+    field public static final int MAX_REGS_REACHED = 4; // 0x4
+    field public static final int UNSUPPORTED = 1; // 0x1
+  }
+
+  public static abstract interface NsdManager.ActionListener {
+    method public abstract void onFailure(int);
+    method public abstract void onSuccess();
+  }
+
+  public static class NsdManager.Channel {
+  }
+
+  public static abstract interface NsdManager.ChannelListener {
+    method public abstract void onChannelConnected(android.net.nsd.NsdManager.Channel);
+    method public abstract void onChannelDisconnected();
+  }
+
+  public static abstract interface NsdManager.DnsSdDiscoveryListener {
+    method public abstract void onFailure(int);
+    method public abstract void onServiceFound(android.net.nsd.DnsSdServiceInfo);
+    method public abstract void onServiceLost(android.net.nsd.DnsSdServiceInfo);
+    method public abstract void onStarted(java.lang.String);
+  }
+
+  public static abstract interface NsdManager.DnsSdRegisterListener {
+    method public abstract void onFailure(int);
+    method public abstract void onServiceRegistered(int, android.net.nsd.DnsSdServiceInfo);
+  }
+
+  public static abstract interface NsdManager.DnsSdResolveListener {
+    method public abstract void onFailure(int);
+    method public abstract void onServiceResolved(android.net.nsd.DnsSdServiceInfo);
+  }
+
+}
+
 package android.net.rtp {
 
   public class AudioCodec {
@@ -12811,15 +12980,26 @@
   }
 
   public class WifiP2pManager {
+    method public void addLocalService(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.nsd.WifiP2pServiceInfo, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public void addServiceRequest(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.nsd.WifiP2pServiceRequest, android.net.wifi.p2p.WifiP2pManager.ActionListener);
     method public void cancelConnect(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public void clearLocalServices(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public void clearServiceRequests(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
     method public void connect(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pConfig, android.net.wifi.p2p.WifiP2pManager.ActionListener);
     method public void createGroup(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
     method public void discoverPeers(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public void discoverServices(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
     method public android.net.wifi.p2p.WifiP2pManager.Channel initialize(android.content.Context, android.os.Looper, android.net.wifi.p2p.WifiP2pManager.ChannelListener);
     method public void removeGroup(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public void removeLocalService(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.nsd.WifiP2pServiceInfo, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public void removeServiceRequest(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.nsd.WifiP2pServiceRequest, android.net.wifi.p2p.WifiP2pManager.ActionListener);
     method public void requestConnectionInfo(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ConnectionInfoListener);
     method public void requestGroupInfo(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.GroupInfoListener);
     method public void requestPeers(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.PeerListListener);
+    method public void setDnsSdResponseListeners(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.DnsSdServiceResponseListener, android.net.wifi.p2p.WifiP2pManager.DnsSdTxtRecordListener);
+    method public void setServiceResponseListener(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ServiceResponseListener);
+    method public void setUpnpServiceResponseListener(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.UpnpServiceResponseListener);
+    method public void stopPeerDiscovery(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
     field public static final int BUSY = 2; // 0x2
     field public static final int ERROR = 0; // 0x0
     field public static final java.lang.String EXTRA_DISCOVERY_STATE = "discoveryState";
@@ -12855,6 +13035,14 @@
     method public abstract void onConnectionInfoAvailable(android.net.wifi.p2p.WifiP2pInfo);
   }
 
+  public static abstract interface WifiP2pManager.DnsSdServiceResponseListener {
+    method public abstract void onDnsSdServiceAvailable(java.lang.String, java.lang.String, android.net.wifi.p2p.WifiP2pDevice);
+  }
+
+  public static abstract interface WifiP2pManager.DnsSdTxtRecordListener {
+    method public abstract void onDnsSdTxtRecordAvailable(java.lang.String, android.net.nsd.DnsSdTxtRecord, android.net.wifi.p2p.WifiP2pDevice);
+  }
+
   public static abstract interface WifiP2pManager.GroupInfoListener {
     method public abstract void onGroupInfoAvailable(android.net.wifi.p2p.WifiP2pGroup);
   }
@@ -12863,6 +13051,53 @@
     method public abstract void onPeersAvailable(android.net.wifi.p2p.WifiP2pDeviceList);
   }
 
+  public static abstract interface WifiP2pManager.ServiceResponseListener {
+    method public abstract void onServiceAvailable(int, byte[], android.net.wifi.p2p.WifiP2pDevice);
+  }
+
+  public static abstract interface WifiP2pManager.UpnpServiceResponseListener {
+    method public abstract void onUpnpServiceAvailable(java.util.List<java.lang.String>, android.net.wifi.p2p.WifiP2pDevice);
+  }
+
+}
+
+package android.net.wifi.p2p.nsd {
+
+  public class WifiP2pDnsSdServiceInfo extends android.net.wifi.p2p.nsd.WifiP2pServiceInfo {
+    method public static android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo newInstance(java.lang.String, java.lang.String, android.net.nsd.DnsSdTxtRecord);
+  }
+
+  public class WifiP2pDnsSdServiceRequest extends android.net.wifi.p2p.nsd.WifiP2pServiceRequest {
+    method public static android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceRequest newInstance();
+    method public static android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceRequest newInstance(java.lang.String);
+    method public static android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceRequest newInstance(java.lang.String, java.lang.String);
+  }
+
+  public class WifiP2pServiceInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int SERVICE_TYPE_ALL = 0; // 0x0
+    field public static final int SERVICE_TYPE_BONJOUR = 1; // 0x1
+    field public static final int SERVICE_TYPE_UPNP = 2; // 0x2
+    field public static final int SERVICE_TYPE_VENDOR_SPECIFIC = 255; // 0xff
+  }
+
+  public class WifiP2pServiceRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public static android.net.wifi.p2p.nsd.WifiP2pServiceRequest newInstance(int, java.lang.String);
+    method public static android.net.wifi.p2p.nsd.WifiP2pServiceRequest newInstance(int);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class WifiP2pUpnpServiceInfo extends android.net.wifi.p2p.nsd.WifiP2pServiceInfo {
+    method public static android.net.wifi.p2p.nsd.WifiP2pUpnpServiceInfo newInstance(java.lang.String, java.lang.String, java.util.List<java.lang.String>);
+  }
+
+  public class WifiP2pUpnpServiceRequest extends android.net.wifi.p2p.nsd.WifiP2pServiceRequest {
+    method public static android.net.wifi.p2p.nsd.WifiP2pUpnpServiceRequest newInstance();
+    method public static android.net.wifi.p2p.nsd.WifiP2pUpnpServiceRequest newInstance(java.lang.String);
+  }
+
 }
 
 package android.nfc {
@@ -23303,6 +23538,7 @@
     method public android.graphics.Canvas lockCanvas(android.graphics.Rect);
     method protected final void onDraw(android.graphics.Canvas);
     method public void setOpaque(boolean);
+    method public void setSurfaceTexture(android.graphics.SurfaceTexture);
     method public void setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener);
     method public void setTransform(android.graphics.Matrix);
     method public void unlockCanvasAndPost(android.graphics.Canvas);
@@ -24127,6 +24363,7 @@
     method public android.view.View getFocusedChild();
     method public android.view.animation.LayoutAnimationController getLayoutAnimation();
     method public android.view.animation.Animation.AnimationListener getLayoutAnimationListener();
+    method public int getLayoutMode();
     method public android.animation.LayoutTransition getLayoutTransition();
     method public int getPersistentDrawingCache();
     method public int indexOfChild(android.view.View);
@@ -24174,6 +24411,7 @@
     method public void setDescendantFocusability(int);
     method public void setLayoutAnimation(android.view.animation.LayoutAnimationController);
     method public void setLayoutAnimationListener(android.view.animation.Animation.AnimationListener);
+    method public void setLayoutMode(int);
     method public void setLayoutTransition(android.animation.LayoutTransition);
     method public void setMotionEventSplittingEnabled(boolean);
     method public void setOnHierarchyChangeListener(android.view.ViewGroup.OnHierarchyChangeListener);
@@ -24186,9 +24424,11 @@
     method public void startViewTransition(android.view.View);
     method public void updateViewLayout(android.view.View, android.view.ViewGroup.LayoutParams);
     field protected static final int CLIP_TO_PADDING_MASK = 34; // 0x22
+    field public static final int COMPONENT_BOUNDS = 0; // 0x0
     field public static final int FOCUS_AFTER_DESCENDANTS = 262144; // 0x40000
     field public static final int FOCUS_BEFORE_DESCENDANTS = 131072; // 0x20000
     field public static final int FOCUS_BLOCK_DESCENDANTS = 393216; // 0x60000
+    field public static final int LAYOUT_BOUNDS = 1; // 0x1
     field public static final int PERSISTENT_ALL_CACHES = 3; // 0x3
     field public static final int PERSISTENT_ANIMATION_CACHE = 1; // 0x1
     field public static final int PERSISTENT_NO_CACHE = 0; // 0x0
@@ -25425,9 +25665,8 @@
     method public void close();
     method public void getSentenceSuggestions(android.view.textservice.TextInfo[], int);
     method public android.view.textservice.SpellCheckerInfo getSpellChecker();
-    method public void getSuggestions(android.view.textservice.TextInfo, int);
-    method public void getSuggestions(android.view.textservice.TextInfo[], int, boolean);
-    method public boolean isSentenceSpellCheckSupported();
+    method public deprecated void getSuggestions(android.view.textservice.TextInfo, int);
+    method public deprecated void getSuggestions(android.view.textservice.TextInfo[], int, boolean);
     method public boolean isSessionDisconnected();
     field public static final java.lang.String SERVICE_META_DATA = "android.view.textservice.scs";
   }
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index c3cceaf..423b02a 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -73,6 +73,18 @@
     public static final String KEY_ANIM_START_Y = "android:animStartY";
 
     /**
+     * Initial width of the animation.
+     * @hide
+     */
+    public static final String KEY_ANIM_START_WIDTH = "android:animStartWidth";
+
+    /**
+     * Initial height of the animation.
+     * @hide
+     */
+    public static final String KEY_ANIM_START_HEIGHT = "android:animStartHeight";
+
+    /**
      * Callback for when animation is started.
      * @hide
      */
@@ -83,7 +95,9 @@
     /** @hide */
     public static final int ANIM_CUSTOM = 1;
     /** @hide */
-    public static final int ANIM_THUMBNAIL = 2;
+    public static final int ANIM_SCALE_UP = 2;
+    /** @hide */
+    public static final int ANIM_THUMBNAIL = 3;
 
     private String mPackageName;
     private int mAnimationType = ANIM_NONE;
@@ -92,6 +106,8 @@
     private Bitmap mThumbnail;
     private int mStartX;
     private int mStartY;
+    private int mStartWidth;
+    private int mStartHeight;
     private IRemoteCallback mAnimationStartedListener;
 
     /**
@@ -127,6 +143,34 @@
     }
 
     /**
+     * Create an ActivityOptions specifying an animation where the new
+     * activity is scaled from a small originating area of the screen to
+     * its final full representation.
+     *
+     * @param source The View that the new activity is animating from.  This
+     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
+     * @param startX The x starting location of the new activity, relative to <var>source</var>.
+     * @param startY The y starting location of the activity, relative to <var>source</var>.
+     * @param startWidth The initial width of the new activity.
+     * @param startWidth The initial height of the new activity.
+     * @return Returns a new ActivityOptions object that you can use to
+     * supply these options as the options Bundle when starting an activity.
+     */
+    public static ActivityOptions makeScaleUpAnimation(View source,
+            int startX, int startY, int startWidth, int startHeight) {
+        ActivityOptions opts = new ActivityOptions();
+        opts.mPackageName = source.getContext().getPackageName();
+        opts.mAnimationType = ANIM_SCALE_UP;
+        int[] pts = new int[2];
+        source.getLocationOnScreen(pts);
+        opts.mStartX = pts[0] + startX;
+        opts.mStartY = pts[1] + startY;
+        opts.mStartWidth = startWidth;
+        opts.mStartHeight = startHeight;
+        return opts;
+    }
+
+    /**
      * Create an ActivityOptions specifying an animation where a thumbnail
      * is scaled from a given position to the new activity window that is
      * being started.
@@ -135,8 +179,8 @@
      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
      * @param thumbnail The bitmap that will be shown as the initial thumbnail
      * of the animation.
-     * @param startX The x starting location of the bitmap, in screen coordiantes.
-     * @param startY The y starting location of the bitmap, in screen coordinates.
+     * @param startX The x starting location of the bitmap, relative to <var>source</var>.
+     * @param startY The y starting location of the bitmap, relative to <var>source</var>.
      * @return Returns a new ActivityOptions object that you can use to
      * supply these options as the options Bundle when starting an activity.
      */
@@ -154,8 +198,8 @@
      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
      * @param thumbnail The bitmap that will be shown as the initial thumbnail
      * of the animation.
-     * @param startX The x starting location of the bitmap, in screen coordiantes.
-     * @param startY The y starting location of the bitmap, in screen coordinates.
+     * @param startX The x starting location of the bitmap, relative to <var>source</var>.
+     * @param startY The y starting location of the bitmap, relative to <var>source</var>.
      * @param listener Optional OnAnimationStartedListener to find out when the
      * requested animation has started running.  If for some reason the animation
      * is not executed, the callback will happen immediately.
@@ -199,6 +243,11 @@
         if (mAnimationType == ANIM_CUSTOM) {
             mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0);
             mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0);
+        } else if (mAnimationType == ANIM_SCALE_UP) {
+            mStartX = opts.getInt(KEY_ANIM_START_X, 0);
+            mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
+            mStartWidth = opts.getInt(KEY_ANIM_START_WIDTH, 0);
+            mStartHeight = opts.getInt(KEY_ANIM_START_HEIGHT, 0);
         } else if (mAnimationType == ANIM_THUMBNAIL) {
             mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL);
             mStartX = opts.getInt(KEY_ANIM_START_X, 0);
@@ -244,6 +293,16 @@
     }
 
     /** @hide */
+    public int getStartWidth() {
+        return mStartWidth;
+    }
+
+    /** @hide */
+    public int getStartHeight() {
+        return mStartHeight;
+    }
+
+    /** @hide */
     public IRemoteCallback getOnAnimationStartListener() {
         return mAnimationStartedListener;
     }
@@ -281,6 +340,13 @@
                 mThumbnail = null;
                 mAnimationStartedListener = null;
                 break;
+            case ANIM_SCALE_UP:
+                mAnimationType = otherOptions.mAnimationType;
+                mStartX = otherOptions.mStartX;
+                mStartY = otherOptions.mStartY;
+                mStartWidth = otherOptions.mStartWidth;
+                mStartHeight = otherOptions.mStartHeight;
+                break;
             case ANIM_THUMBNAIL:
                 mAnimationType = otherOptions.mAnimationType;
                 mThumbnail = otherOptions.mThumbnail;
@@ -316,6 +382,13 @@
                 b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
                 b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
                 break;
+            case ANIM_SCALE_UP:
+                b.putInt(KEY_ANIM_TYPE, mAnimationType);
+                b.putInt(KEY_ANIM_START_X, mStartX);
+                b.putInt(KEY_ANIM_START_Y, mStartY);
+                b.putInt(KEY_ANIM_START_WIDTH, mStartWidth);
+                b.putInt(KEY_ANIM_START_HEIGHT, mStartHeight);
+                break;
             case ANIM_THUMBNAIL:
                 b.putInt(KEY_ANIM_TYPE, mAnimationType);
                 b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
@@ -323,6 +396,7 @@
                 b.putInt(KEY_ANIM_START_Y, mStartY);
                 b.putIBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
                         != null ? mAnimationStartedListener.asBinder() : null);
+                break;
         }
         return b;
     }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 0645aa9..8942135 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -45,6 +45,7 @@
 import android.hardware.ISerialManager;
 import android.hardware.SensorManager;
 import android.hardware.SerialManager;
+import android.hardware.SystemSensorManager;
 import android.hardware.input.IInputManager;
 import android.hardware.input.InputManager;
 import android.hardware.usb.IUsbManager;
@@ -407,7 +408,7 @@
 
         registerService(SENSOR_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
-                    return new SensorManager(ctx.mMainThread.getHandler().getLooper());
+                    return new SystemSensorManager(ctx.mMainThread.getHandler().getLooper());
                 }});
 
         registerService(STATUS_BAR_SERVICE, new ServiceFetcher() {
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index dd58397..55f29e6 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -349,6 +349,7 @@
         private String mMimeType;
         private boolean mRoamingAllowed = true;
         private int mAllowedNetworkTypes = ~0; // default to all network types allowed
+        private boolean mAllowedOverMetered = true;
         private boolean mIsVisibleInDownloadsUi = true;
         private boolean mScannable = false;
         private boolean mUseSystemCache = false;
@@ -609,8 +610,11 @@
         }
 
         /**
-         * Restrict the types of networks over which this download may proceed.  By default, all
-         * network types are allowed.
+         * Restrict the types of networks over which this download may proceed.
+         * By default, all network types are allowed. Consider using
+         * {@link #setAllowedOverMetered(boolean)} instead, since it's more
+         * flexible.
+         *
          * @param flags any combination of the NETWORK_* bit flags.
          * @return this object
          */
@@ -620,6 +624,17 @@
         }
 
         /**
+         * Set whether this download may proceed over a metered network
+         * connection. By default, metered networks are allowed.
+         *
+         * @see ConnectivityManager#isActiveNetworkMetered()
+         */
+        public Request setAllowedOverMetered(boolean allow) {
+            mAllowedOverMetered = allow;
+            return this;
+        }
+
+        /**
          * Set whether this download may proceed over a roaming connection.  By default, roaming is
          * allowed.
          * @param allowed whether to allow a roaming connection to be used
@@ -672,6 +687,7 @@
             putIfNonNull(values, Downloads.Impl.COLUMN_DESCRIPTION, mDescription);
             putIfNonNull(values, Downloads.Impl.COLUMN_MIME_TYPE, mMimeType);
 
+            // TODO: add COLUMN_ALLOW_METERED and persist
             values.put(Downloads.Impl.COLUMN_VISIBILITY, mNotificationVisibility);
             values.put(Downloads.Impl.COLUMN_ALLOWED_NETWORK_TYPES, mAllowedNetworkTypes);
             values.put(Downloads.Impl.COLUMN_ALLOW_ROAMING, mRoamingAllowed);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 19e4372..6653336 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -6576,35 +6576,54 @@
 
         final String action = getAction();
         if (ACTION_SEND.equals(action)) {
-            final Uri stream;
+            Uri stream = null;
             try {
                 stream = getParcelableExtra(EXTRA_STREAM);
             } catch (ClassCastException e) {
-                return;
             }
-            if (stream != null) {
+            final CharSequence text = getCharSequenceExtra(EXTRA_TEXT);
+            final String htmlText = getStringExtra(EXTRA_HTML_TEXT);
+            if (stream != null || text != null || htmlText != null) {
                 final ClipData clipData = new ClipData(
-                        null, new String[] { getType() }, new ClipData.Item(stream));
-
+                        null, new String[] { getType() },
+                        new ClipData.Item(text, htmlText, null, stream));
                 setClipData(clipData);
                 addFlags(FLAG_GRANT_READ_URI_PERMISSION);
             }
 
         } else if (ACTION_SEND_MULTIPLE.equals(action)) {
-            final ArrayList<Uri> streams;
+            ArrayList<Uri> streams = null;
             try {
                 streams = getParcelableArrayListExtra(EXTRA_STREAM);
             } catch (ClassCastException e) {
-                return;
             }
-            if (streams != null && streams.size() > 0) {
-                final Uri firstStream = streams.get(0);
+            final ArrayList<CharSequence> texts = getCharSequenceArrayListExtra(EXTRA_TEXT);
+            final ArrayList<String> htmlTexts = getStringArrayListExtra(EXTRA_HTML_TEXT);
+            int num = -1;
+            if (streams != null) {
+                num = streams.size();
+            }
+            if (texts != null) {
+                if (num >= 0 && num != texts.size()) {
+                    // Wha...!  F- you.
+                    return;
+                }
+                num = texts.size();
+            }
+            if (htmlTexts != null) {
+                if (num >= 0 && num != htmlTexts.size()) {
+                    // Wha...!  F- you.
+                    return;
+                }
+                num = htmlTexts.size();
+            }
+            if (num > 0) {
                 final ClipData clipData = new ClipData(
-                        null, new String[] { getType() }, new ClipData.Item(firstStream));
+                        null, new String[] { getType() },
+                        makeClipItem(streams, texts, htmlTexts, 0));
 
-                final int size = streams.size();
-                for (int i = 1; i < size; i++) {
-                    clipData.addItem(new ClipData.Item(streams.get(i)));
+                for (int i = 1; i < num; i++) {
+                    clipData.addItem(makeClipItem(streams, texts, htmlTexts, i));
                 }
 
                 setClipData(clipData);
@@ -6612,4 +6631,12 @@
             }
         }
     }
+
+    private static ClipData.Item makeClipItem(ArrayList<Uri> streams, ArrayList<CharSequence> texts,
+            ArrayList<String> htmlTexts, int which) {
+        Uri uri = streams != null ? streams.get(which) : null;
+        CharSequence text = texts != null ? texts.get(which) : null;
+        String htmlText = htmlTexts != null ? htmlTexts.get(which) : null;
+        return new ClipData.Item(text, htmlText, null, uri);
+    }
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index b6ebbdf..185fcb9 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3458,9 +3458,9 @@
             ai.disableCompatibilityMode();
         }
         if (stopped) {
-            p.applicationInfo.flags |= ApplicationInfo.FLAG_STOPPED;
+            ai.flags |= ApplicationInfo.FLAG_STOPPED;
         } else {
-            p.applicationInfo.flags &= ~ApplicationInfo.FLAG_STOPPED;
+            ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
         }
         if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
             ai.enabled = true;
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 254f652..04f6377 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -711,6 +711,7 @@
             throw new IllegalArgumentException("sql must not be null.");
         }
 
+        int changedRows = 0;
         final int cookie = mRecentOperations.beginOperation("executeForChangedRowCount",
                 sql, bindArgs);
         try {
@@ -721,8 +722,9 @@
                 applyBlockGuardPolicy(statement);
                 attachCancellationSignal(cancellationSignal);
                 try {
-                    return nativeExecuteForChangedRowCount(
+                    changedRows = nativeExecuteForChangedRowCount(
                             mConnectionPtr, statement.mStatementPtr);
+                    return changedRows;
                 } finally {
                     detachCancellationSignal(cancellationSignal);
                 }
@@ -733,7 +735,9 @@
             mRecentOperations.failOperation(cookie, ex);
             throw ex;
         } finally {
-            mRecentOperations.endOperation(cookie);
+            if (mRecentOperations.endOperationDeferLog(cookie)) {
+                mRecentOperations.logOperation(cookie, "changedRows=" + changedRows);
+            }
         }
     }
 
diff --git a/core/java/android/hardware/LegacySensorManager.java b/core/java/android/hardware/LegacySensorManager.java
new file mode 100644
index 0000000..62c194f
--- /dev/null
+++ b/core/java/android/hardware/LegacySensorManager.java
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2012 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.hardware;
+
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.view.IRotationWatcher;
+import android.view.IWindowManager;
+import android.view.Surface;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Helper class for implementing the legacy sensor manager API.
+ * @hide
+ */
+@SuppressWarnings("deprecation")
+final class LegacySensorManager {
+    private static boolean sInitialized;
+    private static IWindowManager sWindowManager;
+    private static int sRotation = Surface.ROTATION_0;
+
+    private final SensorManager mSensorManager;
+
+    // List of legacy listeners.  Guarded by mLegacyListenersMap.
+    private final HashMap<SensorListener, LegacyListener> mLegacyListenersMap =
+            new HashMap<SensorListener, LegacyListener>();
+
+    public LegacySensorManager(SensorManager sensorManager) {
+        mSensorManager = sensorManager;
+
+        synchronized (SensorManager.class) {
+            if (!sInitialized) {
+                sWindowManager = IWindowManager.Stub.asInterface(
+                        ServiceManager.getService("window"));
+                if (sWindowManager != null) {
+                    // if it's null we're running in the system process
+                    // which won't get the rotated values
+                    try {
+                        sRotation = sWindowManager.watchRotation(
+                                new IRotationWatcher.Stub() {
+                                    public void onRotationChanged(int rotation) {
+                                        LegacySensorManager.onRotationChanged(rotation);
+                                    }
+                                }
+                        );
+                    } catch (RemoteException e) {
+                    }
+                }
+            }
+        }
+    }
+
+    public int getSensors() {
+        int result = 0;
+        final List<Sensor> fullList = mSensorManager.getFullSensorList();
+        for (Sensor i : fullList) {
+            switch (i.getType()) {
+                case Sensor.TYPE_ACCELEROMETER:
+                    result |= SensorManager.SENSOR_ACCELEROMETER;
+                    break;
+                case Sensor.TYPE_MAGNETIC_FIELD:
+                    result |= SensorManager.SENSOR_MAGNETIC_FIELD;
+                    break;
+                case Sensor.TYPE_ORIENTATION:
+                    result |= SensorManager.SENSOR_ORIENTATION
+                            | SensorManager.SENSOR_ORIENTATION_RAW;
+                    break;
+            }
+        }
+        return result;
+    }
+
+    public boolean registerListener(SensorListener listener, int sensors, int rate) {
+        if (listener == null) {
+            return false;
+        }
+        boolean result = false;
+        result = registerLegacyListener(SensorManager.SENSOR_ACCELEROMETER,
+                Sensor.TYPE_ACCELEROMETER, listener, sensors, rate) || result;
+        result = registerLegacyListener(SensorManager.SENSOR_MAGNETIC_FIELD,
+                Sensor.TYPE_MAGNETIC_FIELD, listener, sensors, rate) || result;
+        result = registerLegacyListener(SensorManager.SENSOR_ORIENTATION_RAW,
+                Sensor.TYPE_ORIENTATION, listener, sensors, rate) || result;
+        result = registerLegacyListener(SensorManager.SENSOR_ORIENTATION,
+                Sensor.TYPE_ORIENTATION, listener, sensors, rate) || result;
+        result = registerLegacyListener(SensorManager.SENSOR_TEMPERATURE,
+                Sensor.TYPE_TEMPERATURE, listener, sensors, rate) || result;
+        return result;
+    }
+
+    private boolean registerLegacyListener(int legacyType, int type,
+            SensorListener listener, int sensors, int rate) {
+        boolean result = false;
+        // Are we activating this legacy sensor?
+        if ((sensors & legacyType) != 0) {
+            // if so, find a suitable Sensor
+            Sensor sensor = mSensorManager.getDefaultSensor(type);
+            if (sensor != null) {
+                // We do all of this work holding the legacy listener lock to ensure
+                // that the invariants around listeners are maintained.  This is safe
+                // because neither registerLegacyListener nor unregisterLegacyListener
+                // are called reentrantly while sensors are being registered or unregistered.
+                synchronized (mLegacyListenersMap) {
+                    // If we don't already have one, create a LegacyListener
+                    // to wrap this listener and process the events as
+                    // they are expected by legacy apps.
+                    LegacyListener legacyListener = mLegacyListenersMap.get(listener);
+                    if (legacyListener == null) {
+                        // we didn't find a LegacyListener for this client,
+                        // create one, and put it in our list.
+                        legacyListener = new LegacyListener(listener);
+                        mLegacyListenersMap.put(listener, legacyListener);
+                    }
+
+                    // register this legacy sensor with this legacy listener
+                    if (legacyListener.registerSensor(legacyType)) {
+                        // and finally, register the legacy listener with the new apis
+                        result = mSensorManager.registerListener(legacyListener, sensor, rate);
+                    } else {
+                        result = true; // sensor already enabled
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    public void unregisterListener(SensorListener listener, int sensors) {
+        if (listener == null) {
+            return;
+        }
+        unregisterLegacyListener(SensorManager.SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
+                listener, sensors);
+        unregisterLegacyListener(SensorManager.SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD,
+                listener, sensors);
+        unregisterLegacyListener(SensorManager.SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION,
+                listener, sensors);
+        unregisterLegacyListener(SensorManager.SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION,
+                listener, sensors);
+        unregisterLegacyListener(SensorManager.SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
+                listener, sensors);
+    }
+
+    private void unregisterLegacyListener(int legacyType, int type,
+            SensorListener listener, int sensors) {
+        // Are we deactivating this legacy sensor?
+        if ((sensors & legacyType) != 0) {
+            // if so, find the corresponding Sensor
+            Sensor sensor = mSensorManager.getDefaultSensor(type);
+            if (sensor != null) {
+                // We do all of this work holding the legacy listener lock to ensure
+                // that the invariants around listeners are maintained.  This is safe
+                // because neither registerLegacyListener nor unregisterLegacyListener
+                // are called re-entrantly while sensors are being registered or unregistered.
+                synchronized (mLegacyListenersMap) {
+                    // do we know about this listener?
+                    LegacyListener legacyListener = mLegacyListenersMap.get(listener);
+                    if (legacyListener != null) {
+                        // unregister this legacy sensor and if we don't
+                        // need the corresponding Sensor, unregister it too
+                        if (legacyListener.unregisterSensor(legacyType)) {
+                            // corresponding sensor not needed, unregister
+                            mSensorManager.unregisterListener(legacyListener, sensor);
+
+                            // finally check if we still need the legacyListener
+                            // in our mapping, if not, get rid of it too.
+                            if (!legacyListener.hasSensors()) {
+                                mLegacyListenersMap.remove(listener);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    static void onRotationChanged(int rotation) {
+        synchronized (SensorManager.class) {
+            sRotation  = rotation;
+        }
+    }
+
+    static int getRotation() {
+        synchronized (SensorManager.class) {
+            return sRotation;
+        }
+    }
+
+    private static final class LegacyListener implements SensorEventListener {
+        private float mValues[] = new float[6];
+        private SensorListener mTarget;
+        private int mSensors;
+        private final LmsFilter mYawfilter = new LmsFilter();
+
+        LegacyListener(SensorListener target) {
+            mTarget = target;
+            mSensors = 0;
+        }
+
+        boolean registerSensor(int legacyType) {
+            if ((mSensors & legacyType) != 0) {
+                return false;
+            }
+            boolean alreadyHasOrientationSensor = hasOrientationSensor(mSensors);
+            mSensors |= legacyType;
+            if (alreadyHasOrientationSensor && hasOrientationSensor(legacyType)) {
+                return false; // don't need to re-register the orientation sensor
+            }
+            return true;
+        }
+
+        boolean unregisterSensor(int legacyType) {
+            if ((mSensors & legacyType) == 0) {
+                return false;
+            }
+            mSensors &= ~legacyType;
+            if (hasOrientationSensor(legacyType) && hasOrientationSensor(mSensors)) {
+                return false; // can't unregister the orientation sensor just yet
+            }
+            return true;
+        }
+
+        boolean hasSensors() {
+            return mSensors != 0;
+        }
+
+        private static boolean hasOrientationSensor(int sensors) {
+            return (sensors & (SensorManager.SENSOR_ORIENTATION
+                    | SensorManager.SENSOR_ORIENTATION_RAW)) != 0;
+        }
+
+        public void onAccuracyChanged(Sensor sensor, int accuracy) {
+            try {
+                mTarget.onAccuracyChanged(getLegacySensorType(sensor.getType()), accuracy);
+            } catch (AbstractMethodError e) {
+                // old app that doesn't implement this method
+                // just ignore it.
+            }
+        }
+
+        public void onSensorChanged(SensorEvent event) {
+            final float v[] = mValues;
+            v[0] = event.values[0];
+            v[1] = event.values[1];
+            v[2] = event.values[2];
+            int type = event.sensor.getType();
+            int legacyType = getLegacySensorType(type);
+            mapSensorDataToWindow(legacyType, v, LegacySensorManager.getRotation());
+            if (type == Sensor.TYPE_ORIENTATION) {
+                if ((mSensors & SensorManager.SENSOR_ORIENTATION_RAW)!=0) {
+                    mTarget.onSensorChanged(SensorManager.SENSOR_ORIENTATION_RAW, v);
+                }
+                if ((mSensors & SensorManager.SENSOR_ORIENTATION)!=0) {
+                    v[0] = mYawfilter.filter(event.timestamp, v[0]);
+                    mTarget.onSensorChanged(SensorManager.SENSOR_ORIENTATION, v);
+                }
+            } else {
+                mTarget.onSensorChanged(legacyType, v);
+            }
+        }
+
+        /*
+         * Helper function to convert the specified sensor's data to the windows's
+         * coordinate space from the device's coordinate space.
+         *
+         * output: 3,4,5: values in the old API format
+         *         0,1,2: transformed values in the old API format
+         *
+         */
+        private void mapSensorDataToWindow(int sensor,
+                float[] values, int orientation) {
+            float x = values[0];
+            float y = values[1];
+            float z = values[2];
+
+            switch (sensor) {
+                case SensorManager.SENSOR_ORIENTATION:
+                case SensorManager.SENSOR_ORIENTATION_RAW:
+                    z = -z;
+                    break;
+                case SensorManager.SENSOR_ACCELEROMETER:
+                    x = -x;
+                    y = -y;
+                    z = -z;
+                    break;
+                case SensorManager.SENSOR_MAGNETIC_FIELD:
+                    x = -x;
+                    y = -y;
+                    break;
+            }
+            values[0] = x;
+            values[1] = y;
+            values[2] = z;
+            values[3] = x;
+            values[4] = y;
+            values[5] = z;
+
+            if ((orientation & Surface.ROTATION_90) != 0) {
+                // handles 90 and 270 rotation
+                switch (sensor) {
+                    case SensorManager.SENSOR_ACCELEROMETER:
+                    case SensorManager.SENSOR_MAGNETIC_FIELD:
+                        values[0] =-y;
+                        values[1] = x;
+                        values[2] = z;
+                        break;
+                    case SensorManager.SENSOR_ORIENTATION:
+                    case SensorManager.SENSOR_ORIENTATION_RAW:
+                        values[0] = x + ((x < 270) ? 90 : -270);
+                        values[1] = z;
+                        values[2] = y;
+                        break;
+                }
+            }
+            if ((orientation & Surface.ROTATION_180) != 0) {
+                x = values[0];
+                y = values[1];
+                z = values[2];
+                // handles 180 (flip) and 270 (flip + 90) rotation
+                switch (sensor) {
+                    case SensorManager.SENSOR_ACCELEROMETER:
+                    case SensorManager.SENSOR_MAGNETIC_FIELD:
+                        values[0] =-x;
+                        values[1] =-y;
+                        values[2] = z;
+                        break;
+                    case SensorManager.SENSOR_ORIENTATION:
+                    case SensorManager.SENSOR_ORIENTATION_RAW:
+                        values[0] = (x >= 180) ? (x - 180) : (x + 180);
+                        values[1] =-y;
+                        values[2] =-z;
+                        break;
+                }
+            }
+        }
+
+        private static int getLegacySensorType(int type) {
+            switch (type) {
+                case Sensor.TYPE_ACCELEROMETER:
+                    return SensorManager.SENSOR_ACCELEROMETER;
+                case Sensor.TYPE_MAGNETIC_FIELD:
+                    return SensorManager.SENSOR_MAGNETIC_FIELD;
+                case Sensor.TYPE_ORIENTATION:
+                    return SensorManager.SENSOR_ORIENTATION_RAW;
+                case Sensor.TYPE_TEMPERATURE:
+                    return SensorManager.SENSOR_TEMPERATURE;
+            }
+            return 0;
+        }
+    }
+
+    private static final class LmsFilter {
+        private static final int SENSORS_RATE_MS = 20;
+        private static final int COUNT = 12;
+        private static final float PREDICTION_RATIO = 1.0f/3.0f;
+        private static final float PREDICTION_TIME = (SENSORS_RATE_MS*COUNT/1000.0f)*PREDICTION_RATIO;
+        private float mV[] = new float[COUNT*2];
+        private float mT[] = new float[COUNT*2];
+        private int mIndex;
+
+        public LmsFilter() {
+            mIndex = COUNT;
+        }
+
+        public float filter(long time, float in) {
+            float v = in;
+            final float ns = 1.0f / 1000000000.0f;
+            final float t = time*ns;
+            float v1 = mV[mIndex];
+            if ((v-v1) > 180) {
+                v -= 360;
+            } else if ((v1-v) > 180) {
+                v += 360;
+            }
+            /* Manage the circular buffer, we write the data twice spaced
+             * by COUNT values, so that we don't have to copy the array
+             * when it's full
+             */
+            mIndex++;
+            if (mIndex >= COUNT*2)
+                mIndex = COUNT;
+            mV[mIndex] = v;
+            mT[mIndex] = t;
+            mV[mIndex-COUNT] = v;
+            mT[mIndex-COUNT] = t;
+
+            float A, B, C, D, E;
+            float a, b;
+            int i;
+
+            A = B = C = D = E = 0;
+            for (i=0 ; i<COUNT-1 ; i++) {
+                final int j = mIndex - 1 - i;
+                final float Z = mV[j];
+                final float T = 0.5f*(mT[j] + mT[j+1]) - t;
+                float dT = mT[j] - mT[j+1];
+                dT *= dT;
+                A += Z*dT;
+                B += T*(T*dT);
+                C +=   (T*dT);
+                D += Z*(T*dT);
+                E += dT;
+            }
+            b = (A*B + C*D) / (E*B + C*C);
+            a = (E*b - A) / C;
+            float f = b + PREDICTION_TIME*a;
+
+            // Normalize
+            f *= (1.0f / 360.0f);
+            if (((f>=0)?f:-f) >= 0.5f)
+                f = f - (float)Math.ceil(f + 0.5f) + 1.0f;
+            if (f < 0)
+                f += 1.0f;
+            f *= 360.0f;
+            return f;
+        }
+    }
+}
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 63fb32d..3c70dc6 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -131,7 +131,6 @@
     private float   mResolution;
     private float   mPower;
     private int     mMinDelay;
-    private int     mLegacyType;
 
 
     Sensor() {
@@ -203,12 +202,4 @@
         mMaxRange = max;
         mResolution = res;
     }
-
-    void setLegacyType(int legacyType) {
-        mLegacyType = legacyType;
-    }
-
-    int getLegacyType() {
-        return mLegacyType;
-    }
 }
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 3fdf246..aeb46cf 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -16,23 +16,12 @@
 
 package android.hardware;
 
-import android.os.Looper;
-import android.os.Process;
-import android.os.RemoteException;
 import android.os.Handler;
-import android.os.Message;
-import android.os.ServiceManager;
 import android.util.Log;
 import android.util.SparseArray;
-import android.util.SparseBooleanArray;
-import android.util.SparseIntArray;
-import android.view.IRotationWatcher;
-import android.view.IWindowManager;
-import android.view.Surface;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 
 /**
@@ -83,11 +72,19 @@
  * @see Sensor
  *
  */
-public class SensorManager
-{
-    private static final String TAG = "SensorManager";
+public abstract class SensorManager {
+    /** @hide */
+    protected static final String TAG = "SensorManager";
+
     private static final float[] mTempMatrix = new float[16];
 
+    // Cached lists of sensors by type.  Guarded by mSensorListByType.
+    private final SparseArray<List<Sensor>> mSensorListByType =
+            new SparseArray<List<Sensor>>();
+
+    // Legacy sensor manager implementation.  Guarded by mSensorListByType during initialization.
+    private LegacySensorManager mLegacySensorManager;
+
     /* NOTE: sensor IDs must be a power of 2 */
 
     /**
@@ -353,340 +350,18 @@
     /** see {@link #remapCoordinateSystem} */
     public static final int AXIS_MINUS_Z = AXIS_Z | 0x80;
 
-    /*-----------------------------------------------------------------------*/
-
-    Looper mMainLooper;
-    @SuppressWarnings("deprecation")
-    private HashMap<SensorListener, LegacyListener> mLegacyListenersMap =
-        new HashMap<SensorListener, LegacyListener>();
-
-    /*-----------------------------------------------------------------------*/
-
-    private static final int SENSOR_DISABLE = -1;
-    private static boolean sSensorModuleInitialized = false;
-    private static ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>();
-    private static SparseArray<List<Sensor>> sSensorListByType = new SparseArray<List<Sensor>>();
-    private static IWindowManager sWindowManager;
-    private static int sRotation = Surface.ROTATION_0;
-    /* The thread and the sensor list are global to the process
-     * but the actual thread is spawned on demand */
-    private static SensorThread sSensorThread;
-    private static int sQueue;
-
-    // Used within this module from outside SensorManager, don't make private
-    static SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
-    static final ArrayList<ListenerDelegate> sListeners =
-        new ArrayList<ListenerDelegate>();
-
-    /*-----------------------------------------------------------------------*/
-
-    private class SensorEventPool {
-        private final int mPoolSize;
-        private final SensorEvent mPool[];
-        private int mNumItemsInPool;
-
-        private SensorEvent createSensorEvent() {
-            // maximal size for all legacy events is 3
-            return new SensorEvent(3);
-        }
-
-        SensorEventPool(int poolSize) {
-            mPoolSize = poolSize;
-            mNumItemsInPool = poolSize;
-            mPool = new SensorEvent[poolSize];
-        }
-
-        SensorEvent getFromPool() {
-            SensorEvent t = null;
-            synchronized (this) {
-                if (mNumItemsInPool > 0) {
-                    // remove the "top" item from the pool
-                    final int index = mPoolSize - mNumItemsInPool;
-                    t = mPool[index];
-                    mPool[index] = null;
-                    mNumItemsInPool--;
-                }
-            }
-            if (t == null) {
-                // the pool was empty or this item was removed from the pool for
-                // the first time. In any case, we need to create a new item.
-                t = createSensorEvent();
-            }
-            return t;
-        }
-
-        void returnToPool(SensorEvent t) {
-            synchronized (this) {
-                // is there space left in the pool?
-                if (mNumItemsInPool < mPoolSize) {
-                    // if so, return the item to the pool
-                    mNumItemsInPool++;
-                    final int index = mPoolSize - mNumItemsInPool;
-                    mPool[index] = t;
-                }
-            }
-        }
-    }
-
-    private static SensorEventPool sPool;
-
-    /*-----------------------------------------------------------------------*/
-
-    static private class SensorThread {
-
-        Thread mThread;
-        boolean mSensorsReady;
-
-        SensorThread() {
-        }
-
-        @Override
-        protected void finalize() {
-        }
-
-        // must be called with sListeners lock
-        boolean startLocked() {
-            try {
-                if (mThread == null) {
-                    mSensorsReady = false;
-                    SensorThreadRunnable runnable = new SensorThreadRunnable();
-                    Thread thread = new Thread(runnable, SensorThread.class.getName());
-                    thread.start();
-                    synchronized (runnable) {
-                        while (mSensorsReady == false) {
-                            runnable.wait();
-                        }
-                    }
-                    mThread = thread;
-                }
-            } catch (InterruptedException e) {
-            }
-            return mThread == null ? false : true;
-        }
-
-        private class SensorThreadRunnable implements Runnable {
-            SensorThreadRunnable() {
-            }
-
-            private boolean open() {
-                // NOTE: this cannot synchronize on sListeners, since
-                // it's held in the main thread at least until we
-                // return from here.
-                sQueue = sensors_create_queue();
-                return true;
-            }
-
-            public void run() {
-                //Log.d(TAG, "entering main sensor thread");
-                final float[] values = new float[3];
-                final int[] status = new int[1];
-                final long timestamp[] = new long[1];
-                Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
-
-                if (!open()) {
-                    return;
-                }
-
-                synchronized (this) {
-                    // we've open the driver, we're ready to open the sensors
-                    mSensorsReady = true;
-                    this.notify();
-                }
-
-                while (true) {
-                    // wait for an event
-                    final int sensor = sensors_data_poll(sQueue, values, status, timestamp);
-
-                    int accuracy = status[0];
-                    synchronized (sListeners) {
-                        if (sensor == -1 || sListeners.isEmpty()) {
-                            // we lost the connection to the event stream. this happens
-                            // when the last listener is removed or if there is an error
-                            if (sensor == -1 && !sListeners.isEmpty()) {
-                                // log a warning in case of abnormal termination
-                                Log.e(TAG, "_sensors_data_poll() failed, we bail out: sensors=" + sensor);
-                            }
-                            // we have no more listeners or polling failed, terminate the thread
-                            sensors_destroy_queue(sQueue);
-                            sQueue = 0;
-                            mThread = null;
-                            break;
-                        }
-                        final Sensor sensorObject = sHandleToSensor.get(sensor);
-                        if (sensorObject != null) {
-                            // report the sensor event to all listeners that
-                            // care about it.
-                            final int size = sListeners.size();
-                            for (int i=0 ; i<size ; i++) {
-                                ListenerDelegate listener = sListeners.get(i);
-                                if (listener.hasSensor(sensorObject)) {
-                                    // this is asynchronous (okay to call
-                                    // with sListeners lock held).
-                                    listener.onSensorChangedLocked(sensorObject,
-                                            values, timestamp, accuracy);
-                                }
-                            }
-                        }
-                    }
-                }
-                //Log.d(TAG, "exiting main sensor thread");
-            }
-        }
-    }
-
-    /*-----------------------------------------------------------------------*/
-
-    private class ListenerDelegate {
-        private final SensorEventListener mSensorEventListener;
-        private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>();
-        private final Handler mHandler;
-        public SparseBooleanArray mSensors = new SparseBooleanArray();
-        public SparseBooleanArray mFirstEvent = new SparseBooleanArray();
-        public SparseIntArray mSensorAccuracies = new SparseIntArray();
-
-        ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler) {
-            mSensorEventListener = listener;
-            Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
-            // currently we create one Handler instance per listener, but we could
-            // have one per looper (we'd need to pass the ListenerDelegate
-            // instance to handleMessage and keep track of them separately).
-            mHandler = new Handler(looper) {
-                @Override
-                public void handleMessage(Message msg) {
-                    final SensorEvent t = (SensorEvent)msg.obj;
-                    final int handle = t.sensor.getHandle();
-
-                    switch (t.sensor.getType()) {
-                        // Only report accuracy for sensors that support it.
-                        case Sensor.TYPE_MAGNETIC_FIELD:
-                        case Sensor.TYPE_ORIENTATION:
-                            // call onAccuracyChanged() only if the value changes
-                            final int accuracy = mSensorAccuracies.get(handle);
-                            if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
-                                mSensorAccuracies.put(handle, t.accuracy);
-                                mSensorEventListener.onAccuracyChanged(t.sensor, t.accuracy);
-                            }
-                            break;
-                        default:
-                            // For other sensors, just report the accuracy once
-                            if (mFirstEvent.get(handle) == false) {
-                                mFirstEvent.put(handle, true);
-                                mSensorEventListener.onAccuracyChanged(
-                                        t.sensor, SENSOR_STATUS_ACCURACY_HIGH);
-                            }
-                            break;
-                    }
-
-                    mSensorEventListener.onSensorChanged(t);
-                    sPool.returnToPool(t);
-                }
-            };
-            addSensor(sensor);
-        }
-
-        Object getListener() {
-            return mSensorEventListener;
-        }
-
-        void addSensor(Sensor sensor) {
-            mSensors.put(sensor.getHandle(), true);
-            mSensorList.add(sensor);
-        }
-        int removeSensor(Sensor sensor) {
-            mSensors.delete(sensor.getHandle());
-            mSensorList.remove(sensor);
-            return mSensors.size();
-        }
-        boolean hasSensor(Sensor sensor) {
-            return mSensors.get(sensor.getHandle());
-        }
-        List<Sensor> getSensors() {
-            return mSensorList;
-        }
-
-        void onSensorChangedLocked(Sensor sensor, float[] values, long[] timestamp, int accuracy) {
-            SensorEvent t = sPool.getFromPool();
-            final float[] v = t.values;
-            v[0] = values[0];
-            v[1] = values[1];
-            v[2] = values[2];
-            t.timestamp = timestamp[0];
-            t.accuracy = accuracy;
-            t.sensor = sensor;
-            Message msg = Message.obtain();
-            msg.what = 0;
-            msg.obj = t;
-            msg.setAsynchronous(true);
-            mHandler.sendMessage(msg);
-        }
-    }
 
     /**
      * {@hide}
      */
-    public SensorManager(Looper mainLooper) {
-        mMainLooper = mainLooper;
-
-
-        synchronized(sListeners) {
-            if (!sSensorModuleInitialized) {
-                sSensorModuleInitialized = true;
-
-                nativeClassInit();
-
-                sWindowManager = IWindowManager.Stub.asInterface(
-                        ServiceManager.getService("window"));
-                if (sWindowManager != null) {
-                    // if it's null we're running in the system process
-                    // which won't get the rotated values
-                    try {
-                        sRotation = sWindowManager.watchRotation(
-                                new IRotationWatcher.Stub() {
-                                    public void onRotationChanged(int rotation) {
-                                        SensorManager.this.onRotationChanged(rotation);
-                                    }
-                                }
-                        );
-                    } catch (RemoteException e) {
-                    }
-                }
-
-                // initialize the sensor list
-                sensors_module_init();
-                final ArrayList<Sensor> fullList = sFullSensorsList;
-                int i = 0;
-                do {
-                    Sensor sensor = new Sensor();
-                    i = sensors_module_get_next_sensor(sensor, i);
-
-                    if (i>=0) {
-                        //Log.d(TAG, "found sensor: " + sensor.getName() +
-                        //        ", handle=" + sensor.getHandle());
-                        sensor.setLegacyType(getLegacySensorType(sensor.getType()));
-                        fullList.add(sensor);
-                        sHandleToSensor.append(sensor.getHandle(), sensor);
-                    }
-                } while (i>0);
-
-                sPool = new SensorEventPool( sFullSensorsList.size()*2 );
-                sSensorThread = new SensorThread();
-            }
-        }
+    public SensorManager() {
     }
 
-    private int getLegacySensorType(int type) {
-        switch (type) {
-            case Sensor.TYPE_ACCELEROMETER:
-                return SENSOR_ACCELEROMETER;
-            case Sensor.TYPE_MAGNETIC_FIELD:
-                return SENSOR_MAGNETIC_FIELD;
-            case Sensor.TYPE_ORIENTATION:
-                return SENSOR_ORIENTATION_RAW;
-            case Sensor.TYPE_TEMPERATURE:
-                return SENSOR_TEMPERATURE;
-        }
-        return 0;
-    }
+    /**
+     * Gets the full list of sensors that are available.
+     * @hide
+     */
+    protected abstract List<Sensor> getFullSensorList();
 
     /**
      * @return available sensors.
@@ -695,23 +370,7 @@
      */
     @Deprecated
     public int getSensors() {
-        int result = 0;
-        final ArrayList<Sensor> fullList = sFullSensorsList;
-        for (Sensor i : fullList) {
-            switch (i.getType()) {
-                case Sensor.TYPE_ACCELEROMETER:
-                    result |= SensorManager.SENSOR_ACCELEROMETER;
-                    break;
-                case Sensor.TYPE_MAGNETIC_FIELD:
-                    result |= SensorManager.SENSOR_MAGNETIC_FIELD;
-                    break;
-                case Sensor.TYPE_ORIENTATION:
-                    result |= SensorManager.SENSOR_ORIENTATION |
-                    SensorManager.SENSOR_ORIENTATION_RAW;
-                    break;
-            }
-        }
-        return result;
+        return getLegacySensorManager().getSensors();
     }
 
     /**
@@ -731,9 +390,9 @@
     public List<Sensor> getSensorList(int type) {
         // cache the returned lists the first time
         List<Sensor> list;
-        final ArrayList<Sensor> fullList = sFullSensorsList;
-        synchronized(fullList) {
-            list = sSensorListByType.get(type);
+        final List<Sensor> fullList = getFullSensorList();
+        synchronized (mSensorListByType) {
+            list = mSensorListByType.get(type);
             if (list == null) {
                 if (type == Sensor.TYPE_ALL) {
                     list = fullList;
@@ -745,7 +404,7 @@
                     }
                 }
                 list = Collections.unmodifiableList(list);
-                sSensorListByType.append(type, list);
+                mSensorListByType.append(type, list);
             }
         }
         return list;
@@ -817,128 +476,7 @@
      */
     @Deprecated
     public boolean registerListener(SensorListener listener, int sensors, int rate) {
-        if (listener == null) {
-            return false;
-        }
-        boolean result = false;
-        result = registerLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
-                listener, sensors, rate) || result;
-        result = registerLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD,
-                listener, sensors, rate) || result;
-        result = registerLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION,
-                listener, sensors, rate) || result;
-        result = registerLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION,
-                listener, sensors, rate) || result;
-        result = registerLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
-                listener, sensors, rate) || result;
-        return result;
-    }
-
-    @SuppressWarnings("deprecation")
-    private boolean registerLegacyListener(int legacyType, int type,
-            SensorListener listener, int sensors, int rate)
-    {
-        if (listener == null) {
-            return false;
-        }
-        boolean result = false;
-        // Are we activating this legacy sensor?
-        if ((sensors & legacyType) != 0) {
-            // if so, find a suitable Sensor
-            Sensor sensor = getDefaultSensor(type);
-            if (sensor != null) {
-                // If we don't already have one, create a LegacyListener
-                // to wrap this listener and process the events as
-                // they are expected by legacy apps.
-                LegacyListener legacyListener = null;
-                synchronized (mLegacyListenersMap) {
-                    legacyListener = mLegacyListenersMap.get(listener);
-                    if (legacyListener == null) {
-                        // we didn't find a LegacyListener for this client,
-                        // create one, and put it in our list.
-                        legacyListener = new LegacyListener(listener);
-                        mLegacyListenersMap.put(listener, legacyListener);
-                    }
-                }
-                // register this legacy sensor with this legacy listener
-                legacyListener.registerSensor(legacyType);
-                // and finally, register the legacy listener with the new apis
-                result = registerListener(legacyListener, sensor, rate);
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Unregisters a listener for the sensors with which it is registered.
-     *
-     * @deprecated This method is deprecated, use
-     *             {@link SensorManager#unregisterListener(SensorEventListener, Sensor)}
-     *             instead.
-     *
-     * @param listener
-     *        a SensorListener object
-     *
-     * @param sensors
-     *        a bit masks of the sensors to unregister from
-     */
-    @Deprecated
-    public void unregisterListener(SensorListener listener, int sensors) {
-        unregisterLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
-                listener, sensors);
-        unregisterLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD,
-                listener, sensors);
-        unregisterLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION,
-                listener, sensors);
-        unregisterLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION,
-                listener, sensors);
-        unregisterLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
-                listener, sensors);
-    }
-
-    @SuppressWarnings("deprecation")
-    private void unregisterLegacyListener(int legacyType, int type,
-            SensorListener listener, int sensors)
-    {
-        if (listener == null) {
-            return;
-        }
-        // do we know about this listener?
-        LegacyListener legacyListener = null;
-        synchronized (mLegacyListenersMap) {
-            legacyListener = mLegacyListenersMap.get(listener);
-        }
-        if (legacyListener != null) {
-            // Are we deactivating this legacy sensor?
-            if ((sensors & legacyType) != 0) {
-                // if so, find the corresponding Sensor
-                Sensor sensor = getDefaultSensor(type);
-                if (sensor != null) {
-                    // unregister this legacy sensor and if we don't
-                    // need the corresponding Sensor, unregister it too
-                    if (legacyListener.unregisterSensor(legacyType)) {
-                        // corresponding sensor not needed, unregister
-                        unregisterListener(legacyListener, sensor);
-                        // finally check if we still need the legacyListener
-                        // in our mapping, if not, get rid of it too.
-                        synchronized(sListeners) {
-                            boolean found = false;
-                            for (ListenerDelegate i : sListeners) {
-                                if (i.getListener() == legacyListener) {
-                                    found = true;
-                                    break;
-                                }
-                            }
-                            if (!found) {
-                                synchronized (mLegacyListenersMap) {
-                                    mLegacyListenersMap.remove(listener);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
+        return getLegacySensorManager().registerListener(listener, sensors, rate);
     }
 
     /**
@@ -959,6 +497,24 @@
     /**
      * Unregisters a listener for the sensors with which it is registered.
      *
+     * @deprecated This method is deprecated, use
+     *             {@link SensorManager#unregisterListener(SensorEventListener, Sensor)}
+     *             instead.
+     *
+     * @param listener
+     *        a SensorListener object
+     *
+     * @param sensors
+     *        a bit masks of the sensors to unregister from
+     */
+    @Deprecated
+    public void unregisterListener(SensorListener listener, int sensors) {
+        getLegacySensorManager().unregisterListener(listener, sensors);
+    }
+
+    /**
+     * Unregisters a listener for the sensors with which it is registered.
+     *
      * @param listener
      *        a SensorEventListener object
      *
@@ -970,7 +526,11 @@
      *
      */
     public void unregisterListener(SensorEventListener listener, Sensor sensor) {
-        unregisterListener((Object)listener, sensor);
+        if (listener == null || sensor == null) {
+            return;
+        }
+
+        unregisterListenerImpl(listener, sensor);
     }
 
     /**
@@ -984,9 +544,16 @@
      *
      */
     public void unregisterListener(SensorEventListener listener) {
-        unregisterListener((Object)listener);
+        if (listener == null) {
+            return;
+        }
+
+        unregisterListenerImpl(listener, null);
     }
 
+    /** @hide */
+    protected abstract void unregisterListenerImpl(SensorEventListener listener, Sensor sensor);
+
     /**
      * Registers a {@link android.hardware.SensorEventListener
      * SensorEventListener} for the given sensor.
@@ -1019,31 +586,6 @@
         return registerListener(listener, sensor, rate, null);
     }
 
-    private boolean enableSensorLocked(Sensor sensor, int delay) {
-        boolean result = false;
-        for (ListenerDelegate i : sListeners) {
-            if (i.hasSensor(sensor)) {
-                String name = sensor.getName();
-                int handle = sensor.getHandle();
-                result = sensors_enable_sensor(sQueue, name, handle, delay);
-                break;
-            }
-        }
-        return result;
-    }
-
-    private boolean disableSensorLocked(Sensor sensor) {
-        for (ListenerDelegate i : sListeners) {
-            if (i.hasSensor(sensor)) {
-                // not an error, it's just that this sensor is still in use
-                return true;
-            }
-        }
-        String name = sensor.getName();
-        int handle = sensor.getHandle();
-        return sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE);
-    }
-
     /**
      * Registers a {@link android.hardware.SensorEventListener
      * SensorEventListener} for the given sensor.
@@ -1081,7 +623,7 @@
         if (listener == null || sensor == null) {
             return false;
         }
-        boolean result = true;
+
         int delay = -1;
         switch (rate) {
             case SENSOR_DELAY_FASTEST:
@@ -1101,92 +643,12 @@
                 break;
         }
 
-        synchronized (sListeners) {
-            // look for this listener in our list
-            ListenerDelegate l = null;
-            for (ListenerDelegate i : sListeners) {
-                if (i.getListener() == listener) {
-                    l = i;
-                    break;
-                }
-            }
-
-            // if we don't find it, add it to the list
-            if (l == null) {
-                l = new ListenerDelegate(listener, sensor, handler);
-                sListeners.add(l);
-                // if the list is not empty, start our main thread
-                if (!sListeners.isEmpty()) {
-                    if (sSensorThread.startLocked()) {
-                        if (!enableSensorLocked(sensor, delay)) {
-                            // oops. there was an error
-                            sListeners.remove(l);
-                            result = false;
-                        }
-                    } else {
-                        // there was an error, remove the listener
-                        sListeners.remove(l);
-                        result = false;
-                    }
-                } else {
-                    // weird, we couldn't add the listener
-                    result = false;
-                }
-            } else {
-                l.addSensor(sensor);
-                if (!enableSensorLocked(sensor, delay)) {
-                    // oops. there was an error
-                    l.removeSensor(sensor);
-                    result = false;
-                }
-            }
-        }
-
-        return result;
+        return registerListenerImpl(listener, sensor, delay, handler);
     }
 
-    private void unregisterListener(Object listener, Sensor sensor) {
-        if (listener == null || sensor == null) {
-            return;
-        }
-
-        synchronized (sListeners) {
-            final int size = sListeners.size();
-            for (int i=0 ; i<size ; i++) {
-                ListenerDelegate l = sListeners.get(i);
-                if (l.getListener() == listener) {
-                    if (l.removeSensor(sensor) == 0) {
-                        // if we have no more sensors enabled on this listener,
-                        // take it off the list.
-                        sListeners.remove(i);
-                    }
-                    break;
-                }
-            }
-            disableSensorLocked(sensor);
-        }
-    }
-
-    private void unregisterListener(Object listener) {
-        if (listener == null) {
-            return;
-        }
-
-        synchronized (sListeners) {
-            final int size = sListeners.size();
-            for (int i=0 ; i<size ; i++) {
-                ListenerDelegate l = sListeners.get(i);
-                if (l.getListener() == listener) {
-                    sListeners.remove(i);
-                    // disable all sensors for this listener
-                    for (Sensor sensor : l.getSensors()) {
-                        disableSensorLocked(sensor);
-                    }
-                    break;
-                }
-            }
-        }
-    }
+    /** @hide */
+    protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
+            int delay, Handler handler);
 
     /**
      * <p>
@@ -1653,228 +1115,11 @@
      * @param p atmospheric pressure
      * @return Altitude in meters
      */
-   public static float getAltitude(float p0, float p) {
+    public static float getAltitude(float p0, float p) {
         final float coef = 1.0f / 5.255f;
         return 44330.0f * (1.0f - (float)Math.pow(p/p0, coef));
     }
 
-
-   /**
-     * {@hide}
-     */
-    public void onRotationChanged(int rotation) {
-        synchronized(sListeners) {
-            sRotation  = rotation;
-        }
-    }
-
-    static int getRotation() {
-        synchronized(sListeners) {
-            return sRotation;
-        }
-    }
-
-    private class LegacyListener implements SensorEventListener {
-        private float mValues[] = new float[6];
-        @SuppressWarnings("deprecation")
-        private SensorListener mTarget;
-        private int mSensors;
-        private final LmsFilter mYawfilter = new LmsFilter();
-
-        @SuppressWarnings("deprecation")
-        LegacyListener(SensorListener target) {
-            mTarget = target;
-            mSensors = 0;
-        }
-
-        void registerSensor(int legacyType) {
-            mSensors |= legacyType;
-        }
-
-        boolean unregisterSensor(int legacyType) {
-            mSensors &= ~legacyType;
-            int mask = SENSOR_ORIENTATION|SENSOR_ORIENTATION_RAW;
-            if (((legacyType&mask)!=0) && ((mSensors&mask)!=0)) {
-                return false;
-            }
-            return true;
-        }
-
-        @SuppressWarnings("deprecation")
-        public void onAccuracyChanged(Sensor sensor, int accuracy) {
-            try {
-                mTarget.onAccuracyChanged(sensor.getLegacyType(), accuracy);
-            } catch (AbstractMethodError e) {
-                // old app that doesn't implement this method
-                // just ignore it.
-            }
-        }
-
-        @SuppressWarnings("deprecation")
-        public void onSensorChanged(SensorEvent event) {
-            final float v[] = mValues;
-            v[0] = event.values[0];
-            v[1] = event.values[1];
-            v[2] = event.values[2];
-            int legacyType = event.sensor.getLegacyType();
-            mapSensorDataToWindow(legacyType, v, SensorManager.getRotation());
-            if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
-                if ((mSensors & SENSOR_ORIENTATION_RAW)!=0) {
-                    mTarget.onSensorChanged(SENSOR_ORIENTATION_RAW, v);
-                }
-                if ((mSensors & SENSOR_ORIENTATION)!=0) {
-                    v[0] = mYawfilter.filter(event.timestamp, v[0]);
-                    mTarget.onSensorChanged(SENSOR_ORIENTATION, v);
-                }
-            } else {
-                mTarget.onSensorChanged(legacyType, v);
-            }
-        }
-
-        /*
-         * Helper function to convert the specified sensor's data to the windows's
-         * coordinate space from the device's coordinate space.
-         *
-         * output: 3,4,5: values in the old API format
-         *         0,1,2: transformed values in the old API format
-         *
-         */
-        private void mapSensorDataToWindow(int sensor,
-                float[] values, int orientation) {
-            float x = values[0];
-            float y = values[1];
-            float z = values[2];
-
-            switch (sensor) {
-                case SensorManager.SENSOR_ORIENTATION:
-                case SensorManager.SENSOR_ORIENTATION_RAW:
-                    z = -z;
-                    break;
-                case SensorManager.SENSOR_ACCELEROMETER:
-                    x = -x;
-                    y = -y;
-                    z = -z;
-                    break;
-                case SensorManager.SENSOR_MAGNETIC_FIELD:
-                    x = -x;
-                    y = -y;
-                    break;
-            }
-            values[0] = x;
-            values[1] = y;
-            values[2] = z;
-            values[3] = x;
-            values[4] = y;
-            values[5] = z;
-
-            if ((orientation & Surface.ROTATION_90) != 0) {
-                // handles 90 and 270 rotation
-                switch (sensor) {
-                    case SENSOR_ACCELEROMETER:
-                    case SENSOR_MAGNETIC_FIELD:
-                        values[0] =-y;
-                        values[1] = x;
-                        values[2] = z;
-                        break;
-                    case SENSOR_ORIENTATION:
-                    case SENSOR_ORIENTATION_RAW:
-                        values[0] = x + ((x < 270) ? 90 : -270);
-                        values[1] = z;
-                        values[2] = y;
-                        break;
-                }
-            }
-            if ((orientation & Surface.ROTATION_180) != 0) {
-                x = values[0];
-                y = values[1];
-                z = values[2];
-                // handles 180 (flip) and 270 (flip + 90) rotation
-                switch (sensor) {
-                    case SENSOR_ACCELEROMETER:
-                    case SENSOR_MAGNETIC_FIELD:
-                        values[0] =-x;
-                        values[1] =-y;
-                        values[2] = z;
-                        break;
-                    case SENSOR_ORIENTATION:
-                    case SENSOR_ORIENTATION_RAW:
-                        values[0] = (x >= 180) ? (x - 180) : (x + 180);
-                        values[1] =-y;
-                        values[2] =-z;
-                        break;
-                }
-            }
-        }
-    }
-
-    class LmsFilter {
-        private static final int SENSORS_RATE_MS = 20;
-        private static final int COUNT = 12;
-        private static final float PREDICTION_RATIO = 1.0f/3.0f;
-        private static final float PREDICTION_TIME = (SENSORS_RATE_MS*COUNT/1000.0f)*PREDICTION_RATIO;
-        private float mV[] = new float[COUNT*2];
-        private float mT[] = new float[COUNT*2];
-        private int mIndex;
-
-        public LmsFilter() {
-            mIndex = COUNT;
-        }
-
-        public float filter(long time, float in) {
-            float v = in;
-            final float ns = 1.0f / 1000000000.0f;
-            final float t = time*ns;
-            float v1 = mV[mIndex];
-            if ((v-v1) > 180) {
-                v -= 360;
-            } else if ((v1-v) > 180) {
-                v += 360;
-            }
-            /* Manage the circular buffer, we write the data twice spaced
-             * by COUNT values, so that we don't have to copy the array
-             * when it's full
-             */
-            mIndex++;
-            if (mIndex >= COUNT*2)
-                mIndex = COUNT;
-            mV[mIndex] = v;
-            mT[mIndex] = t;
-            mV[mIndex-COUNT] = v;
-            mT[mIndex-COUNT] = t;
-
-            float A, B, C, D, E;
-            float a, b;
-            int i;
-
-            A = B = C = D = E = 0;
-            for (i=0 ; i<COUNT-1 ; i++) {
-                final int j = mIndex - 1 - i;
-                final float Z = mV[j];
-                final float T = 0.5f*(mT[j] + mT[j+1]) - t;
-                float dT = mT[j] - mT[j+1];
-                dT *= dT;
-                A += Z*dT;
-                B += T*(T*dT);
-                C +=   (T*dT);
-                D += Z*(T*dT);
-                E += dT;
-            }
-            b = (A*B + C*D) / (E*B + C*C);
-            a = (E*b - A) / C;
-            float f = b + PREDICTION_TIME*a;
-
-            // Normalize
-            f *= (1.0f / 360.0f);
-            if (((f>=0)?f:-f) >= 0.5f)
-                f = f - (float)Math.ceil(f + 0.5f) + 1.0f;
-            if (f < 0)
-                f += 1.0f;
-            f *= 360.0f;
-            return f;
-        }
-    }
-
-
     /** Helper function to compute the angle change between two rotation matrices.
      *  Given a current rotation matrix (R) and a previous rotation matrix
      *  (prevR) computes the rotation around the x,y, and z axes which
@@ -2060,14 +1305,66 @@
         Q[3] = rv[2];
     }
 
-    private static native void nativeClassInit();
+    private LegacySensorManager getLegacySensorManager() {
+        synchronized (mSensorListByType) {
+            if (mLegacySensorManager == null) {
+                Log.i(TAG, "This application is using deprecated SensorManager API which will "
+                        + "be removed someday.  Please consider switching to the new API.");
+                mLegacySensorManager = new LegacySensorManager(this);
+            }
+            return mLegacySensorManager;
+        }
+    }
 
-    private static native int sensors_module_init();
-    private static native int sensors_module_get_next_sensor(Sensor sensor, int next);
+    /**
+     * Sensor event pool implementation.
+     * @hide
+     */
+    protected static final class SensorEventPool {
+        private final int mPoolSize;
+        private final SensorEvent mPool[];
+        private int mNumItemsInPool;
 
-    // Used within this module from outside SensorManager, don't make private
-    static native int sensors_create_queue();
-    static native void sensors_destroy_queue(int queue);
-    static native boolean sensors_enable_sensor(int queue, String name, int sensor, int enable);
-    static native int sensors_data_poll(int queue, float[] values, int[] status, long[] timestamp);
+        private SensorEvent createSensorEvent() {
+            // maximal size for all legacy events is 3
+            return new SensorEvent(3);
+        }
+
+        SensorEventPool(int poolSize) {
+            mPoolSize = poolSize;
+            mNumItemsInPool = poolSize;
+            mPool = new SensorEvent[poolSize];
+        }
+
+        SensorEvent getFromPool() {
+            SensorEvent t = null;
+            synchronized (this) {
+                if (mNumItemsInPool > 0) {
+                    // remove the "top" item from the pool
+                    final int index = mPoolSize - mNumItemsInPool;
+                    t = mPool[index];
+                    mPool[index] = null;
+                    mNumItemsInPool--;
+                }
+            }
+            if (t == null) {
+                // the pool was empty or this item was removed from the pool for
+                // the first time. In any case, we need to create a new item.
+                t = createSensorEvent();
+            }
+            return t;
+        }
+
+        void returnToPool(SensorEvent t) {
+            synchronized (this) {
+                // is there space left in the pool?
+                if (mNumItemsInPool < mPoolSize) {
+                    // if so, return the item to the pool
+                    mNumItemsInPool++;
+                    final int index = mPoolSize - mNumItemsInPool;
+                    mPool[index] = t;
+                }
+            }
+        }
+    }
 }
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
new file mode 100644
index 0000000..0204e94
--- /dev/null
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2012 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.hardware;
+
+import android.os.Looper;
+import android.os.Process;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.util.SparseArray;
+import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Sensor manager implementation that communicates with the built-in
+ * system sensors.
+ *
+ * @hide
+ */
+public class SystemSensorManager extends SensorManager {
+    private static final int SENSOR_DISABLE = -1;
+    private static boolean sSensorModuleInitialized = false;
+    private static ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>();
+    /* The thread and the sensor list are global to the process
+     * but the actual thread is spawned on demand */
+    private static SensorThread sSensorThread;
+    private static int sQueue;
+
+    // Used within this module from outside SensorManager, don't make private
+    static SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
+    static final ArrayList<ListenerDelegate> sListeners =
+        new ArrayList<ListenerDelegate>();
+
+    // Common pool of sensor events.
+    static SensorEventPool sPool;
+
+    // Looper associated with the context in which this instance was created.
+    final Looper mMainLooper;
+
+    /*-----------------------------------------------------------------------*/
+
+    static private class SensorThread {
+
+        Thread mThread;
+        boolean mSensorsReady;
+
+        SensorThread() {
+        }
+
+        @Override
+        protected void finalize() {
+        }
+
+        // must be called with sListeners lock
+        boolean startLocked() {
+            try {
+                if (mThread == null) {
+                    mSensorsReady = false;
+                    SensorThreadRunnable runnable = new SensorThreadRunnable();
+                    Thread thread = new Thread(runnable, SensorThread.class.getName());
+                    thread.start();
+                    synchronized (runnable) {
+                        while (mSensorsReady == false) {
+                            runnable.wait();
+                        }
+                    }
+                    mThread = thread;
+                }
+            } catch (InterruptedException e) {
+            }
+            return mThread == null ? false : true;
+        }
+
+        private class SensorThreadRunnable implements Runnable {
+            SensorThreadRunnable() {
+            }
+
+            private boolean open() {
+                // NOTE: this cannot synchronize on sListeners, since
+                // it's held in the main thread at least until we
+                // return from here.
+                sQueue = sensors_create_queue();
+                return true;
+            }
+
+            public void run() {
+                //Log.d(TAG, "entering main sensor thread");
+                final float[] values = new float[3];
+                final int[] status = new int[1];
+                final long timestamp[] = new long[1];
+                Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
+
+                if (!open()) {
+                    return;
+                }
+
+                synchronized (this) {
+                    // we've open the driver, we're ready to open the sensors
+                    mSensorsReady = true;
+                    this.notify();
+                }
+
+                while (true) {
+                    // wait for an event
+                    final int sensor = sensors_data_poll(sQueue, values, status, timestamp);
+
+                    int accuracy = status[0];
+                    synchronized (sListeners) {
+                        if (sensor == -1 || sListeners.isEmpty()) {
+                            // we lost the connection to the event stream. this happens
+                            // when the last listener is removed or if there is an error
+                            if (sensor == -1 && !sListeners.isEmpty()) {
+                                // log a warning in case of abnormal termination
+                                Log.e(TAG, "_sensors_data_poll() failed, we bail out: sensors=" + sensor);
+                            }
+                            // we have no more listeners or polling failed, terminate the thread
+                            sensors_destroy_queue(sQueue);
+                            sQueue = 0;
+                            mThread = null;
+                            break;
+                        }
+                        final Sensor sensorObject = sHandleToSensor.get(sensor);
+                        if (sensorObject != null) {
+                            // report the sensor event to all listeners that
+                            // care about it.
+                            final int size = sListeners.size();
+                            for (int i=0 ; i<size ; i++) {
+                                ListenerDelegate listener = sListeners.get(i);
+                                if (listener.hasSensor(sensorObject)) {
+                                    // this is asynchronous (okay to call
+                                    // with sListeners lock held).
+                                    listener.onSensorChangedLocked(sensorObject,
+                                            values, timestamp, accuracy);
+                                }
+                            }
+                        }
+                    }
+                }
+                //Log.d(TAG, "exiting main sensor thread");
+            }
+        }
+    }
+
+    /*-----------------------------------------------------------------------*/
+
+    private class ListenerDelegate {
+        private final SensorEventListener mSensorEventListener;
+        private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>();
+        private final Handler mHandler;
+        public SparseBooleanArray mSensors = new SparseBooleanArray();
+        public SparseBooleanArray mFirstEvent = new SparseBooleanArray();
+        public SparseIntArray mSensorAccuracies = new SparseIntArray();
+
+        ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler) {
+            mSensorEventListener = listener;
+            Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
+            // currently we create one Handler instance per listener, but we could
+            // have one per looper (we'd need to pass the ListenerDelegate
+            // instance to handleMessage and keep track of them separately).
+            mHandler = new Handler(looper) {
+                @Override
+                public void handleMessage(Message msg) {
+                    final SensorEvent t = (SensorEvent)msg.obj;
+                    final int handle = t.sensor.getHandle();
+
+                    switch (t.sensor.getType()) {
+                        // Only report accuracy for sensors that support it.
+                        case Sensor.TYPE_MAGNETIC_FIELD:
+                        case Sensor.TYPE_ORIENTATION:
+                            // call onAccuracyChanged() only if the value changes
+                            final int accuracy = mSensorAccuracies.get(handle);
+                            if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
+                                mSensorAccuracies.put(handle, t.accuracy);
+                                mSensorEventListener.onAccuracyChanged(t.sensor, t.accuracy);
+                            }
+                            break;
+                        default:
+                            // For other sensors, just report the accuracy once
+                            if (mFirstEvent.get(handle) == false) {
+                                mFirstEvent.put(handle, true);
+                                mSensorEventListener.onAccuracyChanged(
+                                        t.sensor, SENSOR_STATUS_ACCURACY_HIGH);
+                            }
+                            break;
+                    }
+
+                    mSensorEventListener.onSensorChanged(t);
+                    sPool.returnToPool(t);
+                }
+            };
+            addSensor(sensor);
+        }
+
+        Object getListener() {
+            return mSensorEventListener;
+        }
+
+        void addSensor(Sensor sensor) {
+            mSensors.put(sensor.getHandle(), true);
+            mSensorList.add(sensor);
+        }
+        int removeSensor(Sensor sensor) {
+            mSensors.delete(sensor.getHandle());
+            mSensorList.remove(sensor);
+            return mSensors.size();
+        }
+        boolean hasSensor(Sensor sensor) {
+            return mSensors.get(sensor.getHandle());
+        }
+        List<Sensor> getSensors() {
+            return mSensorList;
+        }
+
+        void onSensorChangedLocked(Sensor sensor, float[] values, long[] timestamp, int accuracy) {
+            SensorEvent t = sPool.getFromPool();
+            final float[] v = t.values;
+            v[0] = values[0];
+            v[1] = values[1];
+            v[2] = values[2];
+            t.timestamp = timestamp[0];
+            t.accuracy = accuracy;
+            t.sensor = sensor;
+            Message msg = Message.obtain();
+            msg.what = 0;
+            msg.obj = t;
+            msg.setAsynchronous(true);
+            mHandler.sendMessage(msg);
+        }
+    }
+
+    /**
+     * {@hide}
+     */
+    public SystemSensorManager(Looper mainLooper) {
+        mMainLooper = mainLooper;
+
+        synchronized(sListeners) {
+            if (!sSensorModuleInitialized) {
+                sSensorModuleInitialized = true;
+
+                nativeClassInit();
+
+                // initialize the sensor list
+                sensors_module_init();
+                final ArrayList<Sensor> fullList = sFullSensorsList;
+                int i = 0;
+                do {
+                    Sensor sensor = new Sensor();
+                    i = sensors_module_get_next_sensor(sensor, i);
+
+                    if (i>=0) {
+                        //Log.d(TAG, "found sensor: " + sensor.getName() +
+                        //        ", handle=" + sensor.getHandle());
+                        fullList.add(sensor);
+                        sHandleToSensor.append(sensor.getHandle(), sensor);
+                    }
+                } while (i>0);
+
+                sPool = new SensorEventPool( sFullSensorsList.size()*2 );
+                sSensorThread = new SensorThread();
+            }
+        }
+    }
+
+    /** @hide */
+    @Override
+    protected List<Sensor> getFullSensorList() {
+        return sFullSensorsList;
+    }
+
+    private boolean enableSensorLocked(Sensor sensor, int delay) {
+        boolean result = false;
+        for (ListenerDelegate i : sListeners) {
+            if (i.hasSensor(sensor)) {
+                String name = sensor.getName();
+                int handle = sensor.getHandle();
+                result = sensors_enable_sensor(sQueue, name, handle, delay);
+                break;
+            }
+        }
+        return result;
+    }
+
+    private boolean disableSensorLocked(Sensor sensor) {
+        for (ListenerDelegate i : sListeners) {
+            if (i.hasSensor(sensor)) {
+                // not an error, it's just that this sensor is still in use
+                return true;
+            }
+        }
+        String name = sensor.getName();
+        int handle = sensor.getHandle();
+        return sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE);
+    }
+
+    /** @hide */
+    @Override
+    protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
+            int delay, Handler handler) {
+        boolean result = true;
+        synchronized (sListeners) {
+            // look for this listener in our list
+            ListenerDelegate l = null;
+            for (ListenerDelegate i : sListeners) {
+                if (i.getListener() == listener) {
+                    l = i;
+                    break;
+                }
+            }
+
+            // if we don't find it, add it to the list
+            if (l == null) {
+                l = new ListenerDelegate(listener, sensor, handler);
+                sListeners.add(l);
+                // if the list is not empty, start our main thread
+                if (!sListeners.isEmpty()) {
+                    if (sSensorThread.startLocked()) {
+                        if (!enableSensorLocked(sensor, delay)) {
+                            // oops. there was an error
+                            sListeners.remove(l);
+                            result = false;
+                        }
+                    } else {
+                        // there was an error, remove the listener
+                        sListeners.remove(l);
+                        result = false;
+                    }
+                } else {
+                    // weird, we couldn't add the listener
+                    result = false;
+                }
+            } else if (!l.hasSensor(sensor)) {
+                l.addSensor(sensor);
+                if (!enableSensorLocked(sensor, delay)) {
+                    // oops. there was an error
+                    l.removeSensor(sensor);
+                    result = false;
+                }
+            }
+        }
+
+        return result;
+    }
+
+    /** @hide */
+    @Override
+    protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
+        synchronized (sListeners) {
+            final int size = sListeners.size();
+            for (int i=0 ; i<size ; i++) {
+                ListenerDelegate l = sListeners.get(i);
+                if (l.getListener() == listener) {
+                    if (sensor == null) {
+                        sListeners.remove(i);
+                        // disable all sensors for this listener
+                        for (Sensor s : l.getSensors()) {
+                            disableSensorLocked(s);
+                        }
+                    } else if (l.removeSensor(sensor) == 0) {
+                        // if we have no more sensors enabled on this listener,
+                        // take it off the list.
+                        sListeners.remove(i);
+                        disableSensorLocked(sensor);
+                    }
+                    break;
+                }
+            }
+        }
+    }
+
+    private static native void nativeClassInit();
+
+    private static native int sensors_module_init();
+    private static native int sensors_module_get_next_sensor(Sensor sensor, int next);
+
+    // Used within this module from outside SensorManager, don't make private
+    static native int sensors_create_queue();
+    static native void sensors_destroy_queue(int queue);
+    static native boolean sensors_enable_sensor(int queue, String name, int sensor, int enable);
+    static native int sensors_data_poll(int queue, float[] values, int[] status, long[] timestamp);
+}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index de16985..ef4209f 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -373,10 +373,11 @@
     }
 
     /**
-     * Gets you info about the current data network.
-     * Call {@link NetworkInfo#isConnected()} on the returned {@link NetworkInfo}
-     * to check if the device has a data connection.
-    */
+     * Returns details about the currently active data network. When connected,
+     * this network is the default route for outgoing connections. You should
+     * always check {@link NetworkInfo#isConnected()} before initiating network
+     * traffic. This may return {@code null} when no networks are available.
+     */
     public NetworkInfo getActiveNetworkInfo() {
         try {
             return mService.getActiveNetworkInfo();
@@ -856,4 +857,19 @@
         } catch (RemoteException e) {}
         return false;
     }
+
+    /**
+     * Returns if the currently active data network is metered. A network is
+     * classified as metered when the user is sensitive to heavy data usage on
+     * that connection. You should check this before doing large data transfers,
+     * and warn the user or delay the operation until another network is
+     * available.
+     */
+    public boolean isActiveNetworkMetered() {
+        try {
+            return mService.isActiveNetworkMetered();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
 }
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 7046008..92aeff2 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -51,6 +51,7 @@
     NetworkState[] getAllNetworkState();
 
     NetworkQuotaInfo getActiveNetworkQuotaInfo();
+    boolean isActiveNetworkMetered();
 
     boolean setRadios(boolean onOff);
 
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 35e8e47..3250ae7 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -51,5 +51,6 @@
     boolean getRestrictBackground();
 
     NetworkQuotaInfo getNetworkQuotaInfo(in NetworkState state);
+    boolean isNetworkMetered(in NetworkState state);
 
 }
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index b4f6367..08d4c6c 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -32,6 +32,9 @@
 
     /** Return data layer snapshot of UID network usage. */
     NetworkStats getDataLayerSnapshotForUid(int uid);
+    /** Return set of any ifaces associated with mobile networks since boot. */
+    String[] getMobileIfaces();
+
     /** Increment data layer count of operations performed for UID and tag. */
     void incrementOperationCount(int uid, int tag, int operationCount);
 
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 50432a1..39a4d7b 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -48,6 +48,8 @@
     public static final int MATCH_MOBILE_4G = 3;
     public static final int MATCH_WIFI = 4;
     public static final int MATCH_ETHERNET = 5;
+    public static final int MATCH_MOBILE_WILDCARD = 6;
+    public static final int MATCH_WIFI_WILDCARD = 7;
 
     /**
      * Set of {@link NetworkInfo#getType()} that reflect data usage.
@@ -86,11 +88,19 @@
     }
 
     /**
+     * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks,
+     * regardless of IMSI.
+     */
+    public static NetworkTemplate buildTemplateMobileWildcard() {
+        return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null);
+    }
+
+    /**
      * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks,
      * regardless of SSID.
      */
     public static NetworkTemplate buildTemplateWifiWildcard() {
-        return new NetworkTemplate(MATCH_WIFI, null, null);
+        return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null);
     }
 
     @Deprecated
@@ -198,6 +208,10 @@
                 return matchesWifi(ident);
             case MATCH_ETHERNET:
                 return matchesEthernet(ident);
+            case MATCH_MOBILE_WILDCARD:
+                return matchesMobileWildcard(ident);
+            case MATCH_WIFI_WILDCARD:
+                return matchesWifiWildcard(ident);
             default:
                 throw new IllegalArgumentException("unknown network template");
         }
@@ -257,13 +271,7 @@
     private boolean matchesWifi(NetworkIdentity ident) {
         switch (ident.mType) {
             case TYPE_WIFI:
-                if (mNetworkId == null) {
-                    return true;
-                } else {
-                    return Objects.equal(mNetworkId, ident.mNetworkId);
-                }
-            case TYPE_WIFI_P2P:
-                return mNetworkId == null;
+                return Objects.equal(mNetworkId, ident.mNetworkId);
             default:
                 return false;
         }
@@ -279,6 +287,24 @@
         return false;
     }
 
+    private boolean matchesMobileWildcard(NetworkIdentity ident) {
+        if (ident.mType == TYPE_WIMAX) {
+            return true;
+        } else {
+            return contains(DATA_USAGE_NETWORK_TYPES, ident.mType);
+        }
+    }
+
+    private boolean matchesWifiWildcard(NetworkIdentity ident) {
+        switch (ident.mType) {
+            case TYPE_WIFI:
+            case TYPE_WIFI_P2P:
+                return true;
+            default:
+                return false;
+        }
+    }
+
     private static String getMatchRuleName(int matchRule) {
         switch (matchRule) {
             case MATCH_MOBILE_3G_LOWER:
@@ -291,6 +317,10 @@
                 return "WIFI";
             case MATCH_ETHERNET:
                 return "ETHERNET";
+            case MATCH_MOBILE_WILDCARD:
+                return "MOBILE_WILDCARD";
+            case MATCH_WIFI_WILDCARD:
+                return "WIFI_WILDCARD";
             default:
                 return "UNKNOWN";
         }
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index ee3e165..e437d2e 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -88,6 +88,16 @@
      */
     public static final int TAG_SYSTEM_BACKUP = 0xFFFFFF03;
 
+    private static INetworkStatsService sStatsService;
+
+    private synchronized static INetworkStatsService getStatsService() {
+        if (sStatsService == null) {
+            sStatsService = INetworkStatsService.Stub.asInterface(
+                    ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+        }
+        return sStatsService;
+    }
+
     /**
      * Snapshot of {@link NetworkStats} when the currently active profiling
      * session started, or {@code null} if no session active.
@@ -228,11 +238,9 @@
      * @param operationCount Number of operations to increment count by.
      */
     public static void incrementOperationCount(int tag, int operationCount) {
-        final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
-                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
         final int uid = android.os.Process.myUid();
         try {
-            statsService.incrementOperationCount(uid, tag, operationCount);
+            getStatsService().incrementOperationCount(uid, tag, operationCount);
         } catch (RemoteException e) {
             throw new RuntimeException(e);
         }
@@ -257,7 +265,13 @@
      * @return number of packets.  If the statistics are not supported by this device,
      * {@link #UNSUPPORTED} will be returned.
      */
-    public static native long getMobileTxPackets();
+    public static long getMobileTxPackets() {
+        long total = 0;
+        for (String iface : getMobileIfaces()) {
+            total += getTxPackets(iface);
+        }
+        return total;
+    }
 
     /**
      * Get the total number of packets received through the mobile interface.
@@ -265,7 +279,13 @@
      * @return number of packets.  If the statistics are not supported by this device,
      * {@link #UNSUPPORTED} will be returned.
      */
-    public static native long getMobileRxPackets();
+    public static long getMobileRxPackets() {
+        long total = 0;
+        for (String iface : getMobileIfaces()) {
+            total += getRxPackets(iface);
+        }
+        return total;
+    }
 
     /**
      * Get the total number of bytes transmitted through the mobile interface.
@@ -273,7 +293,13 @@
      * @return number of bytes.  If the statistics are not supported by this device,
      * {@link #UNSUPPORTED} will be returned.
      */
-      public static native long getMobileTxBytes();
+    public static long getMobileTxBytes() {
+        long total = 0;
+        for (String iface : getMobileIfaces()) {
+            total += getTxBytes(iface);
+        }
+        return total;
+    }
 
     /**
      * Get the total number of bytes received through the mobile interface.
@@ -281,7 +307,13 @@
      * @return number of bytes.  If the statistics are not supported by this device,
      * {@link #UNSUPPORTED} will be returned.
      */
-    public static native long getMobileRxBytes();
+    public static long getMobileRxBytes() {
+        long total = 0;
+        for (String iface : getMobileIfaces()) {
+            total += getRxBytes(iface);
+        }
+        return total;
+    }
 
     /**
      * Get the total number of packets transmitted through the specified interface.
@@ -290,7 +322,9 @@
      * {@link #UNSUPPORTED} will be returned.
      * @hide
      */
-    public static native long getTxPackets(String iface);
+    public static long getTxPackets(String iface) {
+        return nativeGetIfaceStat(iface, TYPE_TX_PACKETS);
+    }
 
     /**
      * Get the total number of packets received through the specified interface.
@@ -299,7 +333,9 @@
      * {@link #UNSUPPORTED} will be returned.
      * @hide
      */
-    public static native long getRxPackets(String iface);
+    public static long getRxPackets(String iface) {
+        return nativeGetIfaceStat(iface, TYPE_RX_PACKETS);
+    }
 
     /**
      * Get the total number of bytes transmitted through the specified interface.
@@ -308,7 +344,9 @@
      * {@link #UNSUPPORTED} will be returned.
      * @hide
      */
-    public static native long getTxBytes(String iface);
+    public static long getTxBytes(String iface) {
+        return nativeGetIfaceStat(iface, TYPE_TX_BYTES);
+    }
 
     /**
      * Get the total number of bytes received through the specified interface.
@@ -317,8 +355,9 @@
      * {@link #UNSUPPORTED} will be returned.
      * @hide
      */
-    public static native long getRxBytes(String iface);
-
+    public static long getRxBytes(String iface) {
+        return nativeGetIfaceStat(iface, TYPE_RX_BYTES);
+    }
 
     /**
      * Get the total number of packets sent through all network interfaces.
@@ -326,7 +365,9 @@
      * @return the number of packets.  If the statistics are not supported by this device,
      * {@link #UNSUPPORTED} will be returned.
      */
-    public static native long getTotalTxPackets();
+    public static long getTotalTxPackets() {
+        return nativeGetTotalStat(TYPE_TX_PACKETS);
+    }
 
     /**
      * Get the total number of packets received through all network interfaces.
@@ -334,7 +375,9 @@
      * @return number of packets.  If the statistics are not supported by this device,
      * {@link #UNSUPPORTED} will be returned.
      */
-    public static native long getTotalRxPackets();
+    public static long getTotalRxPackets() {
+        return nativeGetTotalStat(TYPE_RX_PACKETS);
+    }
 
     /**
      * Get the total number of bytes sent through all network interfaces.
@@ -342,7 +385,9 @@
      * @return number of bytes.  If the statistics are not supported by this device,
      * {@link #UNSUPPORTED} will be returned.
      */
-    public static native long getTotalTxBytes();
+    public static long getTotalTxBytes() {
+        return nativeGetTotalStat(TYPE_TX_BYTES);
+    }
 
     /**
      * Get the total number of bytes received through all network interfaces.
@@ -350,7 +395,9 @@
      * @return number of bytes.  If the statistics are not supported by this device,
      * {@link #UNSUPPORTED} will be returned.
      */
-    public static native long getTotalRxBytes();
+    public static long getTotalRxBytes() {
+        return nativeGetTotalStat(TYPE_RX_BYTES);
+    }
 
     /**
      * Get the number of bytes sent through the network for this UID.
@@ -483,7 +530,6 @@
      */
     public static native long getUidTcpRxSegments(int uid);
 
-
     /**
      * Get the number of UDP packets sent for this UID.
      * Includes DNS requests.
@@ -515,13 +561,33 @@
      * special permission.
      */
     private static NetworkStats getDataLayerSnapshotForUid(Context context) {
-        final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
-                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
         final int uid = android.os.Process.myUid();
         try {
-            return statsService.getDataLayerSnapshotForUid(uid);
+            return getStatsService().getDataLayerSnapshotForUid(uid);
         } catch (RemoteException e) {
             throw new RuntimeException(e);
         }
     }
+
+    /**
+     * Return set of any ifaces associated with mobile networks since boot.
+     * Interfaces are never removed from this list, so counters should always be
+     * monotonic.
+     */
+    private static String[] getMobileIfaces() {
+        try {
+            return getStatsService().getMobileIfaces();
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    // NOTE: keep these in sync with android_net_TrafficStats.cpp
+    private static final int TYPE_RX_BYTES = 0;
+    private static final int TYPE_RX_PACKETS = 1;
+    private static final int TYPE_TX_BYTES = 2;
+    private static final int TYPE_TX_PACKETS = 3;
+
+    private static native long nativeGetTotalStat(int type);
+    private static native long nativeGetIfaceStat(String iface, int type);
 }
diff --git a/core/java/android/net/nsd/DnsSdServiceInfo.java b/core/java/android/net/nsd/DnsSdServiceInfo.java
index 33c3eb9..66abd3a 100644
--- a/core/java/android/net/nsd/DnsSdServiceInfo.java
+++ b/core/java/android/net/nsd/DnsSdServiceInfo.java
@@ -22,8 +22,8 @@
 import java.net.InetAddress;
 
 /**
- * Defines a service based on DNS service discovery
- * {@hide}
+ * A class representing service information for network service discovery
+ * {@see NsdManager}
  */
 public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable {
 
@@ -40,56 +40,63 @@
     public DnsSdServiceInfo() {
     }
 
+    /** @hide */
     public DnsSdServiceInfo(String sn, String rt, DnsSdTxtRecord tr) {
         mServiceName = sn;
         mServiceType = rt;
         mTxtRecord = tr;
     }
 
+    /** Get the service name */
     @Override
-    /** @hide */
     public String getServiceName() {
         return mServiceName;
     }
 
+    /** Set the service name */
     @Override
-    /** @hide */
     public void setServiceName(String s) {
         mServiceName = s;
     }
 
+    /** Get the service type */
     @Override
-    /** @hide */
     public String getServiceType() {
         return mServiceType;
     }
 
+    /** Set the service type */
     @Override
-    /** @hide */
     public void setServiceType(String s) {
         mServiceType = s;
     }
 
+    /** @hide */
     public DnsSdTxtRecord getTxtRecord() {
         return mTxtRecord;
     }
 
+    /** @hide */
     public void setTxtRecord(DnsSdTxtRecord t) {
         mTxtRecord = new DnsSdTxtRecord(t);
     }
 
+    /** Get the host address. The host address is valid for a resolved service. */
     public InetAddress getHost() {
         return mHost;
     }
 
+    /** Set the host address */
     public void setHost(InetAddress s) {
         mHost = s;
     }
 
+    /** Get port number. The port number is valid for a resolved service. */
     public int getPort() {
         return mPort;
     }
 
+    /** Set port number */
     public void setPort(int p) {
         mPort = p;
     }
@@ -147,5 +154,4 @@
                 return new DnsSdServiceInfo[size];
             }
         };
-
 }
diff --git a/core/java/android/net/nsd/DnsSdTxtRecord.java b/core/java/android/net/nsd/DnsSdTxtRecord.java
index 952e02f..ccb9a91 100644
--- a/core/java/android/net/nsd/DnsSdTxtRecord.java
+++ b/core/java/android/net/nsd/DnsSdTxtRecord.java
@@ -37,7 +37,6 @@
  * The DnsSdTxtRecord object stores the entire TXT data as a single byte array, traversing it
  * as need be to implement its various methods.
  *
- * @hide
  */
 public class DnsSdTxtRecord implements Parcelable {
     private static final byte mSeperator = '=';
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index 505f11b..dac8d20 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -24,29 +24,110 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.Messenger;
+import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
 
 /**
- * The Network Service Discovery Manager class provides the API for service
- * discovery. Service discovery enables applications to discover and connect with services
- * on a network. Example applications include a game application discovering another instance
- * of the game application or a printer application discovering other printers on a network.
+ * The Network Service Discovery Manager class provides the API to discover services
+ * on a network. As an example, if device A and device B are connected over a Wi-Fi
+ * network, a game registered on device A can be discovered by a game on device
+ * B. Another example use case is an application discovering printers on the network.
+ *
+ * <p> The API currently supports DNS based service discovery and discovery is currently
+ * limited to a local network over Multicast DNS. In future, it will be extended to
+ * support wide area discovery and other service discovery mechanisms.
+ * DNS service discovery is described at http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt
  *
  * <p> The API is asynchronous and responses to requests from an application are on listener
- * callbacks provided by the application. The application needs to do an initialization with
- * {@link #initialize} before doing any operation.
+ * callbacks provided by the application. The application must invoke {@link #initialize} before
+ * doing any other operation.
  *
- * <p> Android currently supports DNS based service discovery and it is limited to a local
- * network with the use of multicast DNS. In future, this class will be
- * extended to support other service discovery mechanisms.
+ * <p> There are three main operations the API supports - registration, discovery and resolution.
+ * <pre>
+ *                          Application start
+ *                                 |
+ *                                 |         <----------------------------------------------
+ *                             initialize()                                                 |
+ *                                 |                                                        |
+ *                                 | Wait until channel connects                            |
+ *                                 | before doing any operation                             |
+ *                                 |                                                        |
+ *                           onChannelConnected()                    __________             |
+ *                                 |                                           |            |
+ *                                 |                                           |            |
+ *                                 |                  onServiceRegistered()    |            |
+ *                     Register any local services  /                          |            |
+ *                      to be advertised with       \                          |            | If application needs to
+ *                       registerService()            onFailure()              |            | do any further operations
+ *                                 |                                           |            | again, it needs to
+ *                                 |                                           |            | initialize() connection
+ *                          discoverServices()                                 |            | to framework again
+ *                                 |                                           |            |
+ *                      Maintain a list to track                               |            |
+ *                        discovered services                                  |            |
+ *                                 |                                           |            |
+ *                                 |--------->                                 |-> onChannelDisconnected()
+ *                                 |          |                                |
+ *                                 |      onServiceFound()                     |
+ *                                 |          |                                |
+ *                                 |     add service to list                   |
+ *                                 |          |                                |
+ *                                 |<----------                                |
+ *                                 |                                           |
+ *                                 |--------->                                 |
+ *                                 |          |                                |
+ *                                 |      onServiceLost()                      |
+ *                                 |          |                                |
+ *                                 |   remove service from list                |
+ *                                 |          |                                |
+ *                                 |<----------                                |
+ *                                 |                                           |
+ *                                 |                                           |
+ *                                 | Connect to a service                      |
+ *                                 | from list ?                               |
+ *                                 |                                           |
+ *                          resolveService()                                   |
+ *                                 |                                           |
+ *                         onServiceResolved()                                 |
+ *                                 |                                           |
+ *                     Establish connection to service                         |
+ *                     with the host and port information                      |
+ *                                 |                                           |
+ *                                 |                                ___________|
+ *                           deinitialize()
+ *                    when done with all operations
+ *                          or before quit
+ *
+ * </pre>
+ * An application that needs to advertise itself over a network for other applications to
+ * discover it can do so with a call to {@link #registerService}. If Example is a http based
+ * application that can provide HTML data to peer services, it can register a name "Example"
+ * with service type "_http._tcp". A successful registration is notified with a callback to
+ * {@link DnsSdRegisterListener#onServiceRegistered} and a failure to register is notified
+ * over {@link DnsSdRegisterListener#onFailure}
+ *
+ * <p> A peer application looking for http services can initiate a discovery for "_http._tcp"
+ * with a call to {@link #discoverServices}. A service found is notified with a callback
+ * to {@link DnsSdDiscoveryListener#onServiceFound} and a service lost is notified on
+ * {@link DnsSdDiscoveryListener#onServiceLost}.
+ *
+ * <p> Once the peer application discovers the "Example" http srevice, and needs to receive data
+ * from the "Example" application, it can initiate a resolve with {@link #resolveService} to
+ * resolve the host and port details for the purpose of establishing a connection. A successful
+ * resolve is notified on {@link DnsSdResolveListener#onServiceResolved} and a failure is notified
+ * on {@link DnsSdResolveListener#onFailure}.
+ *
+ * Applications can reserve for a service type at
+ * http://www.iana.org/form/ports-service. Existing services can be found at
+ * http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml
  *
  * Get an instance of this class by calling {@link android.content.Context#getSystemService(String)
  * Context.getSystemService(Context.NSD_SERVICE)}.
- * @hide
  *
+ * {@see DnsSdServiceInfo}
  */
 public class NsdManager {
     private static final String TAG = "NsdManager";
@@ -80,27 +161,32 @@
     public static final int REGISTER_SERVICE_SUCCEEDED              = BASE + 11;
 
     /** @hide */
-    public static final int UPDATE_SERVICE                          = BASE + 12;
+    public static final int UNREGISTER_SERVICE                      = BASE + 12;
     /** @hide */
-    public static final int UPDATE_SERVICE_FAILED                   = BASE + 13;
+    public static final int UNREGISTER_SERVICE_FAILED               = BASE + 13;
     /** @hide */
-    public static final int UPDATE_SERVICE_SUCCEEDED                = BASE + 14;
+    public static final int UNREGISTER_SERVICE_SUCCEEDED            = BASE + 14;
 
     /** @hide */
-    public static final int RESOLVE_SERVICE                         = BASE + 15;
+    public static final int UPDATE_SERVICE                          = BASE + 15;
     /** @hide */
-    public static final int RESOLVE_SERVICE_FAILED                  = BASE + 16;
+    public static final int UPDATE_SERVICE_FAILED                   = BASE + 16;
     /** @hide */
-    public static final int RESOLVE_SERVICE_SUCCEEDED               = BASE + 17;
+    public static final int UPDATE_SERVICE_SUCCEEDED                = BASE + 17;
 
     /** @hide */
-    public static final int STOP_RESOLVE                            = BASE + 18;
+    public static final int RESOLVE_SERVICE                         = BASE + 18;
     /** @hide */
-    public static final int STOP_RESOLVE_FAILED                     = BASE + 19;
+    public static final int RESOLVE_SERVICE_FAILED                  = BASE + 19;
     /** @hide */
-    public static final int STOP_RESOLVE_SUCCEEDED                  = BASE + 20;
+    public static final int RESOLVE_SERVICE_SUCCEEDED               = BASE + 20;
 
-
+    /** @hide */
+    public static final int STOP_RESOLVE                            = BASE + 21;
+    /** @hide */
+    public static final int STOP_RESOLVE_FAILED                     = BASE + 22;
+    /** @hide */
+    public static final int STOP_RESOLVE_SUCCEEDED                  = BASE + 23;
 
     /**
      * Create a new Nsd instance. Applications use
@@ -115,36 +201,44 @@
     }
 
     /**
+     * Passed with onFailure() calls.
      * Indicates that the operation failed due to an internal error.
      */
     public static final int ERROR               = 0;
 
     /**
-     * Indicates that the operation failed because service discovery is unsupported on the device.
+     * Passed with onFailure() calls.
+     * Indicates that the operation failed because service discovery
+     * is unsupported on the device.
      */
     public static final int UNSUPPORTED         = 1;
 
     /**
-     * Indicates that the operation failed because the framework is busy and
-     * unable to service the request.
+     * Passed with onFailure() calls.
+     * Indicates that the operation failed because the framework is
+     * busy and unable to service the request.
      */
     public static final int BUSY                = 2;
 
     /**
+     * Passed with onFailure() calls.
      * Indicates that the operation failed because it is already active.
      */
     public static final int ALREADY_ACTIVE      = 3;
 
     /**
+     * Passed with onFailure() calls.
      * Indicates that the operation failed because maximum limit on
      * service registrations has reached.
      */
     public static final int MAX_REGS_REACHED    = 4;
 
-
-
     /** Interface for callback invocation when framework channel is connected or lost */
     public interface ChannelListener {
+       /**
+         * The channel to the framework is connected.
+         * Application can initiate calls into the framework using the channel instance passed.
+         */
         public void onChannelConnected(Channel c);
         /**
          * The channel to the framework has been disconnected.
@@ -153,6 +247,7 @@
         public void onChannelDisconnected();
     }
 
+    /** Generic interface for callback invocation for a success or failure */
     public interface ActionListener {
 
         public void onFailure(int errorCode);
@@ -160,11 +255,12 @@
         public void onSuccess();
     }
 
+    /** Interface for callback invocation for service discovery */
     public interface DnsSdDiscoveryListener {
 
         public void onFailure(int errorCode);
 
-        public void onStarted(String registrationType);
+        public void onStarted(String serviceType);
 
         public void onServiceFound(DnsSdServiceInfo serviceInfo);
 
@@ -172,6 +268,7 @@
 
     }
 
+    /** Interface for callback invocation for service registration */
     public interface DnsSdRegisterListener {
 
         public void onFailure(int errorCode);
@@ -179,6 +276,7 @@
         public void onServiceRegistered(int registeredId, DnsSdServiceInfo serviceInfo);
     }
 
+    /** @hide */
     public interface DnsSdUpdateRegistrationListener {
 
         public void onFailure(int errorCode);
@@ -186,6 +284,7 @@
         public void onServiceUpdated(int registeredId, DnsSdTxtRecord txtRecord);
     }
 
+    /** Interface for callback invocation for service resolution */
     public interface DnsSdResolveListener {
 
         public void onFailure(int errorCode);
@@ -208,6 +307,7 @@
         private DnsSdDiscoveryListener mDnsSdDiscoveryListener;
         private ActionListener mDnsSdStopDiscoveryListener;
         private DnsSdRegisterListener mDnsSdRegisterListener;
+        private ActionListener mDnsSdUnregisterListener;
         private DnsSdUpdateRegistrationListener mDnsSdUpdateListener;
         private DnsSdResolveListener mDnsSdResolveListener;
         private ActionListener mDnsSdStopResolveListener;
@@ -279,7 +379,17 @@
                                     (DnsSdServiceInfo) message.obj);
                         }
                         break;
-                    case UPDATE_SERVICE_FAILED:
+                    case UNREGISTER_SERVICE_FAILED:
+                        if (mDnsSdUnregisterListener != null) {
+                            mDnsSdUnregisterListener.onFailure(message.arg1);
+                        }
+                        break;
+                    case UNREGISTER_SERVICE_SUCCEEDED:
+                        if (mDnsSdUnregisterListener != null) {
+                            mDnsSdUnregisterListener.onSuccess();
+                        }
+                        break;
+                   case UPDATE_SERVICE_FAILED:
                         if (mDnsSdUpdateListener != null) {
                             mDnsSdUpdateListener.onFailure(message.arg1);
                         }
@@ -319,6 +429,10 @@
         }
    }
 
+    private static void checkChannel(Channel c) {
+        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+    }
+
     /**
      * Registers the application with the service discovery framework. This function
      * must be the first to be called before any other operations are performed. No service
@@ -327,7 +441,7 @@
      *
      * @param srcContext is the context of the source
      * @param srcLooper is the Looper on which the callbacks are receivied
-     * @param listener for callback at loss of framework communication.
+     * @param listener for callback at loss of framework communication. Cannot be null.
      */
     public void initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {
         Messenger messenger = getMessenger();
@@ -339,88 +453,142 @@
     }
 
     /**
-     * Set the listener for service discovery. Can be null.
+     * Disconnects application from service discovery framework. No further operations
+     * will succeed until a {@link #initialize} is called again.
+     *
+     * @param c channel initialized with {@link #initialize}
      */
-    public void setDiscoveryListener(Channel c, DnsSdDiscoveryListener b) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
-        c.mDnsSdDiscoveryListener = b;
+    public void deinitialize(Channel c) {
+        checkChannel(c);
+        c.mAsyncChannel.disconnect();
     }
 
     /**
-     * Set the listener for stop service discovery. Can be null.
+     * Register a service to be discovered by other services.
+     *
+     * <p> The function call immediately returns after sending a request to register service
+     * to the framework. The application is notified of a success to initiate
+     * discovery through the callback {@link DnsSdRegisterListener#onServiceRegistered} or a failure
+     * through {@link DnsSdRegisterListener#onFailure}.
+     *
+     * @param c is the channel created at {@link #initialize}
+     * @param serviceType The service type being advertised.
+     * @param port on which the service is listenering for incoming connections
+     * @param listener for success or failure callback. Can be null.
      */
-    public void setStopDiscoveryListener(Channel c, ActionListener a) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
-        c.mDnsSdStopDiscoveryListener = a;
-    }
-
-    /**
-     * Set the listener for service registration. Can be null.
-     */
-    public void setRegisterListener(Channel c, DnsSdRegisterListener b) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
-        c.mDnsSdRegisterListener = b;
-    }
-
-    /**
-     * Set the listener for service registration. Can be null.
-     */
-    public void setUpdateRegistrationListener(Channel c, DnsSdUpdateRegistrationListener b) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
-        c.mDnsSdUpdateListener = b;
-    }
-
-    /**
-     * Set the listener for service resolution. Can be null.
-     */
-    public void setResolveListener(Channel c, DnsSdResolveListener b) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
-        c.mDnsSdResolveListener = b;
-    }
-
-    /**
-     * Set the listener for stopping service resolution. Can be null.
-     */
-    public void setStopResolveListener(Channel c, ActionListener b) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
-        c.mDnsSdStopResolveListener = b;
-    }
-
-    public void registerService(Channel c, DnsSdServiceInfo serviceInfo) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
-        if (serviceInfo == null) throw new IllegalArgumentException("Null serviceInfo");
+    public void registerService(Channel c, String serviceName, String serviceType, int port,
+            DnsSdRegisterListener listener) {
+        checkChannel(c);
+        if (TextUtils.isEmpty(serviceName) || TextUtils.isEmpty(serviceType)) {
+            throw new IllegalArgumentException("Service name or type cannot be empty");
+        }
+        if (port <= 0) {
+            throw new IllegalArgumentException("Invalid port number");
+        }
+        DnsSdServiceInfo serviceInfo = new DnsSdServiceInfo(serviceName, serviceType, null);
+        serviceInfo.setPort(port);
+        c.mDnsSdRegisterListener = listener;
         c.mAsyncChannel.sendMessage(REGISTER_SERVICE, serviceInfo);
     }
 
+    /**
+     * Unregister a service registered through {@link #registerService}
+     * @param c is the channel created at {@link #initialize}
+     * @param registeredId is obtained at {@link DnsSdRegisterListener#onServiceRegistered}
+     * @param listener provides callbacks for success or failure. Can be null.
+     */
+    public void unregisterService(Channel c, int registeredId, ActionListener listener) {
+        checkChannel(c);
+        c.mDnsSdUnregisterListener = listener;
+        c.mAsyncChannel.sendMessage(UNREGISTER_SERVICE, registeredId);
+    }
+
+    /** @hide */
     public void updateService(Channel c, int registeredId, DnsSdTxtRecord txtRecord) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+        checkChannel(c);
         c.mAsyncChannel.sendMessage(UPDATE_SERVICE, registeredId, 0, txtRecord);
     }
 
-    public void discoverServices(Channel c, String serviceType) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
-        if (c.mDnsSdDiscoveryListener == null) throw new
-                IllegalStateException("Discovery listener needs to be set first");
+    /**
+     * Initiate service discovery to browse for instances of a service type. Service discovery
+     * consumes network bandwidth and will continue until the application calls
+     * {@link #stopServiceDiscovery}.
+     *
+     * <p> The function call immediately returns after sending a request to start service
+     * discovery to the framework. The application is notified of a success to initiate
+     * discovery through the callback {@link DnsSdDiscoveryListener#onStarted} or a failure
+     * through {@link DnsSdDiscoveryListener#onFailure}.
+     *
+     * <p> Upon successful start, application is notified when a service is found with
+     * {@link DnsSdDiscoveryListener#onServiceFound} or when a service is lost with
+     * {@link DnsSdDiscoveryListener#onServiceLost}.
+     *
+     * <p> Upon failure to start, service discovery is not active and application does
+     * not need to invoke {@link #stopServiceDiscovery}
+     *
+     * @param c is the channel created at {@link #initialize}
+     * @param serviceType The service type being discovered. Examples include "_http._tcp" for
+     * http services or "_ipp._tcp" for printers
+     * @param listener provides callbacks when service is found or lost. Cannot be null.
+     */
+    public void discoverServices(Channel c, String serviceType, DnsSdDiscoveryListener listener) {
+        checkChannel(c);
+        if (listener == null) {
+            throw new IllegalStateException("Discovery listener needs to be set first");
+        }
+        if (TextUtils.isEmpty(serviceType)) {
+            throw new IllegalStateException("Service type cannot be empty");
+        }
         DnsSdServiceInfo s = new DnsSdServiceInfo();
         s.setServiceType(serviceType);
+        c.mDnsSdDiscoveryListener = listener;
         c.mAsyncChannel.sendMessage(DISCOVER_SERVICES, s);
     }
 
-    public void stopServiceDiscovery(Channel c) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+    /**
+     * Stop service discovery initiated with {@link #discoverServices}. An active service
+     * discovery is notified to the application with {@link DnsSdDiscoveryListener#onStarted}
+     * and it stays active until the application invokes a stop service discovery.
+     *
+     * <p> Upon failure to start service discovery notified through
+     * {@link DnsSdDiscoveryListener#onFailure} service discovery is not active and
+     * application does not need to stop it.
+     *
+     * @param c is the channel created at {@link #initialize}
+     * @param listener notifies success or failure. Can be null.
+     */
+    public void stopServiceDiscovery(Channel c, ActionListener listener) {
+        checkChannel(c);
+        c.mDnsSdStopDiscoveryListener = listener;
         c.mAsyncChannel.sendMessage(STOP_DISCOVERY);
     }
 
-    public void resolveService(Channel c, DnsSdServiceInfo serviceInfo) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
-        if (serviceInfo == null) throw new IllegalArgumentException("Null serviceInfo");
-        if (c.mDnsSdResolveListener == null) throw new
-                IllegalStateException("Resolve listener needs to be set first");
+    /**
+     * Resolve a discovered service. An application can resolve a service right before
+     * establishing a connection to fetch the IP and port details on which to setup
+     * the connection.
+     *
+     * @param c is the channel created at {@link #initialize}
+     * @param serviceName of the the service
+     * @param serviceType of the service
+     * @param listener to receive callback upon success or failure. Cannot be null.
+     */
+    public void resolveService(Channel c, String serviceName, String serviceType,
+            DnsSdResolveListener listener) {
+        checkChannel(c);
+        if (TextUtils.isEmpty(serviceName) || TextUtils.isEmpty(serviceType)) {
+            throw new IllegalArgumentException("Service name or type cannot be empty");
+        }
+        if (listener == null) throw new
+                IllegalStateException("Resolve listener cannot be null");
+        c.mDnsSdResolveListener = listener;
+        DnsSdServiceInfo serviceInfo = new DnsSdServiceInfo(serviceName, serviceType, null);
         c.mAsyncChannel.sendMessage(RESOLVE_SERVICE, serviceInfo);
     }
 
+    /** @hide */
     public void stopServiceResolve(Channel c) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+        checkChannel(c);
         if (c.mDnsSdResolveListener == null) throw new
                 IllegalStateException("Resolve listener needs to be set first");
         c.mAsyncChannel.sendMessage(STOP_RESOLVE);
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index af94a37..4645fab 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -33,6 +33,7 @@
     public static final long TRACE_TAG_GRAPHICS = 1L << 1;
     public static final long TRACE_TAG_INPUT = 1L << 2;
     public static final long TRACE_TAG_VIEW = 1L << 3;
+    public static final long TRACE_TAG_WEBVIEW = 1L << 4;
 
     private static final long sEnabledTags = nativeGetEnabledTags();
 
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 850349b..36c01893 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -611,6 +611,11 @@
     /*package*/ void initBluetoothAfterTurningOn() {
         String discoverable = getProperty("Discoverable", false);
         String timeout = getProperty("DiscoverableTimeout", false);
+        if (timeout == null) {
+            Log.w(TAG, "Null DiscoverableTimeout property");
+            // assign a number, anything not 0
+            timeout = "1";
+        }
         if (discoverable.equals("true") && Integer.valueOf(timeout) != 0) {
             setAdapterPropertyBooleanNative("Discoverable", 0);
         }
diff --git a/core/java/android/service/textservice/SpellCheckerService.java b/core/java/android/service/textservice/SpellCheckerService.java
index 53ce32d..c579e6e 100644
--- a/core/java/android/service/textservice/SpellCheckerService.java
+++ b/core/java/android/service/textservice/SpellCheckerService.java
@@ -26,12 +26,18 @@
 import android.os.IBinder;
 import android.os.Process;
 import android.os.RemoteException;
+import android.text.TextUtils;
+import android.text.method.WordIterator;
 import android.util.Log;
 import android.view.textservice.SentenceSuggestionsInfo;
 import android.view.textservice.SuggestionsInfo;
 import android.view.textservice.TextInfo;
+import android.widget.SpellChecker;
 
 import java.lang.ref.WeakReference;
+import java.text.BreakIterator;
+import java.util.ArrayList;
+import java.util.Locale;
 
 /**
  * SpellCheckerService provides an abstract base class for a spell checker.
@@ -92,6 +98,7 @@
      */
     public static abstract class Session {
         private InternalISpellCheckerSession mInternalSession;
+        private volatile SentenceLevelAdapter mSentenceLevelAdapter;
 
         /**
          * @hide
@@ -142,8 +149,8 @@
 
         /**
          * Get sentence suggestions for specified texts in an array of TextInfo.
-         * The default implementation returns an array of SentenceSuggestionsInfo by simply
-         * calling onGetSuggestions.
+         * The default implementation splits the input text to words and returns
+         * {@link SentenceSuggestionsInfo} which contains suggestions for each word.
          * This function will run on the incoming IPC thread.
          * So, this is not called on the main thread,
          * but will be called in series on another thread.
@@ -156,14 +163,41 @@
          */
         public SentenceSuggestionsInfo[] onGetSentenceSuggestionsMultiple(TextInfo[] textInfos,
                 int suggestionsLimit) {
-            final int length = textInfos.length;
-            final SentenceSuggestionsInfo[] retval = new SentenceSuggestionsInfo[length];
-            for (int i = 0; i < length; ++i) {
-                final SuggestionsInfo si = onGetSuggestions(textInfos[i], suggestionsLimit);
-                si.setCookieAndSequence(textInfos[i].getCookie(), textInfos[i].getSequence());
-                final int N = textInfos[i].getText().length();
-                retval[i] = new SentenceSuggestionsInfo(
-                        new SuggestionsInfo[] {si}, new int[]{0}, new int[]{N});
+            if (textInfos == null || textInfos.length == 0) {
+                return SentenceLevelAdapter.EMPTY_SENTENCE_SUGGESTIONS_INFOS;
+            }
+            if (DBG) {
+                Log.d(TAG, "onGetSentenceSuggestionsMultiple: + " + textInfos.length + ", "
+                        + suggestionsLimit);
+            }
+            if (mSentenceLevelAdapter == null) {
+                synchronized(this) {
+                    if (mSentenceLevelAdapter == null) {
+                        final String localeStr = getLocale();
+                        if (!TextUtils.isEmpty(localeStr)) {
+                            mSentenceLevelAdapter = new SentenceLevelAdapter(new Locale(localeStr));
+                        }
+                    }
+                }
+            }
+            if (mSentenceLevelAdapter == null) {
+                return SentenceLevelAdapter.EMPTY_SENTENCE_SUGGESTIONS_INFOS;
+            }
+            final int infosSize = textInfos.length;
+            final SentenceSuggestionsInfo[] retval = new SentenceSuggestionsInfo[infosSize];
+            for (int i = 0; i < infosSize; ++i) {
+                final SentenceLevelAdapter.SentenceTextInfoParams textInfoParams =
+                        mSentenceLevelAdapter.getSplitWords(textInfos[i]);
+                final ArrayList<SentenceLevelAdapter.SentenceWordItem> mItems =
+                        textInfoParams.mItems;
+                final int itemsSize = mItems.size();
+                final TextInfo[] splitTextInfos = new TextInfo[itemsSize];
+                for (int j = 0; j < itemsSize; ++j) {
+                    splitTextInfos[j] = mItems.get(j).mTextInfo;
+                }
+                retval[i] = SentenceLevelAdapter.reconstructSuggestions(
+                        textInfoParams, onGetSuggestionsMultiple(
+                                splitTextInfos, suggestionsLimit, true));
             }
             return retval;
         }
@@ -290,4 +324,135 @@
             return internalSession;
         }
     }
+
+    /**
+     * Adapter class to accommodate word level spell checking APIs to sentence level spell checking
+     * APIs used in
+     * {@link SpellCheckerService.Session#onGetSuggestionsMultiple(TextInfo[], int, boolean)}
+     */
+    private static class SentenceLevelAdapter {
+        public static final SentenceSuggestionsInfo[] EMPTY_SENTENCE_SUGGESTIONS_INFOS =
+                new SentenceSuggestionsInfo[] {};
+        private static final SuggestionsInfo EMPTY_SUGGESTIONS_INFO = new SuggestionsInfo(0, null);
+        /**
+         * Container for split TextInfo parameters
+         */
+        public static class SentenceWordItem {
+            public final TextInfo mTextInfo;
+            public final int mStart;
+            public final int mLength;
+            public SentenceWordItem(TextInfo ti, int start, int end) {
+                mTextInfo = ti;
+                mStart = start;
+                mLength = end - start;
+            }
+        }
+
+        /**
+         * Container for originally queried TextInfo and parameters
+         */
+        public static class SentenceTextInfoParams {
+            final TextInfo mOriginalTextInfo;
+            final ArrayList<SentenceWordItem> mItems;
+            final int mSize;
+            public SentenceTextInfoParams(TextInfo ti, ArrayList<SentenceWordItem> items) {
+                mOriginalTextInfo = ti;
+                mItems = items;
+                mSize = items.size();
+            }
+        }
+
+        private final WordIterator mWordIterator;
+        public SentenceLevelAdapter(Locale locale) {
+            mWordIterator = new WordIterator(locale);
+        }
+
+        private SentenceTextInfoParams getSplitWords(TextInfo originalTextInfo) {
+            final WordIterator wordIterator = mWordIterator;
+            final CharSequence originalText = originalTextInfo.getText();
+            final int cookie = originalTextInfo.getCookie();
+            final int start = 0;
+            final int end = originalText.length();
+            final ArrayList<SentenceWordItem> wordItems = new ArrayList<SentenceWordItem>();
+            wordIterator.setCharSequence(originalText, 0, originalText.length());
+            int wordEnd = wordIterator.following(start);
+            int wordStart = wordIterator.getBeginning(wordEnd);
+            if (DBG) {
+                Log.d(TAG, "iterator: break: ---- 1st word start = " + wordStart + ", end = "
+                        + wordEnd + "\n" + originalText);
+            }
+            while (wordStart <= end && wordEnd != BreakIterator.DONE
+                    && wordStart != BreakIterator.DONE) {
+                if (wordEnd >= start && wordEnd > wordStart) {
+                    final String query = originalText.subSequence(wordStart, wordEnd).toString();
+                    final TextInfo ti = new TextInfo(query, cookie, query.hashCode());
+                    wordItems.add(new SentenceWordItem(ti, wordStart, wordEnd));
+                    if (DBG) {
+                        Log.d(TAG, "Adapter: word (" + (wordItems.size() - 1) + ") " + query);
+                    }
+                }
+                wordEnd = wordIterator.following(wordEnd);
+                if (wordEnd == BreakIterator.DONE) {
+                    break;
+                }
+                wordStart = wordIterator.getBeginning(wordEnd);
+            }
+            if (originalText.length() >= SpellChecker.WORD_ITERATOR_INTERVAL
+                    && wordItems.size() >= 2) {
+                if (DBG) {
+                    Log.w(TAG, "Remove possibly divided word: "
+                            + wordItems.get(0).mTextInfo.getText());
+                }
+                wordItems.remove(0);
+            }
+            return new SentenceTextInfoParams(originalTextInfo, wordItems);
+        }
+
+        public static SentenceSuggestionsInfo reconstructSuggestions(
+                SentenceTextInfoParams originalTextInfoParams, SuggestionsInfo[] results) {
+            if (results == null || results.length == 0) {
+                return null;
+            }
+            if (DBG) {
+                Log.w(TAG, "Adapter: onGetSuggestions: got " + results.length);
+            }
+            if (originalTextInfoParams == null) {
+                if (DBG) {
+                    Log.w(TAG, "Adapter: originalTextInfoParams is null.");
+                }
+                return null;
+            }
+            final int originalCookie = originalTextInfoParams.mOriginalTextInfo.getCookie();
+            final int originalSequence =
+                    originalTextInfoParams.mOriginalTextInfo.getSequence();
+
+            final int querySize = originalTextInfoParams.mSize;
+            final int[] offsets = new int[querySize];
+            final int[] lengths = new int[querySize];
+            final SuggestionsInfo[] reconstructedSuggestions = new SuggestionsInfo[querySize];
+            for (int i = 0; i < querySize; ++i) {
+                final SentenceWordItem item = originalTextInfoParams.mItems.get(i);
+                SuggestionsInfo result = null;
+                for (int j = 0; j < results.length; ++j) {
+                    final SuggestionsInfo cur = results[j];
+                    if (cur != null && cur.getSequence() == item.mTextInfo.getSequence()) {
+                        result = cur;
+                        result.setCookieAndSequence(originalCookie, originalSequence);
+                        break;
+                    }
+                }
+                offsets[i] = item.mStart;
+                lengths[i] = item.mLength;
+                reconstructedSuggestions[i] = result != null ? result : EMPTY_SUGGESTIONS_INFO;
+                if (DBG) {
+                    final int size = reconstructedSuggestions[i].getSuggestionsCount();
+                    Log.w(TAG, "reconstructedSuggestions(" + i + ")" + size + ", first = "
+                            + (size > 0 ? reconstructedSuggestions[i].getSuggestionAt(0)
+                                    : "<none>") + ", offset = " + offsets[i] + ", length = "
+                            + lengths[i]);
+                }
+            }
+            return new SentenceSuggestionsInfo(reconstructedSuggestions, offsets, lengths);
+        }
+    }
 }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 8fe8e40..b70d7b5 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -80,6 +80,8 @@
     void prepareAppTransition(int transit, boolean alwaysKeepCurrent);
     int getPendingAppTransition();
     void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim);
+    void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
+            int startHeight);
     void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
             IRemoteCallback startedCallback);
     void executeAppTransition();
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 32029ba..214dc5c 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -676,7 +676,6 @@
      *
      * @param surfaceTexture The {@link SurfaceTexture} that the view should use.
      * @see SurfaceTexture#detachFromGLContext()
-     * @hide
      */
     public void setSurfaceTexture(SurfaceTexture surfaceTexture) {
         if (surfaceTexture == null) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 962e13a..0ded5f9 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -24,6 +24,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Camera;
 import android.graphics.Canvas;
+import android.graphics.Insets;
 import android.graphics.Interpolator;
 import android.graphics.LinearGradient;
 import android.graphics.Matrix;
@@ -2698,6 +2699,12 @@
     protected int mPaddingBottom;
 
     /**
+     * The layout insets in pixels, that is the distance in pixels between the
+     * visible edges of this view its bounds.
+     */
+    private Insets mLayoutInsets;
+
+    /**
      * Briefly describes the view and is primarily used for accessibility support.
      */
     private CharSequence mContentDescription;
@@ -5807,18 +5814,11 @@
      *
      * @see #FOCUSABLES_ALL
      * @see #FOCUSABLES_TOUCH_MODE
-     * @see #FOCUSABLES_ACCESSIBILITY
      */
     public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
         if (views == null) {
             return;
         }
-        if ((focusableMode & FOCUSABLE_IN_TOUCH_MODE) == FOCUSABLE_IN_TOUCH_MODE) {
-            if (isFocusable() && (!isInTouchMode() || isFocusableInTouchMode())) {
-                views.add(this);
-                return;
-            }
-        }
         if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
             if (AccessibilityManager.getInstance(mContext).isEnabled()
                     && includeForAccessibility()) {
@@ -5826,14 +5826,14 @@
                 return;
             }
         }
-        if ((focusableMode & FOCUSABLES_ALL) == FOCUSABLES_ALL) {
-            if (isFocusable()) {
-                views.add(this);
-                return;
-            }
-        } else {
-            throw new IllegalArgumentException("Unknow focusable mode: " + focusableMode);
+        if (!isFocusable()) {
+            return;
         }
+        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
+                && isInTouchMode() && !isFocusableInTouchMode()) {
+            return;
+        }
+        views.add(this);
     }
 
     /**
@@ -13842,6 +13842,29 @@
     }
 
     /**
+     * @hide
+     */
+    public Insets getLayoutInsets() {
+        if (mLayoutInsets == null) {
+            if (mBackground == null) {
+                mLayoutInsets = Insets.NONE;
+            } else {
+                Rect insetRect = new Rect();
+                boolean hasInsets = mBackground.getLayoutInsets(insetRect);
+                mLayoutInsets = hasInsets ? Insets.of(insetRect) : Insets.NONE;
+            }
+        }
+        return mLayoutInsets;
+    }
+
+    /**
+     * @hide
+     */
+    public void setLayoutInsets(Insets layoutInsets) {
+        mLayoutInsets = layoutInsets;
+    }
+
+    /**
      * Changes the selection state of this view. A view can be selected or not.
      * Note that selection is not the same as focus. Views are typically
      * selected in the context of an AdapterView like ListView or GridView;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 7e90e2b..0b973e5 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -170,6 +170,12 @@
      */
     protected int mGroupFlags;
 
+    /*
+     * THe layout mode: either {@link #UNDEFINED_LAYOUT_MODE}, {@link #COMPONENT_BOUNDS} or
+     * {@link #LAYOUT_BOUNDS}
+     */
+    private int mLayoutMode = UNDEFINED_LAYOUT_MODE;
+
     /**
      * NOTE: If you change the flags below make sure to reflect the changes
      *       the DisplayList class
@@ -335,6 +341,22 @@
      */
     public static final int PERSISTENT_ALL_CACHES = 0x3;
 
+    // Layout Modes
+
+    private static final int UNDEFINED_LAYOUT_MODE = -1;
+
+    /**
+     * This constant is a {@link #setLayoutMode(int) layoutMode}.
+     * Component bounds are the raw values of {@link #getLeft() left}, {@link #getTop() top},
+     * {@link #getRight() right} and {@link #getBottom() bottom}.
+     */
+    public static final int COMPONENT_BOUNDS = 0;
+
+    /**
+     * This constant is a {@link #setLayoutMode(int) layoutMode}.
+     */
+    public static final int LAYOUT_BOUNDS = 1;
+
     /**
      * We clip to padding when FLAG_CLIP_TO_PADDING and FLAG_PADDING_NOT_NULL
      * are set at the same time.
@@ -4424,6 +4446,50 @@
     }
 
     /**
+     * Returns the basis of alignment during the layout of this view group:
+     * either {@link #COMPONENT_BOUNDS} or {@link #LAYOUT_BOUNDS}.
+     *
+     * @return the layout mode to use during layout operations
+     *
+     * @see #setLayoutMode(int)
+     */
+    public int getLayoutMode() {
+        if (mLayoutMode == UNDEFINED_LAYOUT_MODE) {
+            ViewParent parent = getParent();
+            if (parent instanceof ViewGroup) {
+                ViewGroup viewGroup = (ViewGroup) parent;
+                return viewGroup.getLayoutMode();
+            } else {
+                int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
+                boolean preJellyBean = targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN;
+                return preJellyBean ? COMPONENT_BOUNDS : LAYOUT_BOUNDS;
+            }
+
+        }
+        return mLayoutMode;
+    }
+
+    /**
+     * Sets the basis of alignment during alignment of this view group.
+     * Valid values are either {@link #COMPONENT_BOUNDS} or {@link #LAYOUT_BOUNDS}.
+     * <p>
+     * The default is to query the property of the parent if this view group has a parent.
+     * If this ViewGroup is the root of the view hierarchy the default
+     * value is {@link #LAYOUT_BOUNDS} for target SDK's greater than JellyBean,
+     * {@link #LAYOUT_BOUNDS} otherwise.
+     *
+     * @param layoutMode the layout mode to use during layout operations
+     *
+     * @see #getLayoutMode()
+     */
+    public void setLayoutMode(int layoutMode) {
+        if (mLayoutMode != layoutMode) {
+            mLayoutMode = layoutMode;
+            requestLayout();
+        }
+    }
+
+    /**
      * Returns a new set of layout parameters based on the supplied attributes set.
      *
      * @param attrs the attributes to build the layout parameters from
diff --git a/core/java/android/view/textservice/SpellCheckerInfo.java b/core/java/android/view/textservice/SpellCheckerInfo.java
index d05c1af..2167862 100644
--- a/core/java/android/view/textservice/SpellCheckerInfo.java
+++ b/core/java/android/view/textservice/SpellCheckerInfo.java
@@ -45,7 +45,6 @@
     private final ResolveInfo mService;
     private final String mId;
     private final int mLabel;
-    private final boolean mSupportsSentenceSpellCheck;
 
     /**
      * The spell checker setting activity's name, used by the system settings to
@@ -98,9 +97,6 @@
             label = sa.getResourceId(com.android.internal.R.styleable.SpellChecker_label, 0);
             settingsActivityComponent = sa.getString(
                     com.android.internal.R.styleable.SpellChecker_settingsActivity);
-            mSupportsSentenceSpellCheck = sa.getBoolean(
-                    com.android.internal.R.styleable.SpellChecker_supportsSentenceSpellCheck,
-                    false);
             sa.recycle();
 
             final int depth = parser.getDepth();
@@ -142,7 +138,6 @@
      */
     public SpellCheckerInfo(Parcel source) {
         mLabel = source.readInt();
-        mSupportsSentenceSpellCheck = source.readInt() != 0;
         mId = source.readString();
         mSettingsActivityName = source.readString();
         mService = ResolveInfo.CREATOR.createFromParcel(source);
@@ -158,13 +153,6 @@
     }
 
     /**
-     * @hide
-     */
-    public boolean isSentenceSpellCheckSupported() {
-        return mSupportsSentenceSpellCheck;
-    }
-
-    /**
      * Return the component of the service that implements.
      */
     public ComponentName getComponent() {
@@ -188,7 +176,6 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mLabel);
-        dest.writeInt(mSupportsSentenceSpellCheck ? 1 : 0);
         dest.writeString(mId);
         dest.writeString(mSettingsActivityName);
         mService.writeToParcel(dest, flags);
diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java
index 9dc05e4..628da3c 100644
--- a/core/java/android/view/textservice/SpellCheckerSession.java
+++ b/core/java/android/view/textservice/SpellCheckerSession.java
@@ -91,8 +91,6 @@
      * This meta-data must reference an XML resource.
      **/
     public static final String SERVICE_META_DATA = "android.view.textservice.scs";
-    private static final String SUPPORT_SENTENCE_SPELL_CHECK = "SupportSentenceSpellCheck";
-
 
     private static final int MSG_ON_GET_SUGGESTION_MULTIPLE = 1;
     private static final int MSG_ON_GET_SUGGESTION_MULTIPLE_FOR_SENTENCE = 2;
@@ -191,7 +189,9 @@
      * Get candidate strings for a substring of the specified text.
      * @param textInfo text metadata for a spell checker
      * @param suggestionsLimit the maximum number of suggestions that will be returned
+     * @deprecated use {@link SpellCheckerSession#getSentenceSuggestions(TextInfo[], int)} instead
      */
+    @Deprecated
     public void getSuggestions(TextInfo textInfo, int suggestionsLimit) {
         getSuggestions(new TextInfo[] {textInfo}, suggestionsLimit, false);
     }
@@ -201,13 +201,14 @@
      * @param textInfos an array of text metadata for a spell checker
      * @param suggestionsLimit the maximum number of suggestions that will be returned
      * @param sequentialWords true if textInfos can be treated as sequential words.
+     * @deprecated use {@link SpellCheckerSession#getSentenceSuggestions(TextInfo[], int)} instead
      */
+    @Deprecated
     public void getSuggestions(
             TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) {
         if (DBG) {
             Log.w(TAG, "getSuggestions from " + mSpellCheckerInfo.getId());
         }
-        // TODO: Handle multiple words suggestions by using WordBreakIterator
         mSpellCheckerSessionListenerImpl.getSuggestionsMultiple(
                 textInfos, suggestionsLimit, sequentialWords);
     }
@@ -281,7 +282,7 @@
                         break;
                     case TASK_GET_SUGGESTIONS_MULTIPLE_FOR_SENTENCE:
                         if (DBG) {
-                            Log.w(TAG, "Get suggestions from the spell checker.");
+                            Log.w(TAG, "Get sentence suggestions from the spell checker.");
                         }
                         try {
                             session.onGetSentenceSuggestionsMultiple(
@@ -492,11 +493,4 @@
     public ISpellCheckerSessionListener getSpellCheckerSessionListener() {
         return mSpellCheckerSessionListenerImpl;
     }
-
-    /**
-     * @return true if the spell checker supports sentence level spell checking APIs
-     */
-    public boolean isSentenceSpellCheckSupported() {
-        return mSubtype.containsExtraValueKey(SUPPORT_SENTENCE_SPELL_CHECK);
-    }
 }
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 64fbdd5..ab798e8 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -1711,7 +1711,7 @@
 
     void onIsSupportedCallback(boolean isSupported) {
         Message msg = obtainMessage(SEARCHBOX_IS_SUPPORTED_CALLBACK);
-        msg.obj = new Boolean(isSupported);
+        msg.obj = Boolean.valueOf(isSupported);
         sendMessage(msg);
     }
 
diff --git a/core/java/android/webkit/GeolocationPermissions.java b/core/java/android/webkit/GeolocationPermissions.java
index 1441541..a916884 100755
--- a/core/java/android/webkit/GeolocationPermissions.java
+++ b/core/java/android/webkit/GeolocationPermissions.java
@@ -252,7 +252,7 @@
         }
         if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
             boolean allowed = nativeGetAllowed(origin);
-            callback.onReceiveValue(new Boolean(allowed));
+            callback.onReceiveValue(Boolean.valueOf(allowed));
         } else {
             Map values = new HashMap<String, Object>();
             values.put(ORIGIN, origin);
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 105285c..ba48da1 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -190,15 +190,19 @@
     }
 
     /**
-     * Sets whether the WebView should use its built-in zoom mechanisms, as
-     * opposed to separate zoom controls. The built-in zoom mechanisms comprise
-     * on-screen zoom controls, which are displayed over the WebView's content,
-     * and the use of a pinch gesture to control zooming. Whether or not these
-     * on-screen controls are displayed can be set with {@link #setDisplayZoomControls}.
-     * The separate zoom controls are no longer supported, so it is recommended
-     * that this setting is always enabled.
-     * @param enabled Whether the WebView should use the built-in zoom mechanism.
+     * Sets whether the WebView should use its built-in zoom mechanisms. The
+     * built-in zoom mechanisms comprise on-screen zoom controls, which are
+     * displayed over the WebView's content, and the use of a pinch gesture to
+     * control zooming. Whether or not these on-screen controls are displayed
+     * can be set with {@link #setDisplayZoomControls}.
+     * <p>
+     * The built-in mechanisms are the only currently supported zoom
+     * mechanisms, so it is recommended that this setting is always enabled.
+     * @param enabled Whether the WebView should use its built-in zoom mechanisms.
      */
+    // This method was intended to select between the built-in zoom mechanisms
+    // and the separate zoom controls. The latter were obtained using
+    // {@link WebView#getZoomControls}, which is now hidden.
     public void setBuiltInZoomControls(boolean enabled) {
         throw new MustOverrideException();
     }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 5498622..bd10cca 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1530,17 +1530,15 @@
     }
 
     /**
-     * Returns a view containing zoom controls i.e. +/- buttons. The caller is
-     * in charge of installing this view to the view hierarchy. This view will
-     * become visible when the user starts scrolling via touch and fade away if
-     * the user does not interact with it.
+     * Gets the zoom controls for the WebView, as a separate View. The caller is
+     * responsible for inserting this View into the layout hierarchy.
      * <p/>
-     * API version 3 introduces a built-in zoom mechanism that is shown
-     * automatically by the MapView. This is the preferred approach for
-     * showing the zoom UI.
+     * API Level 3 introduced built-in zoom mechanisms for the WebView, as
+     * opposed to these separate zoom controls. The built-in mechanisms are
+     * preferred and can be enabled using
+     * {@link WebSettings#setBuiltInZoomControls}.
      *
-     * @deprecated The built-in zoom mechanism is preferred, see
-     *             {@link WebSettings#setBuiltInZoomControls(boolean)}.
+     * @deprecated The built-in zoom mechanisms are preferred.
      * @hide since API version 16.
      */
     @Deprecated
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 1a2231e..abfc577 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -650,7 +650,8 @@
         mEmptyView = emptyView;
 
         // If not explicitly specified this view is important for accessibility.
-        if (emptyView.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
+        if (emptyView != null
+                && emptyView.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
             emptyView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
         }
 
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 60dd55c..1cb676f5 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -20,6 +20,7 @@
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Insets;
 import android.graphics.Paint;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -559,9 +560,9 @@
         int flags = (gravity & mask) >> shift;
         switch (flags) {
             case (AXIS_SPECIFIED | AXIS_PULL_BEFORE):
-                return LEADING;
+                return horizontal ? LEFT : TOP;
             case (AXIS_SPECIFIED | AXIS_PULL_AFTER):
-                return TRAILING;
+                return horizontal ? RIGHT : BOTTOM;
             case (AXIS_SPECIFIED | AXIS_PULL_BEFORE | AXIS_PULL_AFTER):
                 return FILL;
             case AXIS_SPECIFIED:
@@ -1042,12 +1043,15 @@
             int rightMargin = getMargin(c, true, false);
             int bottomMargin = getMargin(c, false, false);
 
-            // Alignment offsets: the location of the view relative to its alignment group.
-            int alignmentOffsetX = boundsX.getOffset(c, hAlign, leftMargin + pWidth + rightMargin);
-            int alignmentOffsetY = boundsY.getOffset(c, vAlign, topMargin + pHeight + bottomMargin);
+            int sumMarginsX = leftMargin + rightMargin;
+            int sumMarginsY = topMargin + bottomMargin;
 
-            int width = hAlign.getSizeInCell(c, pWidth, cellWidth - leftMargin - rightMargin);
-            int height = vAlign.getSizeInCell(c, pHeight, cellHeight - topMargin - bottomMargin);
+            // Alignment offsets: the location of the view relative to its alignment group.
+            int alignmentOffsetX = boundsX.getOffset(this, c, hAlign, pWidth + sumMarginsX, true);
+            int alignmentOffsetY = boundsY.getOffset(this, c, vAlign, pHeight + sumMarginsY, false);
+
+            int width = hAlign.getSizeInCell(c, pWidth, cellWidth - sumMarginsX);
+            int height = vAlign.getSizeInCell(c, pHeight, cellHeight - sumMarginsY);
 
             int dx = x1 + gravityOffsetX + alignmentOffsetX;
 
@@ -1181,7 +1185,7 @@
                 View c = getChildAt(i);
                 LayoutParams lp = getLayoutParams(c);
                 Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
-                groupBounds.getValue(i).include(c, spec, GridLayout.this, this);
+                groupBounds.getValue(i).include(GridLayout.this, c, spec, this);
             }
         }
 
@@ -2138,16 +2142,30 @@
             return before + after;
         }
 
-        protected int getOffset(View c, Alignment alignment, int size) {
-            return before - alignment.getAlignmentValue(c, size);
+        private int getAlignmentValue(GridLayout gl, View c, int size, Alignment a, boolean horiz) {
+            boolean useLayoutBounds = gl.getLayoutMode() == LAYOUT_BOUNDS;
+            if (!useLayoutBounds) {
+                return a.getAlignmentValue(c, size);
+            } else {
+                Insets insets = c.getLayoutInsets();
+                int leadingInset = horiz ? insets.left : insets.top; // RTL?
+                int trailingInset = horiz ? insets.right : insets.bottom; // RTL?
+                int totalInset = leadingInset + trailingInset;
+                return leadingInset + a.getAlignmentValue(c, size - totalInset);
+            }
         }
 
-        protected final void include(View c, Spec spec, GridLayout gridLayout, Axis axis) {
+        protected int getOffset(GridLayout gl, View c, Alignment a, int size, boolean horizontal) {
+            return before - getAlignmentValue(gl, c, size, a, horizontal);
+        }
+
+        protected final void include(GridLayout gl, View c, Spec spec, Axis axis) {
             this.flexibility &= spec.getFlexibility();
-            int size = gridLayout.getMeasurementIncludingMargin(c, axis.horizontal);
-            Alignment alignment = gridLayout.getAlignment(spec.alignment, axis.horizontal);
+            boolean horizontal = axis.horizontal;
+            int size = gl.getMeasurementIncludingMargin(c, horizontal);
+            Alignment alignment = gl.getAlignment(spec.alignment, horizontal);
             // todo test this works correctly when the returned value is UNDEFINED
-            int before = alignment.getAlignmentValue(c, size);
+            int before = getAlignmentValue(gl, c, size, alignment, horizontal);
             include(before, size - before);
         }
 
@@ -2614,8 +2632,8 @@
                 }
 
                 @Override
-                protected int getOffset(View c, Alignment alignment, int size) {
-                    return max(0, super.getOffset(c, alignment, size));
+                protected int getOffset(GridLayout gl, View c, Alignment a, int size, boolean hrz) {
+                    return max(0, super.getOffset(gl, c, a, size, hrz));
                 }
             };
         }
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index c725b64..e188207 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -116,7 +116,7 @@
                     null /* Bundle not currently used by the textServicesManager */,
                     mCurrentLocale, this,
                     false /* means any available languages from current spell checker */);
-            mIsSentenceSpellCheckSupported = mSpellCheckerSession.isSentenceSpellCheckSupported();
+            mIsSentenceSpellCheckSupported = true;
         }
 
         // Restore SpellCheckSpans in pool
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index f1dffa1..1ba6d43 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -51,6 +51,7 @@
 import android.view.ViewGroup;
 import android.view.Window;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.animation.AnimationUtils;
 import android.widget.SpinnerAdapter;
 
 import java.lang.ref.WeakReference;
@@ -596,19 +597,23 @@
         if (mCurWindowVisibility == View.VISIBLE && (mShowHideAnimationEnabled
                 || alwaysAnimate)) {
             mTopVisibilityView.setAlpha(0);
+            mTopVisibilityView.setTranslationY(-mTopVisibilityView.getHeight());
             AnimatorSet anim = new AnimatorSet();
             AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mTopVisibilityView, "alpha", 1));
+            b.with(ObjectAnimator.ofFloat(mTopVisibilityView, "translationY", 0));
             if (mContentView != null) {
                 b.with(ObjectAnimator.ofFloat(mContentView, "translationY",
                         -mTopVisibilityView.getHeight(), 0));
-                mTopVisibilityView.setTranslationY(-mTopVisibilityView.getHeight());
-                b.with(ObjectAnimator.ofFloat(mTopVisibilityView, "translationY", 0));
             }
             if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
                 mSplitView.setAlpha(0);
+                mSplitView.setTranslationY(mSplitView.getHeight());
                 mSplitView.setVisibility(View.VISIBLE);
                 b.with(ObjectAnimator.ofFloat(mSplitView, "alpha", 1));
+                b.with(ObjectAnimator.ofFloat(mSplitView, "translationY", 0));
             }
+            anim.setInterpolator(AnimationUtils.loadInterpolator(mContext,
+                    com.android.internal.R.interpolator.decelerate_quad));
             anim.addListener(mShowListener);
             mCurrentShowAnim = anim;
             anim.start();
@@ -638,16 +643,20 @@
             mContainerView.setTransitioning(true);
             AnimatorSet anim = new AnimatorSet();
             AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mTopVisibilityView, "alpha", 0));
+            b.with(ObjectAnimator.ofFloat(mTopVisibilityView, "translationY",
+                    -mTopVisibilityView.getHeight()));
             if (mContentView != null) {
                 b.with(ObjectAnimator.ofFloat(mContentView, "translationY",
                         0, -mTopVisibilityView.getHeight()));
-                b.with(ObjectAnimator.ofFloat(mTopVisibilityView, "translationY",
-                        -mTopVisibilityView.getHeight()));
             }
             if (mSplitView != null && mSplitView.getVisibility() == View.VISIBLE) {
                 mSplitView.setAlpha(1);
                 b.with(ObjectAnimator.ofFloat(mSplitView, "alpha", 0));
+                b.with(ObjectAnimator.ofFloat(mSplitView, "translationY",
+                        mSplitView.getHeight()));
             }
+            anim.setInterpolator(AnimationUtils.loadInterpolator(mContext,
+                    com.android.internal.R.interpolator.accelerate_quad));
             anim.addListener(mHideListener);
             mCurrentShowAnim = anim;
             anim.start();
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index e00a853..6a09fe07 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -888,4 +888,19 @@
             ;
         }
     }
+
+    public static boolean nextElementWithin(XmlPullParser parser, int outerDepth)
+            throws IOException, XmlPullParserException {
+        for (;;) {
+            int type = parser.next();
+            if (type == XmlPullParser.END_DOCUMENT
+                    || (type == XmlPullParser.END_TAG && parser.getDepth() == outerDepth)) {
+                return false;
+            }
+            if (type == XmlPullParser.START_TAG
+                    && parser.getDepth() == outerDepth + 1) {
+                return true;
+            }
+        }
+    }
 }
diff --git a/core/java/com/android/internal/widget/SizeAdaptiveLayout.java b/core/java/com/android/internal/widget/SizeAdaptiveLayout.java
new file mode 100644
index 0000000..adfd3dc
--- /dev/null
+++ b/core/java/com/android/internal/widget/SizeAdaptiveLayout.java
@@ -0,0 +1,405 @@
+/*
+ * Copyright (C) 2012 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.widget;
+
+import com.android.internal.R;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewDebug;
+import android.view.ViewGroup;
+import android.widget.RemoteViews.RemoteView;
+
+/**
+ * A layout that switches between its children based on the requested layout height.
+ * Each child specifies its minimum and maximum valid height.  Results are undefined
+ * if children specify overlapping ranges.  A child may specify the maximum height
+ * as 'unbounded' to indicate that it is willing to be displayed arbitrarily tall.
+ *
+ * <p>
+ * See {@link SizeAdaptiveLayout.LayoutParams} for a full description of the
+ * layout parameters used by SizeAdaptiveLayout.
+ */
+@RemoteView
+public class SizeAdaptiveLayout extends ViewGroup {
+
+    private static final String TAG = "SizeAdaptiveLayout";
+    private static final boolean DEBUG = false;
+    private static final long CROSSFADE_TIME = 250;
+
+    // TypedArray indices
+    private static final int MIN_VALID_HEIGHT =
+            R.styleable.SizeAdaptiveLayout_Layout_layout_minHeight;
+    private static final int MAX_VALID_HEIGHT =
+            R.styleable.SizeAdaptiveLayout_Layout_layout_maxHeight;
+
+    // view state
+    private View mActiveChild;
+    private View mLastActive;
+
+    // animation state
+    private AnimatorSet mTransitionAnimation;
+    private AnimatorListener mAnimatorListener;
+    private ObjectAnimator mFadePanel;
+    private ObjectAnimator mFadeView;
+    private int mCanceledAnimationCount;
+    private View mEnteringView;
+    private View mLeavingView;
+    // View used to hide larger views under smaller ones to create a uniform crossfade
+    private View mModestyPanel;
+    private int mModestyPanelTop;
+
+    public SizeAdaptiveLayout(Context context) {
+        super(context);
+        initialize();
+    }
+
+    public SizeAdaptiveLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        initialize();
+    }
+
+    public SizeAdaptiveLayout(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        initialize();
+    }
+
+    private void initialize() {
+        mModestyPanel = new View(getContext());
+        // If the SizeAdaptiveLayout has a solid background, use it as a transition hint.
+        if (getBackground() instanceof ColorDrawable) {
+            mModestyPanel.setBackgroundDrawable(getBackground());
+        } else {
+            mModestyPanel.setBackgroundColor(Color.BLACK);
+        }
+        SizeAdaptiveLayout.LayoutParams layout =
+                new SizeAdaptiveLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+                                                    ViewGroup.LayoutParams.MATCH_PARENT);
+        mModestyPanel.setLayoutParams(layout);
+        addView(mModestyPanel);
+        mFadePanel = ObjectAnimator.ofFloat(mModestyPanel, "alpha", 0f);
+        mFadeView = ObjectAnimator.ofFloat(null, "alpha", 0f);
+        mAnimatorListener = new BringToFrontOnEnd();
+        mTransitionAnimation = new AnimatorSet();
+        mTransitionAnimation.play(mFadeView).with(mFadePanel);
+        mTransitionAnimation.setDuration(CROSSFADE_TIME);
+        mTransitionAnimation.addListener(mAnimatorListener);
+    }
+
+    /**
+     * Visible for testing
+     * @hide
+     */
+    public Animator getTransitionAnimation() {
+        return mTransitionAnimation;
+    }
+
+    /**
+     * Visible for testing
+     * @hide
+     */
+    public View getModestyPanel() {
+        return mModestyPanel;
+    }
+
+    @Override
+    public void onAttachedToWindow() {
+        mLastActive = null;
+        // make sure all views start off invisible.
+        for (int i = 0; i < getChildCount(); i++) {
+            getChildAt(i).setVisibility(View.GONE);
+        }
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        if (DEBUG) Log.d(TAG, this + " measure spec: " +
+                         MeasureSpec.toString(heightMeasureSpec));
+        View model = selectActiveChild(heightMeasureSpec);
+        SizeAdaptiveLayout.LayoutParams lp =
+          (SizeAdaptiveLayout.LayoutParams) model.getLayoutParams();
+        if (DEBUG) Log.d(TAG, "active min: " + lp.minHeight + " max: " + lp.maxHeight);
+        measureChild(model, widthMeasureSpec, heightMeasureSpec);
+        int childHeight = model.getMeasuredHeight();
+        int childWidth = model.getMeasuredHeight();
+        int childState = combineMeasuredStates(0, model.getMeasuredState());
+        if (DEBUG) Log.d(TAG, "measured child at: " + childHeight);
+        int resolvedWidth = resolveSizeAndState(childWidth, widthMeasureSpec, childState);
+        int resolvedheight = resolveSizeAndState(childHeight, heightMeasureSpec, childState);
+        setMeasuredDimension(resolvedWidth, resolvedheight);
+        if (DEBUG) Log.d(TAG, "resolved to: " + resolvedheight);
+    }
+
+    //TODO extend to width and height
+    private View selectActiveChild(int heightMeasureSpec) {
+        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+
+        View unboundedView = null;
+        View tallestView = null;
+        int tallestViewSize = 0;
+        View smallestView = null;
+        int smallestViewSize = Integer.MAX_VALUE;
+        for (int i = 0; i < getChildCount(); i++) {
+            View child = getChildAt(i);
+            if (child != mModestyPanel) {
+                SizeAdaptiveLayout.LayoutParams lp =
+                    (SizeAdaptiveLayout.LayoutParams) child.getLayoutParams();
+                if (DEBUG) Log.d(TAG, "looking at " + i +
+                                 " with min: " + lp.minHeight +
+                                 " max: " +  lp.maxHeight);
+                if (lp.maxHeight == SizeAdaptiveLayout.LayoutParams.UNBOUNDED &&
+                    unboundedView == null) {
+                    unboundedView = child;
+                }
+                if (lp.maxHeight > tallestViewSize) {
+                    tallestViewSize = lp.maxHeight;
+                    tallestView = child;
+                }
+                if (lp.minHeight < smallestViewSize) {
+                    smallestViewSize = lp.minHeight;
+                    smallestView = child;
+                }
+                if (heightMode != MeasureSpec.UNSPECIFIED &&
+                    heightSize >= lp.minHeight && heightSize <= lp.maxHeight) {
+                    if (DEBUG) Log.d(TAG, "  found exact match, finishing early");
+                    return child;
+                }
+            }
+        }
+        if (unboundedView != null) {
+            tallestView = unboundedView;
+        }
+        if (heightMode == MeasureSpec.UNSPECIFIED) {
+            return tallestView;
+        }
+        if (heightSize > tallestViewSize) {
+            return tallestView;
+        }
+        return smallestView;
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        if (DEBUG) Log.d(TAG, this + " onlayout height: " + (bottom - top));
+        mLastActive = mActiveChild;
+        int measureSpec = View.MeasureSpec.makeMeasureSpec(bottom - top,
+                                                           View.MeasureSpec.EXACTLY);
+        mActiveChild = selectActiveChild(measureSpec);
+        mActiveChild.setVisibility(View.VISIBLE);
+
+        if (mLastActive != mActiveChild && mLastActive != null) {
+            if (DEBUG) Log.d(TAG, this + " changed children from: " + mLastActive +
+                    " to: " + mActiveChild);
+
+            mEnteringView = mActiveChild;
+            mLeavingView = mLastActive;
+
+            mEnteringView.setAlpha(1f);
+
+            mModestyPanel.setAlpha(1f);
+            mModestyPanel.bringToFront();
+            mModestyPanelTop = mLeavingView.getHeight();
+            mModestyPanel.setVisibility(View.VISIBLE);
+            // TODO: mModestyPanel background should be compatible with mLeavingView
+
+            mLeavingView.bringToFront();
+
+            if (mTransitionAnimation.isRunning()) {
+                mTransitionAnimation.cancel();
+            }
+            mFadeView.setTarget(mLeavingView);
+            mFadeView.setFloatValues(0f);
+            mFadePanel.setFloatValues(0f);
+            mTransitionAnimation.setupStartValues();
+            mTransitionAnimation.start();
+        }
+        final int childWidth = mActiveChild.getMeasuredWidth();
+        final int childHeight = mActiveChild.getMeasuredHeight();
+        // TODO investigate setting LAYER_TYPE_HARDWARE on mLastActive
+        mActiveChild.layout(0, 0, 0 + childWidth, 0 + childHeight);
+
+        if (DEBUG) Log.d(TAG, "got modesty offset of " + mModestyPanelTop);
+        mModestyPanel.layout(0, mModestyPanelTop, 0 + childWidth, mModestyPanelTop + childHeight);
+    }
+
+    @Override
+    public LayoutParams generateLayoutParams(AttributeSet attrs) {
+        if (DEBUG) Log.d(TAG, "generate layout from attrs");
+        return new SizeAdaptiveLayout.LayoutParams(getContext(), attrs);
+    }
+
+    @Override
+    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+        if (DEBUG) Log.d(TAG, "generate default layout from viewgroup");
+        return new SizeAdaptiveLayout.LayoutParams(p);
+    }
+
+    @Override
+    protected LayoutParams generateDefaultLayoutParams() {
+        if (DEBUG) Log.d(TAG, "generate default layout from null");
+        return new SizeAdaptiveLayout.LayoutParams();
+    }
+
+    @Override
+    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+        return p instanceof SizeAdaptiveLayout.LayoutParams;
+    }
+
+    /**
+     * Per-child layout information associated with ViewSizeAdaptiveLayout.
+     *
+     * TODO extend to width and height
+     *
+     * @attr ref android.R.styleable#SizeAdaptiveLayout_Layout_layout_minHeight
+     * @attr ref android.R.styleable#SizeAdaptiveLayout_Layout_layout_maxHeight
+     */
+    public static class LayoutParams extends ViewGroup.LayoutParams {
+
+        /**
+         * Indicates the minimum valid height for the child.
+         */
+        @ViewDebug.ExportedProperty(category = "layout")
+        public int minHeight;
+
+        /**
+         * Indicates the maximum valid height for the child.
+         */
+        @ViewDebug.ExportedProperty(category = "layout")
+        public int maxHeight;
+
+        /**
+         * Constant value for maxHeight that indicates there is not maximum height.
+         */
+        public static final int UNBOUNDED = -1;
+
+        /**
+         * {@inheritDoc}
+         */
+        public LayoutParams(Context c, AttributeSet attrs) {
+            super(c, attrs);
+            if (DEBUG) {
+                Log.d(TAG, "construct layout from attrs");
+                for (int i = 0; i < attrs.getAttributeCount(); i++) {
+                    Log.d(TAG, " " + attrs.getAttributeName(i) + " = " +
+                          attrs.getAttributeValue(i));
+                }
+            }
+            TypedArray a =
+                    c.obtainStyledAttributes(attrs,
+                            R.styleable.SizeAdaptiveLayout_Layout);
+
+            minHeight = a.getDimensionPixelSize(MIN_VALID_HEIGHT, 0);
+            if (DEBUG) Log.d(TAG, "got minHeight of: " + minHeight);
+
+            try {
+                maxHeight = a.getLayoutDimension(MAX_VALID_HEIGHT, UNBOUNDED);
+                if (DEBUG) Log.d(TAG, "got maxHeight of: " + maxHeight);
+            } catch (Exception e) {
+                if (DEBUG) Log.d(TAG, "caught exception looking for maxValidHeight " + e);
+            }
+
+            a.recycle();
+        }
+
+        /**
+         * Creates a new set of layout parameters with the specified width, height
+         * and valid height bounds.
+         *
+         * @param width the width, either {@link #MATCH_PARENT},
+         *        {@link #WRAP_CONTENT} or a fixed size in pixels
+         * @param height the height, either {@link #MATCH_PARENT},
+         *        {@link #WRAP_CONTENT} or a fixed size in pixels
+         * @param minHeight the minimum height of this child
+         * @param maxHeight the maximum height of this child
+         *        or {@link #UNBOUNDED} if the child can grow forever
+         */
+        public LayoutParams(int width, int height, int minHeight, int maxHeight) {
+            super(width, height);
+            this.minHeight = minHeight;
+            this.maxHeight = maxHeight;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public LayoutParams(int width, int height) {
+            this(width, height, UNBOUNDED, UNBOUNDED);
+        }
+
+        /**
+         * Constructs a new LayoutParams with default values as defined in {@link LayoutParams}.
+         */
+        public LayoutParams() {
+            this(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public LayoutParams(ViewGroup.LayoutParams p) {
+            super(p);
+            minHeight = UNBOUNDED;
+            maxHeight = UNBOUNDED;
+        }
+
+        public String debug(String output) {
+            return output + "SizeAdaptiveLayout.LayoutParams={" +
+                    ", max=" + maxHeight +
+                    ", max=" + minHeight + "}";
+        }
+    }
+
+    class BringToFrontOnEnd implements AnimatorListener {
+        @Override
+            public void onAnimationEnd(Animator animation) {
+            if (mCanceledAnimationCount == 0) {
+                mLeavingView.setVisibility(View.GONE);
+                mModestyPanel.setVisibility(View.GONE);
+                mEnteringView.bringToFront();
+                mEnteringView = null;
+                mLeavingView = null;
+            } else {
+                mCanceledAnimationCount--;
+            }
+        }
+
+        @Override
+            public void onAnimationCancel(Animator animation) {
+            mCanceledAnimationCount++;
+        }
+
+        @Override
+            public void onAnimationRepeat(Animator animation) {
+            if (DEBUG) Log.d(TAG, "fade animation repeated: should never happen.");
+            assert(false);
+        }
+
+        @Override
+            public void onAnimationStart(Animator animation) {
+        }
+    }
+}
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 202abf6..9abfb3a 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -179,6 +179,6 @@
 
 int register_android_hardware_SensorManager(JNIEnv *env)
 {
-    return jniRegisterNativeMethods(env, "android/hardware/SensorManager",
+    return jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager",
             gMethods, NELEM(gMethods));
 }
diff --git a/core/jni/android_net_TrafficStats.cpp b/core/jni/android_net_TrafficStats.cpp
index 0ab659b..325fe26 100644
--- a/core/jni/android_net_TrafficStats.cpp
+++ b/core/jni/android_net_TrafficStats.cpp
@@ -31,6 +31,9 @@
 
 namespace android {
 
+static const uint64_t VALUE_UNKNOWN = -1;
+static const char* IFACE_STAT_ALL = "/proc/net/xt_qtaguid/iface_stat_all";
+
 enum Tx_Rx {
     TX,
     RX
@@ -42,6 +45,21 @@
     TCP_AND_UDP
 };
 
+// NOTE: keep these in sync with TrafficStats.java
+enum IfaceStatType {
+    RX_BYTES = 0,
+    RX_PACKETS = 1,
+    TX_BYTES = 2,
+    TX_PACKETS = 3
+};
+
+struct IfaceStat {
+    uint64_t rxBytes;
+    uint64_t rxPackets;
+    uint64_t txBytes;
+    uint64_t txPackets;
+};
+
 // Returns an ASCII decimal number read from the specified file, -1 on error.
 static jlong readNumber(char const* filename) {
     char buf[80];
@@ -63,130 +81,82 @@
     return atoll(buf);
 }
 
-static const char* mobile_iface_list[] = {
-    "rmnet0",
-    "rmnet1",
-    "rmnet2",
-    "rmnet3",
-    "cdma_rmnet4",
-    "ppp0",
-    0
-};
+static int parseIfaceStat(const char* iface, struct IfaceStat* stat) {
+    FILE *fp = fopen(IFACE_STAT_ALL, "r");
+    if (!fp) {
+        return errno;
+    }
 
-static jlong getAll(const char** iface_list, const char* what) {
+    char buffer[256];
+    char cur_iface[32];
+    int active;
+    uint64_t rxBytes, rxPackets, txBytes, txPackets, devRxBytes, devRxPackets, devTxBytes,
+            devTxPackets;
 
-    char filename[80];
-    int idx = 0;
-    bool supported = false;
-    jlong total = 0;
-    while (iface_list[idx] != 0) {
-
-        snprintf(filename, sizeof(filename), "/sys/class/net/%s/statistics/%s",
-                 iface_list[idx], what);
-        jlong number = readNumber(filename);
-        if (number >= 0) {
-            supported = true;
-            total += number;
+    while (fgets(buffer, 256, fp) != NULL) {
+        if (sscanf(buffer, "%31s %d %llu %llu %llu %llu %llu %llu %llu %llu", cur_iface, &active,
+                   &rxBytes, &rxPackets, &txBytes, &txPackets, &devRxBytes, &devRxPackets,
+                   &devTxBytes, &devTxPackets) != 10) {
+            continue;
         }
-        idx++;
-    }
-    if (supported) return total;
 
-    return -1;
-}
+        if (!iface || !strcmp(iface, cur_iface)) {
+            stat->rxBytes += rxBytes;
+            stat->rxPackets += rxPackets;
+            stat->txBytes += txBytes;
+            stat->txPackets += txPackets;
 
-// Returns the sum of numbers from the specified path under /sys/class/net/*,
-// -1 if no such file exists.
-static jlong readTotal(char const* suffix) {
-    char filename[PATH_MAX] = "/sys/class/net/";
-    DIR *dir = opendir(filename);
-    if (dir == NULL) {
-        ALOGE("Can't list %s: %s", filename, strerror(errno));
-        return -1;
-    }
-
-    int len = strlen(filename);
-    jlong total = -1;
-    while (struct dirent *entry = readdir(dir)) {
-        // Skip ., .., and localhost interfaces.
-        if (entry->d_name[0] != '.' && strncmp(entry->d_name, "lo", 2) != 0) {
-            strlcpy(filename + len, entry->d_name, sizeof(filename) - len);
-            strlcat(filename, suffix, sizeof(filename));
-            jlong num = readNumber(filename);
-            if (num >= 0) total = total < 0 ? num : total + num;
+            if (active) {
+                stat->rxBytes += devRxBytes;
+                stat->rxPackets += devRxPackets;
+                stat->txBytes += devTxBytes;
+                stat->txPackets += devTxPackets;
+            }
         }
     }
 
-    closedir(dir);
-    return total;
+    fclose(fp);
+    return 0;
 }
 
-// Mobile stats get accessed a lot more often than total stats.
-// Note the individual files can come and go at runtime, so we check
-// each file every time (rather than caching which ones exist).
+static uint64_t getIfaceStatType(const char* iface, IfaceStatType type) {
+    struct IfaceStat stat;
+    memset(&stat, 0, sizeof(IfaceStat));
 
-static jlong getMobileTxPackets(JNIEnv* env, jobject clazz) {
-    return getAll(mobile_iface_list, "tx_packets");
-}
-
-static jlong getMobileRxPackets(JNIEnv* env, jobject clazz) {
-    return getAll(mobile_iface_list, "rx_packets");
-}
-
-static jlong getMobileTxBytes(JNIEnv* env, jobject clazz) {
-    return getAll(mobile_iface_list, "tx_bytes");
-}
-
-static jlong getMobileRxBytes(JNIEnv* env, jobject clazz) {
-    return getAll(mobile_iface_list, "rx_bytes");
-}
-
-static jlong getData(JNIEnv* env, const char* what, jstring javaInterface) {
-    ScopedUtfChars interface(env, javaInterface);
-    if (interface.c_str() == NULL) {
-        return -1;
+    if (parseIfaceStat(iface, &stat)) {
+        return VALUE_UNKNOWN;
     }
 
-    char filename[80];
-    snprintf(filename, sizeof(filename), "/sys/class/net/%s/statistics/%s", interface.c_str(), what);
-    return readNumber(filename);
+    switch (type) {
+        case RX_BYTES:
+            return stat.rxBytes;
+        case RX_PACKETS:
+            return stat.rxPackets;
+        case TX_BYTES:
+            return stat.txBytes;
+        case TX_PACKETS:
+            return stat.txPackets;
+        default:
+            return VALUE_UNKNOWN;
+    }
 }
 
-static jlong getTxPackets(JNIEnv* env, jobject clazz, jstring interface) {
-    return getData(env, "tx_packets", interface);
+static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type) {
+    return getIfaceStatType(NULL, (IfaceStatType) type);
 }
 
-static jlong getRxPackets(JNIEnv* env, jobject clazz, jstring interface) {
-    return getData(env, "rx_packets", interface);
+static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) {
+    struct IfaceStat stat;
+    const char* ifaceChars = env->GetStringUTFChars(iface, NULL);
+    if (ifaceChars) {
+        uint64_t stat = getIfaceStatType(ifaceChars, (IfaceStatType) type);
+        env->ReleaseStringUTFChars(iface, ifaceChars);
+        return stat;
+    } else {
+        return VALUE_UNKNOWN;
+    }
 }
 
-static jlong getTxBytes(JNIEnv* env, jobject clazz, jstring interface) {
-    return getData(env, "tx_bytes", interface);
-}
-
-static jlong getRxBytes(JNIEnv* env, jobject clazz, jstring interface) {
-    return getData(env, "rx_bytes", interface);
-}
-
-
-// Total stats are read less often, so we're willing to put up
-// with listing the directory and concatenating filenames.
-
-static jlong getTotalTxPackets(JNIEnv* env, jobject clazz) {
-    return readTotal("/statistics/tx_packets");
-}
-
-static jlong getTotalRxPackets(JNIEnv* env, jobject clazz) {
-    return readTotal("/statistics/rx_packets");
-}
-
-static jlong getTotalTxBytes(JNIEnv* env, jobject clazz) {
-    return readTotal("/statistics/tx_bytes");
-}
-
-static jlong getTotalRxBytes(JNIEnv* env, jobject clazz) {
-    return readTotal("/statistics/rx_bytes");
-}
 
 // Per-UID stats require reading from a constructed filename.
 
@@ -323,18 +293,8 @@
 }
 
 static JNINativeMethod gMethods[] = {
-    {"getMobileTxPackets", "()J", (void*) getMobileTxPackets},
-    {"getMobileRxPackets", "()J", (void*) getMobileRxPackets},
-    {"getMobileTxBytes", "()J", (void*) getMobileTxBytes},
-    {"getMobileRxBytes", "()J", (void*) getMobileRxBytes},
-    {"getTxPackets", "(Ljava/lang/String;)J", (void*) getTxPackets},
-    {"getRxPackets", "(Ljava/lang/String;)J", (void*) getRxPackets},
-    {"getTxBytes", "(Ljava/lang/String;)J", (void*) getTxBytes},
-    {"getRxBytes", "(Ljava/lang/String;)J", (void*) getRxBytes},
-    {"getTotalTxPackets", "()J", (void*) getTotalTxPackets},
-    {"getTotalRxPackets", "()J", (void*) getTotalRxPackets},
-    {"getTotalTxBytes", "()J", (void*) getTotalTxBytes},
-    {"getTotalRxBytes", "()J", (void*) getTotalRxBytes},
+    {"nativeGetTotalStat", "(I)J", (void*) getTotalStat},
+    {"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*) getIfaceStat},
 
     /* Per-UID Stats */
     {"getUidTxBytes", "(I)J", (void*) getUidTxBytes},
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index ce2cdee..31b914a 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -198,7 +198,7 @@
     return surface;
 }
 
-static void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface)
+void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface)
 {
     Surface* const p = (Surface*)env->GetIntField(clazz, so.surface);
     if (surface.get()) {
diff --git a/core/res/res/anim/dock_bottom_enter.xml b/core/res/res/anim/dock_bottom_enter.xml
index 7a2e94b..74a021b 100644
--- a/core/res/res/anim/dock_bottom_enter.xml
+++ b/core/res/res/anim/dock_bottom_enter.xml
@@ -19,8 +19,6 @@
 <!-- Animation for when a dock window at the bottom of the screen is entering. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/decelerate_quad">
-    <translate android:fromYDelta="75%" android:toYDelta="0"
+    <translate android:fromYDelta="100%" android:toYDelta="0"
         android:duration="@android:integer/config_mediumAnimTime"/>
-    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
-        android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/dock_bottom_exit.xml b/core/res/res/anim/dock_bottom_exit.xml
index c2fd15c..213b3d9 100644
--- a/core/res/res/anim/dock_bottom_exit.xml
+++ b/core/res/res/anim/dock_bottom_exit.xml
@@ -19,8 +19,6 @@
 <!-- Animation for when a dock window at the bottom of the screen is exiting. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/accelerate_quad">
-    <translate android:fromYDelta="0" android:toYDelta="75%"
+    <translate android:fromYDelta="0" android:toYDelta="100%"
         android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
-    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-        android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/dock_left_enter.xml b/core/res/res/anim/dock_left_enter.xml
index b057f67..4fce35a 100644
--- a/core/res/res/anim/dock_left_enter.xml
+++ b/core/res/res/anim/dock_left_enter.xml
@@ -19,8 +19,6 @@
 <!-- Animation for when a dock window at the left of the screen is entering. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/decelerate_quad">
-    <translate android:fromXDelta="-75%" android:toXDelta="0"
+    <translate android:fromXDelta="-100%" android:toXDelta="0"
         android:duration="@android:integer/config_mediumAnimTime"/>
-    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
-        android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/dock_left_exit.xml b/core/res/res/anim/dock_left_exit.xml
index 576b1aa..bce203d 100644
--- a/core/res/res/anim/dock_left_exit.xml
+++ b/core/res/res/anim/dock_left_exit.xml
@@ -19,8 +19,6 @@
 <!-- Animation for when a dock window at the right of the screen is exiting. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/accelerate_quad">
-    <translate android:fromXDelta="0" android:toXDelta="-75%"
+    <translate android:fromXDelta="0" android:toXDelta="-100%"
         android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
-    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-        android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/dock_right_enter.xml b/core/res/res/anim/dock_right_enter.xml
index e1bd190..26b8ad6 100644
--- a/core/res/res/anim/dock_right_enter.xml
+++ b/core/res/res/anim/dock_right_enter.xml
@@ -19,8 +19,6 @@
 <!-- Animation for when a dock window at the right of the screen is entering. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/decelerate_quad">
-    <translate android:fromXDelta="75%" android:toXDelta="0"
+    <translate android:fromXDelta="100%" android:toXDelta="0"
         android:duration="@android:integer/config_mediumAnimTime"/>
-    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
-        android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/dock_right_exit.xml b/core/res/res/anim/dock_right_exit.xml
index 6d778fa..6beda59 100644
--- a/core/res/res/anim/dock_right_exit.xml
+++ b/core/res/res/anim/dock_right_exit.xml
@@ -19,8 +19,6 @@
 <!-- Animation for when a dock window at the right of the screen is exiting. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/accelerate_quad">
-    <translate android:fromXDelta="0" android:toXDelta="75%"
+    <translate android:fromXDelta="0" android:toXDelta="100%"
         android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
-    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-        android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/dock_top_enter.xml b/core/res/res/anim/dock_top_enter.xml
index f2e4cae..594b479 100644
--- a/core/res/res/anim/dock_top_enter.xml
+++ b/core/res/res/anim/dock_top_enter.xml
@@ -19,8 +19,6 @@
 <!-- Animation for when a dock window at the top of the screen is entering. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/decelerate_quad">
-    <translate android:fromYDelta="-75%" android:toYDelta="0"
+    <translate android:fromYDelta="-100%" android:toYDelta="0"
         android:duration="@android:integer/config_mediumAnimTime"/>
-    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
-        android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/dock_top_exit.xml b/core/res/res/anim/dock_top_exit.xml
index 7373695..b9691f6 100644
--- a/core/res/res/anim/dock_top_exit.xml
+++ b/core/res/res/anim/dock_top_exit.xml
@@ -19,8 +19,6 @@
 <!-- Animation for when a dock window at the top of the screen is exiting. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/accelerate_quad">
-    <translate android:fromYDelta="0" android:toYDelta="-75%"
+    <translate android:fromYDelta="0" android:toYDelta="-100%"
         android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
-    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-        android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 25fc3a0..d299436 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1007,11 +1007,17 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Voer die vereiste PIN in:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Voeg karakter in"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Onbekend program"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Stuur SMS-boodskappe"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"\'n Groot aantal SMS-boodskappe word gestuur. Raak OK om voort te gaan, of Kanselleer om op te hou stuur."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Kanselleer"</string>
+    <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; stuur \'n groot aantal SMS-boodskappe. Wil jy hierdie program toelaat om voort te gaan om boodskappe te stuur?"</string>
+    <string name="sms_control_yes" msgid="3663725993855816807">"Laat toe"</string>
+    <string name="sms_control_no" msgid="625438561395534982">"Weier"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Stuur SMS na kortkode?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Stuur \'n premium SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; wil graag \'n SMS stuur aan &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, wat lyk asof dit \'n SMS-kortkode is.&lt;p&gt;Die stuur van SMS\'e na sommige kortkodes kan veroorsaak dat jou selfoonrekening gedebiteer word vir premium dienste.&lt;p&gt;Wil jy hierdie program toelaat om die boodskap te stuur?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; wil graag \'n SMS stuur aan &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, wat \'n betaalde SMS-kortkode is.&lt;p&gt;&lt;b&gt;As jy \'n boodskap na hierdie bestemming stuur, sal jou selfoonrekening gedebiteer word vir betaalde dienste.&lt;/b&gt;&lt;p&gt;Wil jy hierdie program toelaat om die boodskap te stuur?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Stuur boodskap"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Moenie stuur nie"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Gee kwaadwillige program aan"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kaart verwyder"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Die mobielnetwerk sal nie beskikbaar wees nie totdat jy weer begin met \'n geldige SIM-kaart."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Klaar"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 0764f0e..b2714dd 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"በማንኛውም ጊዜ  የማሳያውን መሽከርከር ለመለወጥ ለመተግበሪያው ይፈቅዳሉ፡፡ ለተለመዱ መተግበሪያዎች አያስፈልግም፡፡"</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"የጠቋሚ ፍጥነት ለውጥ"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"መዳፊት ወይም ዱካ መከተያ ጠቋሚ ፍጥነትን በማንኛውም ጊዜ ለመለወጥ ለመተግበሪያው ይፈቅዳሉ፡፡ ለመደበኛ መተግበሪያዎች መቼም ቢሆን አያስፈልግም፡፡"</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"የቁልፍ ሰሌዳ አቀማመጥ ቀይር"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"መተግበሪያው የቁልፍ ሰሌዳ አቀማመጡን እንዲቀይር ይፈቅድለታል። ለመደበኛ መተግበሪያዎች መቼም ቢሆን ሊያስፈልግ አይገባም።"</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"ወደ መተግበሪያዎችን የLinux ምልክቶች ላክ"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"ለሁሉም ተከታታይ ሂደቶች ልከው የሚያቀርቧቸው ሲግናሎችን ለመጠየቅ ለመተግበሪያው ይፈቅዳሉ።"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"ትግበራ ሁልጊዜ አሂድ ላይ አድርግ"</string>
@@ -1009,11 +1007,17 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"የሚፈለገውን ፒን ተይብ፦"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"ፒን፦"</string>
     <string name="select_character" msgid="3365550120617701745">"ቁምፊ አስገባ"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"ያልታወቀ መተግበሪያ"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"የSMS መልዕክቶች መበላክ ላይ"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"በጣም ብዙ የ SMS መልዕክቶቸ ተልከዋል።ለመቀጠል \"እሺ \" ፣ ወይም መላክ ለማቆም\"ተው \" ምረጥ።"</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"እሺ"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"ይቅር"</string>
+    <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ቁጥሩ ብዙ የሆኑ የኤስ.ኤም.ኤስ. መልዕቶችን እየላከ ነው። ይሄ መተግበሪያ መልዕክቶችን መላኩን እንዲቀጥል መፍቀድ ትፈልጋለህ?"</string>
+    <string name="sms_control_yes" msgid="3663725993855816807">"ፍቀድ"</string>
+    <string name="sms_control_no" msgid="625438561395534982">"ከልክል"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"ኤስ.ኤም.ኤስ. ለአጭር ኮድ ይላክ?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"ከፍ ያለ ኤስ.ኤም.ኤስ. ይላክ?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የጽሑፍ መልዕክት ለ&lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; መላክ ይፈልጋል፣ ይሄ ደግሞ የኤስ.ኤም.ኤስ. አጭር ኮድ ሆኖ ተገኝቷል።&lt;p&gt;የጽሑፍ መልዕክቶች ለሆኑ አጭር ኮዶች መላክ የተንቀሳቃሽ መለያህ ከፍ ላሉ አገልግሎቶች ሊያስከፍለው ይችላል።&lt;p&gt;ይሄ መተግበሪያ መልዕክቱ እንዲልክ መፍቀድ ትፈልጋለህ?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የጽሑፍ መልዕክት ለ&lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; መላክ ይፈልጋል፣ ይሄ ደግሞ ከፍ ያለ የኤስ.ኤም.ኤስ. አጭር ኮድ ነው።&lt;p&gt;&lt;b&gt;መልዕክት ወደዚህ ቦታ መላክ የተንቀሳቃሽ መለያህ ከፍ ላሉ አገልግሎቶች ያስከፍለዋል።&lt;/b&gt;&lt;p&gt;ይሄ መተግበሪያ መልዕክቱ እንዲልክ መፍቀድ ትፈልጋለህ?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"መልዕክት ላክ"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"አትላክ"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"ተንኮል አዘል መተግበሪያ ሪፖርት አድርግ"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM ካርድ ተወግዷል"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"በትክክል የገባ SIM ካርድ ድጋሚ እስኪያስጀምሩ የተንቀሳቃሽ ስልክ አውታረመረብ አይገኝም።"</string>
     <string name="sim_done_button" msgid="827949989369963775">"ተከናውኗል"</string>
@@ -1063,10 +1067,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB ማረሚያ ላለማንቃት ዳስስ።"</string>
     <string name="select_input_method" msgid="4653387336791222978">"የግቤት ስልት ምረጥ"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"የግቤት ስልቶችን አዘጋጅ"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"የሚዳሰስ የቁልፍ ሰሌዳ"</string>
+    <string name="hardware" msgid="7517821086888990278">"ሃርድዌር"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"ዕጩዎች"</u></string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index cc3cf93..daef582 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"للسماح للتطبيق بتغيير تدوير الشاشة في أي وقت. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"تغيير سرعة المؤشر"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"للسماح للتطبيق بتغيير سرعة مؤشر الماوس أو لوحة التتبع في أي وقت. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"تغيير تنسيق لوحة مفاتيح"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"للسماح للتطبيق بتغيير تنسيق لوحة المفاتيح. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"إرسال إشارات Linux للتطبيقات"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"للسماح للتطبيق بطلب إرسال الإشارة المزوّدة لجميع العمليات المستمرة."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"تشغيل التطبيق دائمًا"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"اكتب رقم التعريف الشخصي المطلوب:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"رقم التعريف الشخصي:"</string>
     <string name="select_character" msgid="3365550120617701745">"إدراج حرف"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"تطبيق غير معروف"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"إرسال رسائل قصيرة SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"تم إرسال عدد كبير من الرسائل القصيرة SMS. المس \"موافق\" للمتابعة، أو \"إلغاء\" لإيقاف الإرسال."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"موافق"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"إلغاء"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"تمت إزالة بطاقة SIM"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"لن تكون شبكة الجوال متاحة حتى تتم إعادة التشغيل وإدخال بطاقة SIM صالحة."</string>
     <string name="sim_done_button" msgid="827949989369963775">"تم"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"المس لتعطيل تصحيح أخطاء USB."</string>
     <string name="select_input_method" msgid="4653387336791222978">"اختيار أسلوب الإدخال"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"إعداد أسلوب الإدخال"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"لوحة مفاتيح فعلية"</string>
+    <string name="hardware" msgid="7517821086888990278">"أجهزة"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789 أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"العناصر المرشحة"</u></string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 16cb445..c155537 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1007,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Увядзіце патрэбны PIN-код:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-код"</string>
     <string name="select_character" msgid="3365550120617701745">"Уставіць сімвал"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Невядомае прыкладанне"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Адпраўка SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Адпраўляецца вялікая колькасць SMS-паведамленняў. Націсніце \"OK\", каб працягнуць, ці \"Адмена\", каб спыніць адпраўку."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"ОК"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Адмяніць"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-карта выдаленая"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Мабільная сетка будзе недаступная да перазагрузкі з дзеючай SIM-картай."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Гатова"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 83f5e41..7860382 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1009,11 +1009,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Въведете задължителния ПИН:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"ПИН:"</string>
     <string name="select_character" msgid="3365550120617701745">"Вмъкване на знак"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Неизвестно приложение"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Изпращане на SMS съобщения"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Изпращат се голям брой SMS съобщения. Докоснете „OK“, за да продължите, или „Отказ“, за да спрете изпращането."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Отказ"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM картата е премахната"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Няма да имате достъп до мобилната мрежа, докато не рестартирате с поставена валидна SIM карта."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index c72c2dd..e266a85 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Permet que l\'aplicació canviï el gir de la pantalla en qualsevol moment. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"canvi de velocitat del punter"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Permet que l\'aplicació canviï la velocitat del punter del ratolí o del ratolí tàctil en qualsevol moment. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"canvia la disposició del teclat"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Permet que l\'aplicació canviï la disposició del teclat. En principi mai no serà necessari per a les aplicacions normals."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"envia senyals Linux a les aplicacions"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Permet que l\'aplicació sol·liciti que el senyal subministrat s\'enviï a tots els processos persistents."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"fes que l\'aplicació s\'executi sempre"</string>
@@ -1009,11 +1007,17 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Introdueix el PIN sol·licitat:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Insereix un caràcter"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Aplicació desconeguda"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"S\'estan enviant missatges SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"S\'estan enviant molts missatges SMS. Toca D\'acord per continuar o Cancel·la per aturar l\'enviament."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"D\'acord"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Cancel·la"</string>
+    <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; està enviant molts missatges SMS. Vols permetre que aquesta aplicació continuï enviant missatges?"</string>
+    <string name="sms_control_yes" msgid="3663725993855816807">"Permet"</string>
+    <string name="sms_control_no" msgid="625438561395534982">"Denega"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Vols enviar SMS a codi curt?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Vols enviar el SMS prèmium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vol enviar un missatge de text a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, que sembla que és un codi SMS curt.&lt;p&gt;Si envies missatges de text a codis curts, pot ser que es carreguin serveis prèmium al teu compte mòbil.&lt;p&gt;Vols permetre que aquesta aplicació enviï el missatge?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vol enviar un missatge de text a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, que és un codi curt SMS prèmium.&lt;p&gt;&lt;b&gt;Si envies un missatge a aquesta destinació, es carregaran els serveis prèmium al teu compte mòbil.&lt;/b&gt;&lt;p&gt;Vols permetre que aquesta aplicació enviï el missatge?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Envia el missatge"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"No enviïs"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Informa d\'una aplic. maliciosa"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Extracció de la targeta SIM"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"La xarxa de telefonia mòbil no estarà disponible fins que no reiniciïs amb una targeta SIM vàlida inserida."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Fet"</string>
@@ -1063,10 +1067,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Toca-ho per desactivar la depuració USB."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Selecció de mètodes d\'introducció"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Configura els mètodes d\'entrada"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclat físic"</string>
+    <string name="hardware" msgid="7517821086888990278">"Maquinari"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidats"</u></string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 52d10a2..33f91e8 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1009,11 +1009,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Zadejte požadovaný kód PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Vkládání znaků"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Neznámá aplikace"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Odesílání zpráv SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Odesíláte velký počet zpráv SMS. Dotkněte se možnosti OK, chcete-li pokračovat, nebo možnosti Zrušit, chcete-li odesílání ukončit."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Zrušit"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Karta SIM odebrána"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilní síť bude dostupná až poté, co vložíte platnou kartu SIM a restartujete zařízení."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Hotovo"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index b0a487b..c5b0e17 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1007,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Skriv den påkrævede pinkode:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Pinkode:"</string>
     <string name="select_character" msgid="3365550120617701745">"Indsæt tegn"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Ukendt app"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Sender sms-beskeder"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Der sendes et stort antal sms-beskeder. Vælg \"OK\" for at fortsætte eller \"Annuller\" for at stoppe afsendelsen."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Annuller"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kort blev fjernet"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Det mobile netværk er utilgængeligt, indtil du genstarter med et gyldigt SIM-kort."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Udfør"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 27b88f4..5a24cb3 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Ermöglicht der App, die Bildschirmdrehung jederzeit zu ändern. Sollte nie für normale Apps benötigt werden."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"Zeigergeschwindigkeit ändern"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Ermöglicht der App, jederzeit die Geschwindigkeit des Maus- bzw. Touchpad-Zeigers zu ändern. Sollte nie für normale Apps benötigt werden."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"Tastaturlayout ändern"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Ermöglicht der App, das Tastaturlayout zu ändern. Sollte für normale Apps nie benötigt werden."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"Linux-Signale an Apps senden"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Ermöglicht der App, das Senden des gelieferten Signals an alle andauernden Prozesse zu fordern"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"App permanent ausführen"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Geben Sie die erforderliche PIN ein:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Zeichen einfügen"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Unbekannte App"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Kurznachrichten werden gesendet"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Es wird eine große Anzahl an SMS versendet. Tippen Sie zum Fortfahren auf \"OK\" oder tippen Sie auf \"Abbrechen\", um den Sendevorgang zu beenden."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Abbrechen"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-Karte entfernt"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Das Mobilfunknetz ist erst wieder verfügbar, wenn Sie einen Neustart mit einer gültigen SIM-Karte durchführen."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Fertig"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Zum Deaktivieren von USB-Debugging tippen"</string>
     <string name="select_input_method" msgid="4653387336791222978">"Eingabemethode wählen"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Eingabemethoden einrichten"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Physische Tastatur"</string>
+    <string name="hardware" msgid="7517821086888990278">"Hardware"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"Kandidaten"</u></string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 0a5dd69..7c951cc 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Επιτρέπει στην εφαρμογή την αλλαγή της περιστροφής της οθόνης ανά πάσα στιγμή. Δεν απαιτείται για συνήθεις εφαρμογές."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"αλλαγή ταχύτητας δείκτη"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Επιτρέπει στην εφαρμογή την αλλαγή της ταχύτητας του δείκτη του ποντικιού ή της επιφάνειας αφής ανά πάσα στιγμή. Δεν πρέπει να χρησιμοποιείται από συνήθεις εφαρμογές."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"αλλαγή διάταξης πληκτρολογίου"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Επιτρέπει στην εφαρμογή την αλλαγή της διάταξης πληκτρολογίου. Δεν απαιτείται για συνήθεις εφαρμογές."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"αποστολή σημάτων Linux σε εφαρμογές"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Επιτρέπει στην εφαρμογή την αποστολή αιτήματος για την αποστολή του παρεχόμενου σήματος σε όλες τις υπάρχουσες διαδικασίες."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"να εκτελείται συνεχώς η εφαρμογή"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Πληκτρολογήστε τον απαιτούμενο κωδικό PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Εισαγωγή χαρακτήρα"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Άγνωστη εφαρμογή"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Αποστολή μηνυμάτων SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Αποστέλλεται μεγάλος αριθμός μηνυμάτων SMS. Αγγίξτε το στοιχείο \"OK\" για συνέχεια, ή το στοιχείο \"Ακύρωση\" για διακοπή της αποστολής."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Ακύρωση"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Η κάρτα SIM αφαιρέθηκε"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Το δίκτυο κινητής τηλεφωνίας δεν θα είναι διαθέσιμο μέχρι να κάνετε επανεκκίνηση αφού τοποθετήσετε μια έγκυρη κάρτα SIM."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Τέλος"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Αγγίξτε για απενεργοποίηση του εντοπισμού σφαλμάτων USB."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Επιλογή μεθόδου εισόδου"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Ρύθμιση μεθόδων εισαγωγής"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Φυσικό πληκτρολόγιο"</string>
+    <string name="hardware" msgid="7517821086888990278">"Υλικό"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"υποψήφιοι"</u></string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index fe5a173..208e96a 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1007,11 +1007,17 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Type the required PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Insert character"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Unknown app"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Sending SMS messages"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"A large number of SMS messages are being sent. Touch OK to continue or Cancel to stop sending."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Cancel"</string>
+    <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; is sending a large number of SMS messages. Do you want to allow this app to continue sending messages?"</string>
+    <string name="sms_control_yes" msgid="3663725993855816807">"Allow"</string>
+    <string name="sms_control_no" msgid="625438561395534982">"Deny"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Send SMS to short code?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Send premium SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; would like to send a text message to &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, which appears to be an SMS short code.&lt;p&gt;Sending text messages to some short codes may cause your mobile account to be billed for premium services.&lt;p&gt;do you want to allow this app to send the message?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; would like to send a text message to &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, which is a premium SMS short code.&lt;p&gt;&lt;b&gt;Sending a message to this destination will cause your mobile account to be billed for premium services.&lt;/b&gt;&lt;p&gt;Do you want to allow this app to send the message?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Send message"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Don\'t send"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Report malicious app"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM card removed"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"The mobile network will be unavailable until you restart with a valid SIM card inserted."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Done"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index ade6cfb..6f1ee53 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Permite que la aplicación cambie la rotación de la pantalla en cualquier momento. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"cambiar velocidad del puntero"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Permite que la aplicación cambie la velocidad del puntero del mouse o el trackpad en cualquier momento. Las aplicaciones normales no deben utilizar este permiso."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"Cambiar el diseño del teclado"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Permite que la aplicación cambie el diseño del teclado. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"enviar señales de Linux a las aplicaciones"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Permite que la aplicación solicite que la señal suministrada se envíe a todos los procesos persistentes."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"hacer que la aplicación se ejecute siempre"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Escribe el PIN solicitado:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Insertar caracteres"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Aplicación desconocida"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Enviando mensajes SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Se está enviando una gran cantidad de mensajes SMS. Toca \"Aceptar\" para continuar o \"Cancelar\" para detener el envío."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"Aceptar"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Cancelar"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Tarjeta SIM eliminada"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"La red para celulares no estará disponible hasta que reinicies, luego de insertar una tarjeta SIM válida."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Finalizado"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Toca para desactivar la depuración de USB."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Selecciona el método de introducción"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Configurar métodos de introducción"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclado físico"</string>
+    <string name="hardware" msgid="7517821086888990278">"Hardware"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 8f50660..95e1152 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Permite que la aplicación cambie la rotación de la pantalla en cualquier momento. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"cambiar velocidad del puntero"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Permite que la aplicación modifique la velocidad del puntero del ratón o del trackpad en cualquier momento. Las aplicaciones normales no deberían necesitar este permiso."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"cambiar el diseño del teclado"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Permite que la aplicación cambie el diseño del teclado. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"enviar señales Linux a aplicaciones"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Permite que la aplicación solicite que la señal suministrada se envíe a todos los procesos persistentes."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"hacer que la aplicación se ejecute siempre"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Escribe el PIN solicitado:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Insertar carácter"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Aplicación desconocida"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Enviando mensajes SMS..."</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Se va a enviar un número elevado de mensajes SMS. Selecciona Aceptar para continuar o Cancelar para detener el envío."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"Aceptar"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Cancelar"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Tarjeta SIM eliminada"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"La red móvil no estará disponible hasta que reinicies el dispositivo con una tarjeta SIM válida."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Listo"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Tocar para inhabilitar la depuración USB"</string>
     <string name="select_input_method" msgid="4653387336791222978">"Seleccionar método de introducción"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Ajustar métodos de introducción"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclado físico"</string>
+    <string name="hardware" msgid="7517821086888990278">"Hardware"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 25f3752..a72691f 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1007,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Sisestage nõutav PIN-kood:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-kood:"</string>
     <string name="select_character" msgid="3365550120617701745">"Sisesta tähemärk"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Tundmatu rakendus"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS-sõnumite saatmine"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Saadetakse suur hulk SMS-sõnumid. Saatmise jätkamiseks valige OK, lõpetamiseks Tühista."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Tühista"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kaart eemaldatud"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobiilsidevõrk ei ole saadaval, kuni sisestate kehtiva SIM-kaardi ja taaskäivitate seadme."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Valmis"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index d60c59d..d33fe74 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"به برنامه اجازه می‎دهد تا چرخش صفحه را هر وقت بخواهد تغییر دهد. برای برنامه‎های عادی نیاز نیست."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"تغییر سرعت اشاره گر"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"به برنامه اجازه می‎دهد تا سرعت ماوس و پد کنترل را هر وقت خواست تغییر دهد. برای برنامه‎های عادی نیاز نیست."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"تغییر چیدمان صفحه کلید"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"به برنامه اجازه می‌دهد تا چیدمان صفحه کلید را تغییر دهد. این کار هیچ گاه برای برنامه‌های عادی نیاز نیست."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"ارسال سیگنالهای Linux به برنامه‎ها"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"به برنامه اجازه می‎دهد تا درخواست کند سیگنال ارائه شده به همه مراحل دائم ارسال شود."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"همیشه برنامه اجرا شود"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"پین لازم را تایپ کنید:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"پین:"</string>
     <string name="select_character" msgid="3365550120617701745">"درج نویسه"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"برنامه ناشناخته"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"ارسال پیامک ها"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"تعداد زیادی پیام کوتاه ارسال شده است. برای ادامه، \"تأیید\" را لمس کرده و برای توقف ارسال، \"لغو\" را لمس کنید."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"تأیید"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"لغو"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"سیم کارت برداشته شد"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"تا وقتی که با یک سیم‌کارت معتبر راه‌اندازی مجدد نکنید شبکه تلفن همراه غیر قابل‌ دسترس خواهد بود."</string>
     <string name="sim_done_button" msgid="827949989369963775">"انجام شد"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"غیرفعال کردن اشکال زدایی USB را لمس کنید."</string>
     <string name="select_input_method" msgid="4653387336791222978">"انتخاب روش ورودی"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"تنظیم روش‌های ورودی"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"صفحه کلید فیزیکی"</string>
+    <string name="hardware" msgid="7517821086888990278">"سخت‌افزار"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"داوطلبین"</u></string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 211fab2..f03e1af 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Antaa sovelluksen muuttaa näytön kiertoa milloin tahansa. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"muuta osoittimen nopeutta"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Antaa sovelluksen muuttaa hiiren tai kosketuslevyn osoittimen nopeutta milloin tahansa. Ei tavallisten sovellusten käyttöön."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"vaihda näppäimistön asettelua"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Antaa sovelluksen muuttaa näppäimistön asettelua. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"Linux-signaalien lähettäminen sovelluksille"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Antaa sovelluksen pyytää, että tarjottu signaali lähetetään kaikille käynnissä oleville prosesseille."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"sovelluksen asettaminen aina käynnissä olevaksi"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Kirjoita pyydetty PIN-koodi:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-koodi:"</string>
     <string name="select_character" msgid="3365550120617701745">"Lisää merkki"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Tuntematon sovellus"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Tekstiviestien lähettäminen"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Olet lähettämässä suurta määrää tekstiviestejä. Jatka koskettamalla OK tai peruuta lähetys valitsemalla Peruuta."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Peruuta"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kortti poistettu"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobiiliverkko ei ole käytettävissä, ennen kuin käynnistät uudelleen kelvollisella laitteeseen kytketyllä SIM-kortilla."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Valmis"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Poista USB-vianetsintä käytöstä koskettamalla tätä."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Valitse syöttötapa"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Määritä syöttötavat"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Fyysinen näppäimistö"</string>
+    <string name="hardware" msgid="7517821086888990278">"Laitteisto"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidaatit"</u></string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 787bdda..72ac5f4 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1007,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Saisissez le code PIN requis :"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Code PIN :"</string>
     <string name="select_character" msgid="3365550120617701745">"Insérer un caractère"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Application inconnue"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Envoi de messages SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Vous êtes sur le point d\'envoyer un grand nombre de SMS. Appuyez sur \"OK\" pour continuer ou sur \"Annuler\" pour interrompre l\'envoi."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Annuler"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Carte SIM retirée"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Le réseau mobile ne sera pas disponible avant le redémarrage avec une carte SIM valide insérée."</string>
     <string name="sim_done_button" msgid="827949989369963775">"OK"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 1a95f32..e94e286 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"एप्‍लिकेशन को किसी भी समय स्‍क्रीन का रोटेशन बदलने देता है. सामान्‍य एप्‍लिकेशन के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"सूचक गति बदलें"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"एप्लिकेशन को माउस या ट्रैकपैड सूचक गति को किसी भी समय बदलने देता है. सामान्‍य एप्‍लिकेशन के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"कीबोर्ड लेआउट बदलें"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"एप्‍लिकेशन को कीबोर्ड लेआउट बदलने देता है. सामान्‍य एप्‍लिकेशन के लिए कभी आवश्‍यक नहीं है."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"एप्लिकेशन को Linux सिग्नल भेजें"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"एप्‍लिकेशन को यह अनुरोध करने देता है कि दिया गया सिग्नल सभी जारी प्रक्रियाओं को भेजा जाए."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"एप्‍लिकेशन को हमेशा चलने वाला बनाएं"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"आवश्‍यक पिन लिखें:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"पिन:"</string>
     <string name="select_character" msgid="3365550120617701745">"वर्ण सम्‍मिलित करें"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"अज्ञात एप्‍लिकेशन"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS संदेश भेज रहा है"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"बड़ी संख्‍या में SMS संदेश भेजे जा रहे हैं. जारी रखने के लिए ठीक स्‍पर्श करें, या भेजना बंद करने के लिए रद्द करें स्‍पर्श करें."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"ठीक"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"रद्द करें"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"सिमकार्ड निकाला गया"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"मान्‍य सि‍म कार्ड डालकर पुन: प्रारंभ करने तक मोबाइल नेटवर्क अनुपलब्‍ध रहेगा."</string>
     <string name="sim_done_button" msgid="827949989369963775">"पूर्ण"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB डीबग करना अक्षम करने के लिए स्‍पर्श करें."</string>
     <string name="select_input_method" msgid="4653387336791222978">"इनपुट पद्धति चुनें"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"इनपुट पद्धतियां सेट करें"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"भौतिक कीबोर्ड"</string>
+    <string name="hardware" msgid="7517821086888990278">"हार्डवेयर"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"उम्‍मीदवार"</u></string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 0591e04..412bc61 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1009,11 +1009,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Upišite potreban PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Umetni znak"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Nepoznata aplikacija"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Slanje SMS poruka"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Šalje se velika količina SMS poruka. Dodirnite \"U redu\" za nastavak ili \"Odustani\" za prekid slanja."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"U redu"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Odustani"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM kartica uklonjena"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilna mreža bit će nedostupna do ponovnog pokretanja s umetnutom važećom SIM karticom."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Gotovo"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 4043aef..c8f039f 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Lehetővé teszi az alkalmazás számára a képernyő elforgatásának bármikori módosítását. A normál alkalmazásoknak erre soha nincs szüksége."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"mutató sebességének módosítása"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Lehetővé teszi az alkalmazás számára, hogy bármikor módosítsa az egér vagy az érintőpad mutatójának sebességét. Normál alkalmazásoknak soha nem lehet rá szükségük."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"billentyűzetkiosztás módosítása"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Lehetővé teszi az alkalmazás számára, hogy módosítsa a billentyűzetkiosztást. Normál alkalmazásoknak alapesetben nem lehet szükségük rá."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"Linux-jelek küldése az alkalmazásoknak"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Lehetővé teszi az alkalmazás számára, hogy a megadott jelet elküldje az összes állandó folyamatnak."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"az alkalmazás állandó futtatása"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Adja meg a szükséges PIN kódot:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN kód:"</string>
     <string name="select_character" msgid="3365550120617701745">"Karakter beszúrása"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Ismeretlen alkalmazás"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS-ek küldése"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Nagy számú SMS-t kíván elküldeni. A folytatáshoz érintse meg az \"OK\", a küldés leállításához a \"Mégse\" lehetőséget."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Mégse"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kártya eltávolítva"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"A mobilhálózat nem lesz elérhető, amíg újra nem indítja egy érvényes SIM kártya behelyezése után."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Kész"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Érintse meg az USB hibakeresés kikapcsolásához."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Beviteli mód kiválasztása"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Beviteli módok beállítása"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Fizikai billentyűzet"</string>
+    <string name="hardware" msgid="7517821086888990278">"Hardver"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"jelöltek"</u></string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 7a52979..03dac8a 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1009,11 +1009,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Ketik PIN yang diminta:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Sisipkan huruf"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Apl tak dikenal"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Mengirim pesan SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Pesan SMS dalam jumlah besar sedang dikirimkan. Sentuh Oke untuk melanjutkan, atau Batal untuk menghentikan pengiriman."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"Oke"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Batal"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Kartu SIM dihapus"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Jaringan seluler tidak akan tersedia sampai Anda memulai lagi dengan memasukkan kartu SIM yang valid."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Selesai"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 9073bf1..e9e5924 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1007,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Inserisci il PIN richiesto:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Inserisci carattere"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Applicazione sconosciuta"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Invio SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"È in corso l\'invio di numerosi SMS. Tocca \"OK\" per continuare oppure \"Annulla\" per interrompere l\'invio."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Annulla"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Scheda SIM rimossa"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"La rete mobile non sarà disponibile finché non eseguirai il riavvio con una scheda SIM valida inserita."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Fine"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 714f203..731546c 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"מאפשר ליישום לשנות את הסיבוב של המסך בכל עת. הרשאה זו לעולם אינה נחוצה ליישומים רגילים."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"שינוי מהירות המצביע"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"מאפשר ליישום לשנות את המהירות של מצביע העכבר או לוח המגע בכל עת. יישומים רגילים לא אמורים לעולם להזדקק להרשאה זו."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"שנה את פריסת המקלדת"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"מאפשר ליישום לשנות את פריסת המקלדת. הרשאה זו לעולם אינה אמורה להיות נחוצה עבור יישומים רגילים."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"שליחת אותות Linux ליישומים"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"מאפשר ליישום לבקש שהאות שנקלט יישלח לכל התהליכים המתמשכים."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"הגדרת היישום לפעול תמיד"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"הקלד את קוד ה-PIN הנדרש."</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"הוסף תו"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"יישום לא ידוע"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"שולח הודעות SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"מתבצעת כעת שליחה של מספר גדול של הודעות SMS. גע באפשרות \'אישור\' כדי להמשיך, או \'ביטול\' כדי לעצור את השליחה."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"אישור"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"ביטול"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"כרטיס ה-SIM הוסר"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"הרשת הסלולרית לא תהיה זמינה עד שתפעיל מחדש לאחר הכנסת כרטיס SIM חוקי."</string>
     <string name="sim_done_button" msgid="827949989369963775">"סיום"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"גע כדי להשבית את ניקוי הבאגים בהתקן ה-USB."</string>
     <string name="select_input_method" msgid="4653387336791222978">"בחר שיטת הזנה"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"הגדר שיטות קלט"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"מקלדת פיזית"</string>
+    <string name="hardware" msgid="7517821086888990278">"חומרה"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"מועמדים"</u></string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index a5db38b..e9d3558 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"いつでも画面の向きを変更することをアプリに許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"ポインタの速度の変更"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"マウスまたはトラックパッドのポインタの速度をいつでも変更することをアプリに許可します。通常のアプリでは不要です。"</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"キーボードレイアウトの変更"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"キーボードレイアウトの変更をアプリに許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"アプリへのLinuxシグナルの送信"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"受信したシグナルをすべての継続プロセスに送信するようリクエストすることをアプリに許可します。"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"アプリの常時実行"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"必要なPINを入力してください:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"文字を挿入"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"不明なアプリ"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMSメッセージの送信中"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"大量のSMSメッセージを送信しようとしています。[OK]で送信、[キャンセル]で中止します。"</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"キャンセル"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIMカードが取り外されました"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"有効なSIMカードを挿入して再起動するまでは、モバイルネットワークは利用できません。"</string>
     <string name="sim_done_button" msgid="827949989369963775">"完了"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"タップしてUSBデバッグを無効にします。"</string>
     <string name="select_input_method" msgid="4653387336791222978">"入力方法の選択"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"入力方法をセットアップ"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"物理キーボード"</string>
+    <string name="hardware" msgid="7517821086888990278">"ハードウェア"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"候補"</u></string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 4f580ba..02ab306 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"앱이 언제든지 화면 회전을 변경할 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"포인터 속도 변경"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"앱이 언제든지 마우스 또는 트랙패드 포인터의 속도를 변경할 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"키보드 레이아웃 변경"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"앱이 키보드 레이아웃을 변경할 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"앱에 Linux 시그널 보내기"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"제공된 시그널을 모든 영구 프로세스로 전송하는 것을 앱이 요청할 수 있도록 허용합니다."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"앱이 항상 실행되도록 설정"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"필수 PIN 입력:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"문자 삽입"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"알 수 없는 앱"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS 메시지를 보내는 중"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"SMS 메시지를 대량 전송 중입니다. 계속하려면 \'확인\'을 터치하고 전송을 중지하려면 \'취소\'를 터치하세요."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"확인"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"취소"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM 카드 제거됨"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"유효한 SIM 카드를 삽입하여 다시 시작할 때까지 모바일 네트워크를 사용할 수 없습니다."</string>
     <string name="sim_done_button" msgid="827949989369963775">"완료"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB 디버깅을 사용하지 않으려면 터치하세요."</string>
     <string name="select_input_method" msgid="4653387336791222978">"입력 방법 선택"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"입력 방법 설정"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"물리적 키보드"</string>
+    <string name="hardware" msgid="7517821086888990278">"하드웨어"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"가능한 원인"</u></string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index c588fa6..3d389d8 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Leidžiama programai bet kada kaitalioti ekraną. Įprastoms programoms to neturėtų prireikti."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"keisti žymiklio greitį"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Leidžiama programai keisti pelės ar sensorinio pulto žymiklio greitį. Įprastoms programoms to neturėtų prireikti."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"keisti klaviatūros išdėstymą"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Leidžiama programai pakeisti klaviatūros išdėstymą. Įprastoms programoms to neturėtų prireikti."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"siųsti „Linux“ signalus programoms"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Leidžiama programai pateikti užklausą, kad teikiamas signalas būtų siunčiamas visiems nuolatiniams procesams."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"nustatyti, kad programa būtų visada vykdoma"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Įveskite reikiamą PIN kodą:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN kodas:"</string>
     <string name="select_character" msgid="3365550120617701745">"Įterpti simbolį"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Nežinoma programa"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS pranešimų siuntimas"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Siunčiama daug SMS pranešimų. Palieskite „Gerai“, jei norite tęsti, arba „Atšaukti“, jei norite sustabdyti siuntimą."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"Gerai"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Atšaukti"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM kortelė pašalinta"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilusis tinklas bus nepasiekiamas, kol nepaleisite iš naujo įdėję tinkamą SIM kortelę."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Atlikta"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Palieskite, kad neleistumėte USB derinimo."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Pasirinkite įvesties metodą"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Nustatyti įvesties metodus"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Fizinė klaviatūra"</string>
+    <string name="hardware" msgid="7517821086888990278">"Apar. įr."</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidatai"</u></string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index d710347..05d0dbe 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Ļauj lietotnei jebkurā laikā mainīt ekrāna pozīciju. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"Rādītāja ātruma mainīšana"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Ļauj lietotnei jebkurā laikā mainīt peles vai skārienpaliktņa rādītāja ātrumu. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"Tastatūras izkārtojuma maiņa"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Ļauj lietotnei mainīt tastatūras izkārtojumu. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"sūtīt Linux signālus lietotnēm"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Ļauj lietotnei pieprasīt, lai piegādātais signāls tiktu sūtīts visiem pastāvīgajiem procesiem."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"likt lietotnei vienmēr darboties"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Ierakstiet pieprasīto PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Ievietojiet rakstzīmi"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Nezināma lietotne"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Īsziņu sūtīšana"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Tiek sūtīts daudz īsziņu. Pieskarieties Labi, lai turpinātu, vai Atcelt, lai apturētu sūtīšanu."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"Labi"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Atcelt"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM karte ir izņemta."</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilais tīkls nebūs pieejams līdz brīdim, kad restartēsiet ierīci ar ievietotu derīgu SIM karti."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Gatavs"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Pieskarieties, lai atspējotu USB atkļūdošanu."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Ievades metodes izvēle"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Iestatīt ievades metodes"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Fiziskā tastatūra"</string>
+    <string name="hardware" msgid="7517821086888990278">"Aparatūra"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidāti"</u></string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 38fc473..f0f5630 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Membenarkan apl untuk menukar putaran skrin pada bila-bila masa. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"tukar kelajuan penuding"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Membenarkan apl untuk menukar kelajuan penunjuk tetikus atau pad jejak pada bila-bila masa. Tidak sekali-kali diperlukan untuk apl biasa."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"tukar susun atur papan kekunci"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Membenarkan apl menukar susun atur papan kekunci. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"hantar isyarat Linux kepada apl"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Membenarkan apl meminta isyarat yang dibekalkan dihantar kepada semua proses yang berterusan."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"buatkan apl sentiasa berjalan"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Taipkan PIN yang diperlukan:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Masukkan aksara"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Apl tidak diketahui"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Menghantar mesej SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Sejumlah besar mesej SMS sedang dihantar. Sentuh \"OK\" untuk meneruskan atau \"Batal\" untuk menghentikan penghantaran."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Batal"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Kad SIM dikeluarkan"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Rangkaian mudah alih tidak akan tersedia sehingga anda mula semula dengan kad SIM yang sah dimasukkan."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Selesai"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Sentuh untuk melumpuhkan penyahpepijatan USB."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Pilih kaedah input"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Sediakan kaedah input"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Papan kekunci fizikal"</string>
+    <string name="hardware" msgid="7517821086888990278">"Perkakasan"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"calon"</u></string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index df05f01..6609d29 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1009,11 +1009,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Skriv inn påkrevd PIN-kode:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Sett inn tegn"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Ukjent app"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Sender SMS-meldinger"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Et stort antall SMS-meldinger sendes. Trykk på OK for å fortsette, eller trykk på Avbryt for å avbryte sendingen."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Avbryt"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kort er fjernet"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Det mobile nettverket forblir utilgjengelig inntil du starter på nytt med et gyldig SIM-kort."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Fullført"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 3d48936..1c8809a 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Hiermee kan de app de rotatie van het scherm op elk moment wijzigen. Nooit vereist voor normale apps."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"aanwijzersnelheid wijzigen"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Hiermee kan de app de snelheid van de muis- of trackpadaanwijzer op elk moment wijzigen. Nooit vereist voor normale apps."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"toetsenbordindeling wijzigen"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Hiermee kan de app de toetsenbordindeling wijzigen. Nooit vereist voor normale apps."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"Linux-signalen verzenden naar apps"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Hiermee kan de app ervoor zorgen dat het geleverde signaal wordt verzonden naar alle persistente processen."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"app altijd laten uitvoeren"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Voer de gewenste pincode in:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Pincode"</string>
     <string name="select_character" msgid="3365550120617701745">"Teken invoegen"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Onbekende app"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS-berichten verzenden"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Er wordt een groot aantal sms\'jes verzonden. Raak \'OK\' aan om door te gaan of \'Annuleren\' om de verzending te stoppen."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Annuleren"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Simkaart verwijderd"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Het mobiele netwerk is niet beschikbaar totdat u het apparaat opnieuw start met een geldige simkaart."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Gereed"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Raak deze optie aan om USB-foutopsporing uit te schakelen."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Invoermethode selecteren"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Invoermethoden instellen"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Fysiek toetsenbord"</string>
+    <string name="hardware" msgid="7517821086888990278">"Hardware"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidaten"</u></string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index d566c14..83b7aba 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Pozwala aplikacji na zmianę obrotu ekranu w dowolnym momencie. To uprawnienie nie powinno być potrzebne zwykłym aplikacjom."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"zmiana szybkości wskaźnika"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Pozwala aplikacji zmienić szybkość wskaźnika myszy lub touchpada w dowolnym momencie. Nieprzeznaczone dla zwykłych aplikacji."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"zmiana układu klawiatury"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Zezwala aplikacji na zmianę układu klawiatury. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"wysyłanie sygnałów systemu Linux do aplikacji"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Pozwala aplikacji na żądanie, aby dostarczony sygnał został wysłany do wszystkich trwałych procesów."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"sprawianie, że aplikacja jest cały czas uruchomiona"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Wpisz wymagany kod PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Kod PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Wstaw znak"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Nieznana aplikacja"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Wysyłanie wiadomości SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Wysyłana jest duża liczba wiadomości SMS. Dotknij OK, aby kontynuować, lub Anuluj, aby zatrzymać wysyłanie."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Anuluj"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Karta SIM wyjęta"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Sieć komórkowa będzie niedostępna do chwili ponownego uruchomienia urządzenia z użyciem ważnej karty SIM."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Gotowe"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Dotknij, aby wyłączyć debugowanie USB."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Wybierz metodę wprowadzania"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Konfiguruj metody wprowadzania"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Klawiatura fizyczna"</string>
+    <string name="hardware" msgid="7517821086888990278">"Sprzęt"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandydaci"</u></string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 0f55711..8f2f78f 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Permite que a aplicação altere a rotação do ecrã em qualquer momento. Nunca deve ser necessário para aplicações normais."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"alterar a veloc. do ponteiro"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Permite à aplicação mudar em qualquer altura a velocidade do ponteiro do rato ou do trackpad. Nunca deverá ser necessário para aplicações normais."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"alterar o esquema de teclado"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Permite que a aplicação altere o esquema de teclado. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"enviar sinais Linux para aplicações"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Permite à aplicação pedir que o sinal fornecido seja enviado a todos os processos persistentes."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"fazer com que a aplicação seja sempre executada"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Introduza o PIN solicitado:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Introduzir carácter"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Aplicação desconhecida"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"A enviar mensagens SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Está a ser enviado um grande número de mensagens SMS. Toque em “OK” para continuar ou “Cancelar” para parar o envio."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Cancelar"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Cartão SIM removido"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"A rede de telemóvel estará indisponível até que reinicie o aparelho com um cartão SIM válido inserido."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Concluído"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Toque para desativar a depuração USB."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Escolher o método de entrada"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Configurar métodos de introdução"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclado físico"</string>
+    <string name="hardware" msgid="7517821086888990278">"Hardware"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 1beb4e7..4d770b5 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Permite que o aplicativo gire a tela a qualquer momento. Nunca deve ser necessário para aplicativos normais."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"alterar velocidade do ponteiro"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Permite que o aplicativo altere a velocidade do cursos do mouse ou trackpad a qualquer momento. Nunca deve ser necessário para aplicativos normais."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"alterar layout do teclado"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Permite que o aplicativo altere o layout do teclado. Não será necessário para aplicativos normais."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"enviar sinais para aplicativos Linux"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Permite que o aplicativo solicite o envio do sinal fornecido a todos os processos persistentes."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"sempre executar o aplicativo"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Digite o PIN obrigatório:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Inserir caractere"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Aplicativo desconhecido"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Enviando mensagens SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Muitas mensagens SMS estão sendo enviadas. Selecione \"OK\" para continuar ou \"Cancelar\" para interromper o envio."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Cancelar"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Cartão SIM removido"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"A rede móvel ficará indisponível até que você reinicie com um cartão SIM válido inserido."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Concluído"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Toque para desativar a depuração do USB."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Selecione o método de entrada"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Configurar métodos de entrada"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclado físico"</string>
+    <string name="hardware" msgid="7517821086888990278">"Hardware"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 637e4b1..6f066de 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -1489,13 +1489,27 @@
     <!-- no translation found for wifi_p2p_show_pin_message (8530563323880921094) -->
     <skip />
     <string name="select_character" msgid="3365550120617701745">"Inserir in caracter"</string>
-    <!-- no translation found for sms_control_default_app_name (3058577482636640465) -->
-    <skip />
     <string name="sms_control_title" msgid="7296612781128917719">"Trametter messadis SMS"</string>
-    <!-- no translation found for sms_control_message (4073755190243093924) -->
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
     <skip />
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Interrumper"</string>
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <!-- no translation found for sim_removed_title (6227712319223226185) -->
     <skip />
     <!-- no translation found for sim_removed_message (2333164559970958645) -->
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 0f773a5..3772861 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1009,11 +1009,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Introduceţi codul PIN necesar:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Cod PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Introduceţi caracterul"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Aplicaţie necunoscută"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Se trimit mesaje SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"În acest moment se trimit multe mesaje SMS. Atingeţi „OK” pentru a continua sau „Anulaţi” pentru a opri trimiterea."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Anulaţi"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Card SIM eliminat"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Reţeaua mobilă va fi indisponibilă până când reporniţi cu o cartelă SIM validă introdusă."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Terminat"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 7b7c95bd..b967620 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Приложение сможет менять ориентацию экрана. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"изменять скорость указателя"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Приложение сможет в любой момент изменить скорость движения указателя мыши или сенсорной панели. Это разрешение не используется обычными приложениями."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"менять раскладку автоматически"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Разрешить автоматическую смену раскладки клавиатуры (используется лишь в некоторых приложениях)."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"отправка сигналов Linux приложениям"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Приложение сможет запрашивать передачу полученного сигнала всем постоянным процессам."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"постоянная работа приложения"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Введите PIN-код:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-код:"</string>
     <string name="select_character" msgid="3365550120617701745">"Введите символ"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Неизвестное приложение"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Отправка SMS-сообщений"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Отправляется большое количество SMS-сообщений. Нажмите \"ОК\", чтобы продолжить отправку, или \"Отмена\", чтобы прекратить ее."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"ОК"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Отмена"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-карта удалена"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Пока вы не вставите действующую SIM-карту, мобильная сеть будет недоступна."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Нажмите, чтобы отключить отладку по USB."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Выберите способ ввода"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Настройка способов ввода"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Физическая клавиатура"</string>
+    <string name="hardware" msgid="7517821086888990278">"Аппаратура"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"варианты"</u></string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index a2ac96e..1bf7a17 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Umožňuje aplikácii kedykoľvek zmeniť otáčanie obrazovky. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"zmena rýchlosti ukazovateľa"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Umožňuje aplikácii kedykoľvek zmeniť rýchlosť kurzora myši alebo touchpadu. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"zmeniť rozloženie klávesnice"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Umožňuje aplikácii zmeniť rozloženie klávesnice. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"odoslať aplikáciám signály systému Linux"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Umožňuje aplikácii vyžiadať odoslanie poskytnutého signálu všetkým trvalým procesom."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"nastaviť, aby bola aplikácia neustále spustená"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Zadajte požadovaný kód PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Vkladanie znakov"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Neznáma aplikácia"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Odosielanie správ SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Odosiela sa veľký počet správ SMS. Ak chcete pokračovať, dotknite sa tlačidla OK. Ak chcete odosielanie ukončiť, dotknite sa tlačidla Zrušiť."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Zrušiť"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Karta SIM bola odobraná"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilná sieť nebude k dispozícii, kým nevložíte platnú kartu SIM a zariadenie nereštartujete."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Hotovo"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Dotknutím zakážete ladenie USB."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Zvoliť metódu vstupu"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Nastavenie metód vstupu"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Fyzická klávesnica"</string>
+    <string name="hardware" msgid="7517821086888990278">"Hardvér"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁÄBCČDĎDZDŽEÉFGHCHIÍJKLĽMNŇOÓÔPRŔSŠTŤUÚVWXYÝZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidáti"</u></string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 2b452ae..152d1c1 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Programu omogoča, da kadar koli zasuka zaslon. Ne uporabljajte za navadne programe."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"spreminjanje hitrosti kazalca"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Programu omogoča spreminjanje hitrosti kazalca miške ali sledilne ploščice. Tega ni treba nikoli uporabiti za navadne programe."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"spreminjanje postavitve tipkovnice"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Aplikaciji omogoča, da kadar koli spremeni postavitev tipkovnice. Običajne aplikacije tega ne potrebujejo."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"pošiljanje signalov Linuxa programom"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Programu omogoča, da zahteva, da je posredovani signal poslan vsem trajnim procesom."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"neprekinjeno izvajanje programov"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Vnesite zahtevano kodo PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Vstavljanje znaka"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Neznan program"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Pošiljanje sporočil SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"V pošiljanju je veliko sporočil SMS. Če želite nadaljevati, izberite »V redu«. Če želite pošiljanje ustaviti, izberite »Prekliči«."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"V redu"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Prekliči"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Kartica SIM odstranjena"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilno omrežje ne bo na voljo, dokler naprave vnovič ne zaženete z veljavno kartico SIM."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Dokončano"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Dotaknite se, če želite onemogočiti iskanje in odpravljanje napak prek vrat USB."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Izberite način vnosa"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Nastavi načine vnosa"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Fizična tipkovnica"</string>
+    <string name="hardware" msgid="7517821086888990278">"Strojna oprema"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidati"</u></string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 0fdce67..9e63b31 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1009,11 +1009,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Унесите потребни PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Уметање знака"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Непозната апликација"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Слање SMS порука"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Шаље се велики број SMS порука. Додирните Потврди да бисте наставили или Откажи да бисте зауставили слање."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"Потврди"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Откажи"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM картица је уклоњена"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Мобилна мрежа неће бити доступна док не покренете систем поново уз уметање важеће SIM картице."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 2c4efc5..3db9ec7 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Gör att appen när som helst kan ändra skärmläget. Behövs inte för vanliga appar."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"ändra markörens hastighet"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Tillåter att appen när som helst ändrar hastigheten för musens eller styrplattans markör. Ska inte behövas för vanliga appar."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"ändra tangentbordslayout"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Tillåter att appen ändrar tangentbordets layout. Ska inte behövas för vanliga appar."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"skicka Linux-signaler till appar"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Tillåter att appen begär att den angivna signalen skickas till alla beständiga processer."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"se till att appen alltid körs"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Ange den obligatoriska PIN-koden:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-kod:"</string>
     <string name="select_character" msgid="3365550120617701745">"Infoga tecken"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Okänd app"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Skickar SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Flera SMS skickas. Tryck på OK om du vill fortsätta eller på Avbryt om du vill avsluta sändningen."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Avbryt"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kortet togs bort"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Det mobila nätverket kommer inte att vara tillgängligt förrän du startar om med ett giltigt SIM-kort."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Klar"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Tryck om du vill inaktivera USB-felsökning."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Välj inmatningsmetod"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Konfigurera inmatningsmetoder"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Fysiskt tangentbord"</string>
+    <string name="hardware" msgid="7517821086888990278">"Maskinvara"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidater"</u></string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 41345bd..20bc2c6 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Inaruhusu programu kubadilisha mzunguko wa skrini wakati wowote. Kamwe hazihitajiki kwa programu za kawaida."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"Badilisha kasi ya pointa"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Inaruhusu programu kubadilisha kasi ya kielekezi cha kipanya au pedi ya kufuatilia wakati wowote. Kamwe haitahitajika kwa programu za kawaida."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"badilisha mpangilio wa kibodi"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Inaruhusu programu kubadilisha mpangilio wa kibodi. Haipaswi kamwe kuhitajika kwa rogramu za kawaida."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"Tuma ishara za Linux kwa programu"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Inaruhusu programu kuomba ishara iliyotolewa kutumwa kwa michakato inyoendelea."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"Fanya programu kuendeshwa kila mara"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Charaza PIN inayohitajika:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Ingiza kibambo"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Programu isiyojulikana"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Inatuma ujumbe wa SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Idadi kubwa ya jumbe za SMS inatumwa. Gusa SAWA kuendelea, au Ghairi kuwacha kutuma."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"Sawa"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Ghairi"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Kadi ya SIM imeondolewa"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"mtandao wa simu hutapatika hadi uanzishe upya na SIM kadi halali iliyoingizwa."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Kwisha"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Gusa ili kulemaza utatuaji wa USB."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Chagua njia ya ingizo"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Weka mbinu za ingizo"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Kibodi halisi"</string>
+    <string name="hardware" msgid="7517821086888990278">"Maunzi"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"wagombeaji"</u></string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 3f479e5..0884fb7 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1009,11 +1009,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"พิมพ์ PIN ที่ต้องการ:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"ใส่อักขระ"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"แอปพลิเคชันที่ไม่รู้จัก"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"กำลังส่งข้อความ SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"กำลังส่งข้อความ SMS จำนวนมาก แตะ \"ตกลง\" เพื่อทำงานต่อหรือ \"ยกเลิก\" เพื่อหยุดส่ง"</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"ตกลง"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"ยกเลิก"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"นำซิมการ์ดออกแล้ว"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"เครือข่ายมือถือจะไม่สามารถใช้งานได้จนกว่าคุณจะรีสตาร์ทโดยใส่ซิมการ์ดที่ถูกต้องแล้ว"</string>
     <string name="sim_done_button" msgid="827949989369963775">"เสร็จสิ้น"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index a5d3f08..26f7d5e 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Pinapayagan ang app na baguhin ang pag-ikot ng screen anumang oras. Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"baguhin ang bilis ng pointer"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Pinapayagan ang app na baguhin ang bilis ng mouse o trackpad pointer anumang oras. Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"baguhin ang layout ng keyboard"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Pinapayagan ang app na baguhin ang layout ng keyboard. Hindi kailanman dapat na kailanganin para sa mga normal na app."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"magpadala ng mga signal ng Linux sa apps"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Pinapayagan ang app na hilinging maipadala ang ibinigay na signal sa lahat ng nagpapatuloy na proseso."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"palaging patakbuhin ang app"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"I-type ang kinakailangang PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Magpasok ng character"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Hindi kilalang app"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Nagpapadala ng mga SMS na mensahe"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Ipinapadala ang malaking bilang ng mga mensaheng SMS. Pindutin ang OK upang magpatuloy, o Kanselahin upang ihinto ang pagpapadala."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Kanselahin"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Naalis ang SIM card"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Hindi magiging available ang mobile network hanggang mag-restart ka gamit ang isang may-bisang SIM card"</string>
     <string name="sim_done_button" msgid="827949989369963775">"Tapos na"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Pindutin upang huwag paganahin ang pag-debug ng USB."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Pumili ng pamamaraan ng pag-input"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"I-set up paraan ng pag-input"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Aktwal na keyboard"</string>
+    <string name="hardware" msgid="7517821086888990278">"Hardware"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"mga kandidato"</u></string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 86c1a709..8abf38d 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Uygulamaya, istediği zaman ekran dönüşünü değiştirme izni verir. Normal uygulamalar için gerekli değildir."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"işaretçi hızını değiştir"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Uygulamaya, istediği zaman fare veya izleme yüzeyi işaretçi hızını değiştirme izni verir. Normal uygulamalar için gerekli değildir."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"klavye düzenini değiştir"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Uygulamaya klavye düzenini değiştirme izni verir. Normal uygulamalar için hiçbir zaman gerekmez."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"uygulamalara Linux sinyalleri gönder"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Uygulamaya, sağlanan sinyalin tüm kalıcı işlemlere gönderilmesini isteme izni verir."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"uygulamayı her zaman çalıştır"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Gerekli PIN\'i yazın:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Karakter ekle"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Bilinmeyen uygulama"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS mesajları gönderiliyor"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Çok sayıda SMS mesajı gönderiliyor. Devam etmek için Tamam\'a, göndermeyi durdurmak için İptal\'e dokunun."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"Tamam"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"İptal"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM kart çıkarıldı"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Geçerli bir SIM kart yerleştirilmiş olarak yeniden başlatana kadar mobil ağ kullanılamayacak."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Tamamlandı"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB hata ayıklama özelliğini devre dışı bırakmak için dokunun."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Giriş yöntemini seçin"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Giriş yöntemlerini ayarla"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Fiziksel klavye"</string>
+    <string name="hardware" msgid="7517821086888990278">"Donanım"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"adaylar"</u></string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 154468c..5504176 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1009,11 +1009,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Введіть потрібний PIN-код:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-код:"</string>
     <string name="select_character" msgid="3365550120617701745">"Вставл-ня символу"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Невідома програма"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Надсил. SMS повідомлень"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Надсилається велика кількість SMS повідомлень. Торкніться \"OK\", щоб продовжити, або \"Скасувати\", щоб припинити надсилання."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Скасувати"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-карту вилучено"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Мобільна мережа буде недоступна, поки ви не здійсните перезапуск, вставивши дійсну SIM-карту."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index cbad241..96e97f6 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Cho phép ứng dụng thay đổi độ xoay màn hình bất cứ lúc nào. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"thay đổi tốc độ con trỏ"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Cho phép ứng dụng thay đổi tốc độ của chuột hoặc con trỏ trên ô di chuột bất kỳ lúc nào. Không cần thiết cho các ứng dụng thông thường."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"thay đổi bố cục bàn phím"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Cho phép các ứng dụng thay đổi bố cục bàn phím. Không bao giờ cần thiết cho các ứng dụng bình thường."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"gửi tín hiệu Linux đến ứng dụng"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Cho phép ứng dụng yêu cầu tín hiệu đã cung cấp được gửi đến tất cả các quá trình liên tục."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"đặt ứng dụng luôn chạy"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Nhập PIN bắt buộc:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Mã PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Chèn ký tự"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"Ứng dụng không xác định"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Đang gửi tin nhắn SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Một lượng lớn các tin nhắn SMS đang được gửi. Chạm OK để tiếp tục hoặc Hủy để ngừng gửi."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Hủy"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"Đã xóa thẻ SIM"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mạng di động sẽ không khả dụng cho đến khi bạn khởi động lại với thẻ SIM hợp lệ được lắp."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Xong"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Chạm để vô hiệu hóa gỡ lỗi USB."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Chọn phương thức nhập"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Thiết lập phương thức nhập"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Bàn phím thực"</string>
+    <string name="hardware" msgid="7517821086888990278">"Phần cứng"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"ứng viên"</u></string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index cb612e1..08a15e4 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"允许应用随时更改屏幕的旋转状态。普通应用绝不需要此权限。"</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"更改指针速度"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"允许应用随时更改鼠标或触控板指针速度。普通应用绝不需要此权限。"</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"更改键盘布局"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"允许应用更改键盘布局。普通应用绝不需要此权限。"</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"向应用发送 Linux 信号"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"允许应用请求将提供的信号发送给所有持续的进程。"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"让应用始终运行"</string>
@@ -1009,11 +1007,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"键入所需的 PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"插入字符"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"未知应用"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"正在发送短信"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"正在发送大量短信。触摸“确定”继续,或触摸“取消”停止发送。"</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"确定"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"取消"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"已移除 SIM 卡"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"移动网络不可用。请插入有效的 SIM 卡并重新启动。"</string>
     <string name="sim_done_button" msgid="827949989369963775">"完成"</string>
@@ -1063,10 +1077,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"触摸以停用 USB 调试。"</string>
     <string name="select_input_method" msgid="4653387336791222978">"选择输入法"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"设置输入法"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"物理键盘"</string>
+    <string name="hardware" msgid="7517821086888990278">"硬件"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"候选"</u></string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index c2ae68e..0468534 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1009,11 +1009,27 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"請輸入必要的 PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"插入字元"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"不明的應用程式"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"傳送 SMS 簡訊"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"即將傳送大量的 SMS 簡訊。輕觸 [確定] 可繼續傳送,或輕觸 [取消] 停止傳送。"</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"確定"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"取消"</string>
+    <!-- no translation found for sms_control_message (3867899169651496433) -->
+    <skip />
+    <!-- no translation found for sms_control_yes (3663725993855816807) -->
+    <skip />
+    <!-- no translation found for sms_control_no (625438561395534982) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM 卡已移除"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"您必須先插入有效的 SIM 卡再重新啟動手機,才能使用行動網路。"</string>
     <string name="sim_done_button" msgid="827949989369963775">"完成"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index eea53ec..c910d4a 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -286,10 +286,8 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"Ivumela insiza ukuthi iguqule ukujikeleza kweskrini nganoma isiphi isikhathi. Akudingakeli izinsiza ezejwayelekile."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"guqula isivinini sesikhombi"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Ivumela insiza ukuthi iguqule ijubane legundane noma lendawo yokukhomba ngomunwe. Akufanele kudingakele izinsiza ezijwayelekile."</string>
-    <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) -->
-    <skip />
-    <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) -->
-    <skip />
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"shintsha isendlalelo sekhibhodi"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"Ivumela uhlelo lokusebenza ukushintsha isendlalelo sekhibhodi. Kufanele ingadingi izinhlelo zokusebenzia ezivamile."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"Thumela imifanekiso ye-Linu ezinsizeni"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Ivumela insiza ukuthi icele ukuthi isiginali ethunyelwe idluliselwe kuzo zonke izinqubeko ezisalelayo."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"yenza insiza ukuthi ihlale isebenza"</string>
@@ -1009,11 +1007,17 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Faka i-PIN edingekayo:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"Faka uhlamvu"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"insiza engaziwa"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Ithumela imiyalezo ye-SMS"</string>
-    <string name="sms_control_message" msgid="4073755190243093924">"Inani eliphezulu lwama-SMS liyathunyelwa. Khetha \"KULUNGILE\" ukuqhubeka, noma \"Khansela\" ukumisa ukuthumela."</string>
-    <string name="sms_control_yes" msgid="2532062172402615953">"KULUNGILE"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Khansela"</string>
+    <string name="sms_control_message" msgid="3867899169651496433">"I-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ithumela inombolo enkulu yemilayezo ye-SMS. Ufuna ukuvumela lolu hlelo lokusebenza ukuqhubeka ukuthumela imilayezo?"</string>
+    <string name="sms_control_yes" msgid="3663725993855816807">"Vumela"</string>
+    <string name="sms_control_no" msgid="625438561395534982">"Nqaba"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Thumela ikhodi efushane?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Ukuthumela i-SMS ye-premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"I-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ithanda ukuthumela umlayezo wombhalo ku-&lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, okubonakala sengathi ikhodi ye-SMS efushane.&lt;p&gt;Ukuthumela umlayezo wombhalo kungabangela i-akhawunti yeselula yakho ukuthi ikhokheliswe amasevisi e-premium.&lt;p&gt;Ufuna ukuvumela uhlelo lokusebenza ukuthumela umlayezo?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"I-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ithanda ukuthumela umlayezo wombhalo ku-&lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, okuyikhodi efushane ye-SMS ye-premium.&lt;p&gt;&lt;b&gt;Ukuthumela umlayezo kule ndawo kuzobangela i-akhawunti yeselula yakho ukuthi ikhokheliswe amasevisi e-premium.&lt;/b&gt;&lt;p&gt;Ufuna ukuvumela lolu hlelo lokusebenza ukuthumela umlayezo?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Thumela umlayezo?"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Ungathumeli"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Bika uhlelo lokusebenza olungalungile"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Ikhadi le-SIM likhishiwe"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Inethiwekhi yeselula ngeke itholakale kuwena kuze kube uqala kabusha ufake ikhadi le-SIM elifanele."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Kwenziwe"</string>
@@ -1063,10 +1067,8 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Thinta ukwenza ukuthi ukudibhaga kwe-USB kungasebenzi."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Khetha indlela yokufaka"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Izilungiselelo zezindlela zokufakwayo"</string>
-    <!-- no translation found for use_physical_keyboard (6203112478095117625) -->
-    <skip />
-    <!-- no translation found for hardware (7517821086888990278) -->
-    <skip />
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"Ukwakheka kwekhibhodi"</string>
+    <string name="hardware" msgid="7517821086888990278">"I-Hardware"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"abahlanganyeli"</u></string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index de24d10..6f489d4 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2367,8 +2367,6 @@
         <!-- Component name of an activity that allows the user to modify
              the settings for this service. -->
         <attr name="settingsActivity"/>
-        <!-- Set true when the spell checker supports sentence level spell checking. -->
-        <attr name="supportsSentenceSpellCheck" format="boolean" />
     </declare-styleable>
 
     <!-- This is the subtype of the spell checker. Subtype can describe locales (e.g. en_US, fr_FR...) -->
@@ -5382,6 +5380,21 @@
     </declare-styleable>
 
     <!-- =============================== -->
+    <!-- SizeAdaptiveLayout class attributes -->
+    <!-- =============================== -->
+    <eat-comment />
+    <declare-styleable name="SizeAdaptiveLayout_Layout">
+      <!-- The maximum valid height for this item. -->
+      <attr name="layout_maxHeight" format="dimension">
+        <!-- Indicates that the view may be resized arbitrarily large. -->
+        <enum name="unbounded" value="-1" />
+      </attr>
+      <!-- The minimum valid height for this item. -->
+      <attr name="layout_minHeight" format="dimension" />
+    </declare-styleable>
+    <declare-styleable name="SizeAdaptiveLayout" />
+
+    <!-- =============================== -->
     <!-- LockPatternView class attributes -->
     <!-- =============================== -->
     <eat-comment />
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 4a5e442..8ac94fb 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3588,8 +3588,6 @@
 
   <public type="attr" name="parentActivityName" />
 
-  <public type="attr" name="supportsSentenceSpellCheck" />
-
   <public type="attr" name="importantForAccessibility"/>
 
 </resources>
diff --git a/core/tests/coretests/res/drawable/abe.jpg b/core/tests/coretests/res/drawable/abe.jpg
new file mode 100644
index 0000000..1f978a9
--- /dev/null
+++ b/core/tests/coretests/res/drawable/abe.jpg
Binary files differ
diff --git a/core/tests/coretests/res/drawable/gettysburg.png b/core/tests/coretests/res/drawable/gettysburg.png
new file mode 100644
index 0000000..7a2d596
--- /dev/null
+++ b/core/tests/coretests/res/drawable/gettysburg.png
Binary files differ
diff --git a/core/tests/coretests/res/layout/size_adaptive.xml b/core/tests/coretests/res/layout/size_adaptive.xml
new file mode 100644
index 0000000..03d0574
--- /dev/null
+++ b/core/tests/coretests/res/layout/size_adaptive.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.internal.widget.SizeAdaptiveLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:id="@+id/multi1"
+    android:layout_width="match_parent"
+    android:layout_height="64dp" >
+
+    <include
+        android:id="@+id/one_u"
+        layout="@layout/size_adaptive_one_u"
+        android:layout_width="fill_parent"
+        android:layout_height="64dp"
+        internal:layout_minHeight="64dp"
+        internal:layout_maxHeight="64dp"
+        />
+
+    <include
+        android:id="@+id/four_u"
+        layout="@layout/size_adaptive_four_u"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        internal:layout_minHeight="65dp"
+        internal:layout_maxHeight="unbounded"/>
+
+</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_color.xml b/core/tests/coretests/res/layout/size_adaptive_color.xml
new file mode 100644
index 0000000..cdb7a59
--- /dev/null
+++ b/core/tests/coretests/res/layout/size_adaptive_color.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.internal.widget.SizeAdaptiveLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:background="#ffffff"
+    android:id="@+id/multi1"
+    android:layout_width="match_parent"
+    android:layout_height="64dp" >
+
+    <include
+        android:id="@+id/one_u"
+        layout="@layout/size_adaptive_one_u"
+        android:layout_width="fill_parent"
+        android:layout_height="64dp"
+        internal:layout_minHeight="64dp"
+        internal:layout_maxHeight="64dp"
+        />
+
+    <include
+        android:id="@+id/four_u"
+        layout="@layout/size_adaptive_four_u"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        internal:layout_minHeight="65dp"
+        internal:layout_maxHeight="unbounded"/>
+
+</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_four_u.xml b/core/tests/coretests/res/layout/size_adaptive_four_u.xml
new file mode 100644
index 0000000..232b921
--- /dev/null
+++ b/core/tests/coretests/res/layout/size_adaptive_four_u.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/gridLayout4"
+    android:layout_width="match_parent"
+    android:layout_height="256dp"
+    android:background="#000000"
+    android:columnCount="2"
+    android:padding="1dp" >
+
+    <ImageView
+        android:id="@+id/actor"
+        android:layout_width="62dp"
+        android:layout_height="62dp"
+        android:layout_row="0"
+        android:layout_column="0"
+        android:layout_rowSpan="2"
+        android:contentDescription="@string/actor"
+        android:src="@drawable/abe" />
+
+    <TextView
+        android:layout_width="0dp"
+        android:id="@+id/name"
+        android:layout_row="0"
+        android:layout_column="1"
+        android:layout_gravity="fill_horizontal"
+        android:padding="3dp"
+        android:text="@string/actor"
+        android:textColor="#ffffff"
+        android:textStyle="bold" />
+
+    <ImageView
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_row="1"
+        android:layout_column="1"
+        android:layout_gravity="fill_horizontal"
+        android:padding="5dp"
+        android:adjustViewBounds="true"
+        android:background="#555555"
+        android:scaleType="centerCrop"
+        android:src="@drawable/gettysburg"
+        android:contentDescription="@string/caption" />
+
+    <TextView
+        android:layout_width="0dp"
+        android:id="@+id/note"
+        android:layout_row="2"
+        android:layout_column="1"
+        android:layout_gravity="fill_horizontal"
+        android:padding="3dp"
+        android:singleLine="true"
+        android:text="@string/first"
+        android:textColor="#ffffff" />
+</GridLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_four_u_text.xml b/core/tests/coretests/res/layout/size_adaptive_four_u_text.xml
new file mode 100644
index 0000000..93a10de
--- /dev/null
+++ b/core/tests/coretests/res/layout/size_adaptive_four_u_text.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/gridLayout4"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="#000000"
+    android:columnCount="2"
+    android:padding="1dp"
+    android:orientation="horizontal" >
+
+    <ImageView
+        android:id="@+id/actor"
+        android:layout_width="62dp"
+        android:layout_height="62dp"
+        android:layout_row="0"
+        android:layout_column="0"
+        android:layout_rowSpan="2"
+        android:contentDescription="@string/actor"
+        android:src="@drawable/abe" />
+
+    <TextView
+        android:layout_width="0dp"
+        android:id="@+id/name"
+        android:layout_row="0"
+        android:layout_column="1"
+        android:layout_gravity="fill_horizontal"
+        android:padding="3dp"
+        android:text="@string/actor"
+        android:textColor="#ffffff"
+        android:textStyle="bold" />
+
+    <TextView
+        android:id="@+id/note"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_column="1"
+        android:layout_gravity="fill_horizontal"
+        android:layout_marginTop="5dp"
+        android:layout_row="1"
+        android:padding="3dp"
+        android:singleLine="false"
+        android:text="@string/first"
+        android:textColor="#ffffff" />
+
+    </GridLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_gappy.xml b/core/tests/coretests/res/layout/size_adaptive_gappy.xml
new file mode 100644
index 0000000..d5e3b41
--- /dev/null
+++ b/core/tests/coretests/res/layout/size_adaptive_gappy.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.internal.widget.SizeAdaptiveLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:id="@+id/multi_with_gap"
+    android:layout_width="match_parent"
+    android:layout_height="64dp" >
+
+    <include
+        android:id="@+id/one_u"
+        layout="@layout/size_adaptive_one_u"
+        android:layout_width="fill_parent"
+        android:layout_height="64dp"
+        internal:layout_minHeight="64dp"
+        internal:layout_maxHeight="64dp"
+        />
+
+    <include
+        android:id="@+id/four_u"
+        layout="@layout/size_adaptive_four_u"
+        android:layout_width="fill_parent"
+        android:layout_height="256dp"
+        internal:layout_minHeight="128dp"
+        internal:layout_maxHeight="unbounded"/>
+
+</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_large_only.xml b/core/tests/coretests/res/layout/size_adaptive_large_only.xml
new file mode 100644
index 0000000..cf58265
--- /dev/null
+++ b/core/tests/coretests/res/layout/size_adaptive_large_only.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.internal.widget.SizeAdaptiveLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:id="@+id/large_only_multi"
+    android:layout_width="match_parent"
+    android:layout_height="64dp" >
+
+    <include
+        android:id="@+id/four_u"
+        layout="@layout/size_adaptive_four_u"
+        android:layout_width="fill_parent"
+        android:layout_height="256dp"
+        internal:layout_minHeight="65dp"
+        internal:layout_maxHeight="unbounded"/>
+
+</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_one_u.xml b/core/tests/coretests/res/layout/size_adaptive_one_u.xml
new file mode 100644
index 0000000..b6fe4a0
--- /dev/null
+++ b/core/tests/coretests/res/layout/size_adaptive_one_u.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/gridLayout1"
+    android:layout_width="match_parent"
+    android:layout_height="64dp"
+    android:background="#000000"
+    android:columnCount="3"
+    android:padding="1dp"
+    android:rowCount="2" >
+
+    <ImageView
+        android:id="@+id/actor"
+        android:layout_width="62dp"
+        android:layout_height="62dp"
+        android:layout_column="0"
+        android:layout_row="0"
+        android:layout_rowSpan="2"
+        android:contentDescription="@string/actor"
+        android:src="@drawable/abe" />
+
+    <TextView
+        android:id="@+id/name"
+        android:layout_gravity="fill"
+        android:padding="3dp"
+        android:text="@string/actor"
+        android:textColor="#ffffff"
+        android:textStyle="bold" />
+
+    <ImageView
+        android:layout_width="62dp"
+        android:layout_height="62dp"
+        android:layout_gravity="fill_vertical"
+        android:layout_rowSpan="2"
+        android:adjustViewBounds="true"
+        android:background="#555555"
+        android:padding="2dp"
+        android:scaleType="fitXY"
+        android:src="@drawable/gettysburg"
+        android:contentDescription="@string/caption" />
+
+    <TextView
+        android:id="@+id/note"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_gravity="fill"
+        android:layout_marginTop="5dp"
+        android:padding="3dp"
+        android:singleLine="true"
+        android:text="@string/first"
+        android:textColor="#ffffff" />
+
+</GridLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_one_u_text.xml b/core/tests/coretests/res/layout/size_adaptive_one_u_text.xml
new file mode 100644
index 0000000..df54eb6
--- /dev/null
+++ b/core/tests/coretests/res/layout/size_adaptive_one_u_text.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/gridLayout1"
+    android:layout_width="match_parent"
+    android:layout_height="64dp"
+    android:background="#000000"
+    android:columnCount="2"
+    android:padding="1dp"
+    android:rowCount="2" >
+
+    <ImageView
+        android:id="@+id/actor"
+        android:layout_width="62dp"
+        android:layout_height="62dp"
+        android:layout_column="0"
+        android:layout_row="0"
+        android:layout_rowSpan="2"
+        android:contentDescription="@string/actor"
+        android:src="@drawable/abe" />
+
+    <TextView
+        android:id="@+id/name"
+        android:layout_gravity="fill"
+        android:padding="3dp"
+        android:text="@string/actor"
+        android:textColor="#ffffff"
+        android:textStyle="bold" />
+
+    <TextView
+        android:id="@+id/note"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_gravity="fill"
+        android:layout_marginTop="5dp"
+        android:padding="3dp"
+        android:singleLine="true"
+        android:text="@string/first"
+        android:textColor="#ffffff" />
+
+</GridLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_overlapping.xml b/core/tests/coretests/res/layout/size_adaptive_overlapping.xml
new file mode 100644
index 0000000..4abe8b0
--- /dev/null
+++ b/core/tests/coretests/res/layout/size_adaptive_overlapping.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.internal.widget.SizeAdaptiveLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:id="@+id/multi_with_overlap"
+    android:layout_width="match_parent"
+    android:layout_height="64dp" >
+
+    <include
+        android:id="@+id/one_u"
+        layout="@layout/size_adaptive_one_u"
+        android:layout_width="fill_parent"
+        android:layout_height="64dp"
+        internal:layout_minHeight="64dp"
+        internal:layout_maxHeight="64dp"
+        />
+
+    <include
+        android:id="@+id/four_u"
+        layout="@layout/size_adaptive_four_u"
+        android:layout_width="fill_parent"
+        android:layout_height="256dp"
+        internal:layout_minHeight="64dp"
+        internal:layout_maxHeight="256dp"/>
+
+</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_singleton.xml b/core/tests/coretests/res/layout/size_adaptive_singleton.xml
new file mode 100644
index 0000000..eba387f
--- /dev/null
+++ b/core/tests/coretests/res/layout/size_adaptive_singleton.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.internal.widget.SizeAdaptiveLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="64dp" >
+
+    <include
+        android:id="@+id/one_u"
+        layout="@layout/size_adaptive_one_u_text"
+        android:layout_width="fill_parent"
+        android:layout_height="64dp"
+        internal:layout_minHeight="64dp"
+        internal:layout_maxHeight="64dp"
+        />
+
+</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_text.xml b/core/tests/coretests/res/layout/size_adaptive_text.xml
new file mode 100644
index 0000000..a9f0ba9
--- /dev/null
+++ b/core/tests/coretests/res/layout/size_adaptive_text.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.internal.widget.SizeAdaptiveLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:id="@+id/multi1"
+    android:layout_width="match_parent"
+    android:layout_height="64dp" >
+
+    <include
+        android:id="@+id/one_u"
+        layout="@layout/size_adaptive_one_u_text"
+        android:layout_width="fill_parent"
+        android:layout_height="64dp"
+        internal:layout_minHeight="64dp"
+        internal:layout_maxHeight="64dp"
+        />
+
+    <include
+        android:id="@+id/four_u"
+        layout="@layout/size_adaptive_four_u_text"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        internal:layout_minHeight="65dp"
+        internal:layout_maxHeight="unbounded"/>
+
+</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_three_way.xml b/core/tests/coretests/res/layout/size_adaptive_three_way.xml
new file mode 100644
index 0000000..1eb5396
--- /dev/null
+++ b/core/tests/coretests/res/layout/size_adaptive_three_way.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.internal.widget.SizeAdaptiveLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:id="@+id/three_way_multi"
+    android:layout_width="match_parent"
+    android:layout_height="64dp" >
+
+    <include
+        android:id="@+id/one_u"
+        layout="@layout/size_adaptive_one_u"
+        android:layout_width="fill_parent"
+        android:layout_height="64dp"
+        internal:layout_minHeight="64dp"
+        internal:layout_maxHeight="64dp"
+        />
+
+    <include
+        android:id="@+id/two_u"
+        layout="@layout/size_adaptive_four_u"
+        android:layout_width="fill_parent"
+        android:layout_height="128dp"
+        internal:layout_minHeight="65dp"
+        internal:layout_maxHeight="128dp"/>
+
+    <include
+        android:id="@+id/four_u"
+        layout="@layout/size_adaptive_four_u"
+        android:layout_width="fill_parent"
+        android:layout_height="256dp"
+        internal:layout_minHeight="129dp"
+        internal:layout_maxHeight="unbounded"/>
+
+</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/values/strings.xml b/core/tests/coretests/res/values/strings.xml
index 71f3520..ce0d9a2 100644
--- a/core/tests/coretests/res/values/strings.xml
+++ b/core/tests/coretests/res/values/strings.xml
@@ -131,4 +131,8 @@
 
     <string name="textview_hebrew_text">&#x05DD;&#x05DE;ab?!</string>
 
+    <!-- SizeAdaptiveLayout -->
+    <string name="first">Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.</string>
+    <string name="actor">Abe Lincoln</string>
+    <string name="caption">Lincoln adressing the crowd at Gettysburgh</string>
 </resources>
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 9575ced..580b4da 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -170,11 +170,10 @@
         return ipm;
     }
 
-    public boolean invokeInstallPackage(Uri packageURI, int flags, GenericReceiver receiver) {
+    public void invokeInstallPackage(Uri packageURI, int flags, GenericReceiver receiver,
+            boolean shouldSucceed) {
         PackageInstallObserver observer = new PackageInstallObserver();
-        final boolean received = false;
         mContext.registerReceiver(receiver, receiver.filter);
-        final boolean DEBUG = true;
         try {
             // Wait on observer
             synchronized(observer) {
@@ -192,10 +191,24 @@
                     if(!observer.isDone()) {
                         fail("Timed out waiting for packageInstalled callback");
                     }
-                    if (observer.returnCode != PackageManager.INSTALL_SUCCEEDED) {
-                        Log.i(TAG, "Failed to install with error code = " + observer.returnCode);
-                        return false;
+
+                    if (shouldSucceed) {
+                        if (observer.returnCode != PackageManager.INSTALL_SUCCEEDED) {
+                            fail("Package installation should have succeeded, but got code "
+                                    + observer.returnCode);
+                        }
+                    } else {
+                        if (observer.returnCode == PackageManager.INSTALL_SUCCEEDED) {
+                            fail("Package installation should fail");
+                        }
+
+                        /*
+                         * We'll never expect get a notification since we
+                         * shouldn't succeed.
+                         */
+                        return;
                     }
+
                     // Verify we received the broadcast
                     waitTime = 0;
                     while((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
@@ -209,7 +222,6 @@
                     if(!receiver.isDone()) {
                         fail("Timed out waiting for PACKAGE_ADDED notification");
                     }
-                    return receiver.received;
                 }
             }
         } finally {
@@ -588,7 +600,7 @@
                 }
             } else {
                 InstallReceiver receiver = new InstallReceiver(pkg.packageName);
-                assertTrue(invokeInstallPackage(packageURI, flags, receiver));
+                invokeInstallPackage(packageURI, flags, receiver, true);
                 // Verify installed information
                 assertInstall(pkg, flags, expInstallLocation);
             }
@@ -705,13 +717,9 @@
             receiver = new InstallReceiver(ip.pkg.packageName);
         }
         try {
-            try {
-                assertEquals(invokeInstallPackage(ip.packageURI, flags, receiver), replace);
-                if (replace) {
-                    assertInstall(ip.pkg, flags, ip.pkg.installLocation);
-                }
-            } catch (Exception e) {
-                failStr("Failed with exception : " + e);
+            invokeInstallPackage(ip.packageURI, flags, receiver, replace);
+            if (replace) {
+                assertInstall(ip.pkg, flags, ip.pkg.installLocation);
             }
         } finally {
             cleanUpInstall(ip);
@@ -1244,7 +1252,7 @@
         GenericReceiver receiver = new ReplaceReceiver(ip.pkg.packageName);
         int replaceFlags = rFlags | PackageManager.INSTALL_REPLACE_EXISTING;
         try {
-            assertEquals(invokeInstallPackage(ip.packageURI, replaceFlags, receiver), true);
+            invokeInstallPackage(ip.packageURI, replaceFlags, receiver, true);
             assertInstall(ip.pkg, rFlags, ip.pkg.installLocation);
         } catch (Exception e) {
             failStr("Failed with exception : " + e);
@@ -1271,7 +1279,7 @@
         GenericReceiver receiver = new ReplaceReceiver(ip.pkg.packageName);
         int replaceFlags = rFlags | PackageManager.INSTALL_REPLACE_EXISTING;
         try {
-            assertEquals(invokeInstallPackage(ip.packageURI, replaceFlags, receiver), true);
+            invokeInstallPackage(ip.packageURI, replaceFlags, receiver, true);
             assertInstall(ip.pkg, iFlags, ip.pkg.installLocation);
         } catch (Exception e) {
             failStr("Failed with exception : " + e);
diff --git a/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java
new file mode 100644
index 0000000..fc83e4a
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2012 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.widget;
+
+import com.android.frameworks.coretests.R;
+
+import android.content.Context;
+import android.graphics.drawable.ColorDrawable;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.android.internal.widget.SizeAdaptiveLayout;
+
+
+public class SizeAdaptiveLayoutTest extends AndroidTestCase {
+
+    private LayoutInflater mInflater;
+    private int mOneU;
+    private int mFourU;
+    private SizeAdaptiveLayout mSizeAdaptiveLayout;
+    private View mSmallView;
+    private View mMediumView;
+    private View mLargeView;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // inflate the layout
+        final Context context = getContext();
+        mInflater = LayoutInflater.from(context);
+        mOneU = 64;
+        mFourU = 4 * mOneU;
+    }
+
+    private void inflate(int resource){
+        mSizeAdaptiveLayout = (SizeAdaptiveLayout) mInflater.inflate(resource, null);
+        mSizeAdaptiveLayout.onAttachedToWindow();
+
+        mSmallView = mSizeAdaptiveLayout.findViewById(R.id.one_u);
+        mMediumView = mSizeAdaptiveLayout.findViewById(R.id.two_u);
+        mLargeView = mSizeAdaptiveLayout.findViewById(R.id.four_u);
+    }
+
+    /**
+     * The name 'test preconditions' is a convention to signal that if this
+     * test doesn't pass, the test case was not set up properly and it might
+     * explain any and all failures in other tests.  This is not guaranteed
+     * to run before other tests, as junit uses reflection to find the tests.
+     */
+    @SmallTest
+    public void testPreconditions() {
+        assertNotNull(mInflater);
+
+        inflate(R.layout.size_adaptive);
+        assertNotNull(mSizeAdaptiveLayout);
+        assertNotNull(mSmallView);
+        assertNotNull(mLargeView);
+    }
+
+    @SmallTest
+    public void testOpenLarge() {
+        inflate(R.layout.size_adaptive);
+        SizeAdaptiveLayout.LayoutParams lp =
+          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
+        int height = (int) lp.minHeight + 10;
+
+        measureAndLayout(height);
+
+        assertEquals("4U should be visible",
+                View.VISIBLE,
+                mLargeView.getVisibility());
+        assertEquals("1U should be gone",
+                View.GONE,
+                mSmallView.getVisibility());
+    }
+
+    @SmallTest
+    public void testOpenSmall() {
+        inflate(R.layout.size_adaptive);
+        SizeAdaptiveLayout.LayoutParams lp =
+          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
+        int height = (int) lp.minHeight;
+
+        measureAndLayout(height);
+
+        assertEquals("1U should be visible",
+                View.VISIBLE,
+                mSmallView.getVisibility());
+        assertEquals("4U should be gone",
+                View.GONE,
+                mLargeView.getVisibility());
+    }
+
+    @SmallTest
+    public void testOpenTooSmall() {
+        inflate(R.layout.size_adaptive);
+        SizeAdaptiveLayout.LayoutParams lp =
+          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
+        int height = (int) lp.minHeight - 10;
+
+        measureAndLayout(height);
+
+        assertEquals("1U should be visible",
+                View.VISIBLE,
+                mSmallView.getVisibility());
+        assertEquals("4U should be gone",
+                View.GONE,
+                mLargeView.getVisibility());
+    }
+
+    @SmallTest
+    public void testOpenTooBig() {
+        inflate(R.layout.size_adaptive);
+        SizeAdaptiveLayout.LayoutParams lp =
+          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
+        lp.maxHeight = 500;
+        mLargeView.setLayoutParams(lp);
+        int height = (int) (lp.minHeight + 10);
+
+        measureAndLayout(height);
+
+        assertEquals("4U should be visible",
+                View.VISIBLE,
+                mLargeView.getVisibility());
+        assertEquals("1U should be gone",
+                View.GONE,
+                mSmallView.getVisibility());
+    }
+
+    @SmallTest
+    public void testOpenWrapContent() {
+        inflate(R.layout.size_adaptive_text);
+        SizeAdaptiveLayout.LayoutParams lp =
+          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
+        int height = (int) lp.minHeight + 10;
+
+        // manually measure it, and lay it out
+        int measureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);
+        mSizeAdaptiveLayout.measure(500, measureSpec);
+        assertTrue("should not be forced to 4U",
+                mSizeAdaptiveLayout.getMeasuredHeight() < mFourU);
+    }
+
+    @SmallTest
+    public void testOpenOneUOnlySmall() {
+        inflate(R.layout.size_adaptive_singleton);
+        assertNull("largeView should be NULL in the singleton layout", mLargeView);
+
+        SizeAdaptiveLayout.LayoutParams lp =
+          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
+        int height = (int) lp.minHeight - 10;
+
+        measureAndLayout(height);
+
+        assertEquals("1U should be visible",
+                View.VISIBLE,
+                mSmallView.getVisibility());
+    }
+
+    @SmallTest
+    public void testOpenOneUOnlyLarge() {
+        inflate(R.layout.size_adaptive_singleton);
+        assertNull("largeView should be NULL in the singleton layout", mLargeView);
+
+        SizeAdaptiveLayout.LayoutParams lp =
+          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
+        int height = (int) lp.maxHeight + 10;
+
+        measureAndLayout(height);
+
+        assertEquals("1U should be visible",
+                View.VISIBLE,
+                mSmallView.getVisibility());
+    }
+
+    @SmallTest
+    public void testOpenOneUOnlyJustRight() {
+        inflate(R.layout.size_adaptive_singleton);
+        assertNull("largeView should be NULL in the singleton layout", mLargeView);
+
+        SizeAdaptiveLayout.LayoutParams lp =
+          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
+        int height = (int) lp.minHeight;
+
+        measureAndLayout(height);
+
+        assertEquals("1U should be visible",
+                View.VISIBLE,
+                mSmallView.getVisibility());
+    }
+
+    @SmallTest
+    public void testOpenFourUOnlySmall() {
+        inflate(R.layout.size_adaptive_large_only);
+        assertNull("smallView should be NULL in the singleton layout", mSmallView);
+
+        SizeAdaptiveLayout.LayoutParams lp =
+          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
+        int height = (int) lp.minHeight - 10;
+
+        measureAndLayout(height);
+
+        assertEquals("4U should be visible",
+                View.VISIBLE,
+                mLargeView.getVisibility());
+    }
+
+    @SmallTest
+    public void testOpenFourUOnlyLarge() {
+        inflate(R.layout.size_adaptive_large_only);
+        assertNull("smallView should be NULL in the singleton layout", mSmallView);
+
+        SizeAdaptiveLayout.LayoutParams lp =
+          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
+        int height = (int) lp.maxHeight + 10;
+
+        measureAndLayout(height);
+
+        assertEquals("4U should be visible",
+                View.VISIBLE,
+                mLargeView.getVisibility());
+    }
+
+    @SmallTest
+    public void testOpenFourUOnlyJustRight() {
+        inflate(R.layout.size_adaptive_large_only);
+        assertNull("smallView should be NULL in the singleton layout", mSmallView);
+
+        SizeAdaptiveLayout.LayoutParams lp =
+          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
+        int height = (int) lp.minHeight;
+
+        measureAndLayout(height);
+
+        assertEquals("4U should be visible",
+                View.VISIBLE,
+                mLargeView.getVisibility());
+    }
+
+    @SmallTest
+    public void testOpenIntoAGap() {
+        inflate(R.layout.size_adaptive_gappy);
+
+        SizeAdaptiveLayout.LayoutParams smallParams =
+          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
+        SizeAdaptiveLayout.LayoutParams largeParams =
+          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
+        assertTrue("gappy layout should have a gap",
+                smallParams.maxHeight + 10 < largeParams.minHeight);
+        int height = (int) smallParams.maxHeight + 10;
+
+        measureAndLayout(height);
+
+        assertTrue("one and only one view should be visible",
+                mLargeView.getVisibility() != mSmallView.getVisibility());
+        // behavior is undefined in this case.
+    }
+
+    @SmallTest
+    public void testOpenIntoAnOverlap() {
+        inflate(R.layout.size_adaptive_overlapping);
+
+        SizeAdaptiveLayout.LayoutParams smallParams =
+          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
+        SizeAdaptiveLayout.LayoutParams largeParams =
+          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
+        assertEquals("overlapping layout should overlap",
+                smallParams.minHeight,
+                largeParams.minHeight);
+        int height = (int) smallParams.maxHeight;
+
+        measureAndLayout(height);
+
+        assertTrue("one and only one view should be visible",
+                mLargeView.getVisibility() != mSmallView.getVisibility());
+        assertEquals("1U should get priority in an overlap because it is first",
+                View.VISIBLE,
+                mSmallView.getVisibility());
+    }
+
+    @SmallTest
+    public void testOpenThreeWayViewSmall() {
+        inflate(R.layout.size_adaptive_three_way);
+        assertNotNull("mMediumView should not be NULL in the three view layout", mMediumView);
+
+        SizeAdaptiveLayout.LayoutParams lp =
+          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
+        int height = (int) lp.minHeight;
+
+        measureAndLayout(height);
+
+        assertEquals("1U should be visible",
+                View.VISIBLE,
+                mSmallView.getVisibility());
+        assertEquals("2U should be gone",
+                View.GONE,
+                mMediumView.getVisibility());
+        assertEquals("4U should be gone",
+                View.GONE,
+                mLargeView.getVisibility());
+    }
+
+    @SmallTest
+    public void testOpenThreeWayViewMedium() {
+        inflate(R.layout.size_adaptive_three_way);
+        assertNotNull("mMediumView should not be NULL in the three view layout", mMediumView);
+
+        SizeAdaptiveLayout.LayoutParams lp =
+          (SizeAdaptiveLayout.LayoutParams) mMediumView.getLayoutParams();
+        int height = (int) lp.minHeight;
+
+        measureAndLayout(height);
+
+        assertEquals("1U should be gone",
+                View.GONE,
+                mSmallView.getVisibility());
+        assertEquals("2U should be visible",
+                View.VISIBLE,
+                mMediumView.getVisibility());
+        assertEquals("4U should be gone",
+                View.GONE,
+                mLargeView.getVisibility());
+    }
+
+    @SmallTest
+    public void testOpenThreeWayViewLarge() {
+        inflate(R.layout.size_adaptive_three_way);
+        assertNotNull("mMediumView should not be NULL in the three view layout", mMediumView);
+
+        SizeAdaptiveLayout.LayoutParams lp =
+          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
+        int height = (int) lp.minHeight;
+
+        measureAndLayout(height);
+
+        assertEquals("1U should be gone",
+                View.GONE,
+                mSmallView.getVisibility());
+        assertEquals("2U should be gone",
+                View.GONE,
+                mMediumView.getVisibility());
+        assertEquals("4U should be visible",
+                View.VISIBLE,
+                mLargeView.getVisibility());
+    }
+
+    @SmallTest
+    public void testResizeWithoutAnimation() {
+        inflate(R.layout.size_adaptive);
+
+        SizeAdaptiveLayout.LayoutParams largeParams =
+          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
+        int startHeight = (int) largeParams.minHeight + 10;
+        int endHeight = (int) largeParams.minHeight + 10;
+
+        measureAndLayout(startHeight);
+
+        assertEquals("4U should be visible",
+                View.VISIBLE,
+                mLargeView.getVisibility());
+        assertFalse("There should be no animation on initial rendering.",
+                    mSizeAdaptiveLayout.getTransitionAnimation().isRunning());
+
+        measureAndLayout(endHeight);
+
+        assertEquals("4U should still be visible",
+                View.VISIBLE,
+                mLargeView.getVisibility());
+        assertFalse("There should be no animation on scale within a view.",
+                    mSizeAdaptiveLayout.getTransitionAnimation().isRunning());
+    }
+
+    @SmallTest
+    public void testResizeWithAnimation() {
+        inflate(R.layout.size_adaptive);
+
+        SizeAdaptiveLayout.LayoutParams smallParams =
+          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
+        SizeAdaptiveLayout.LayoutParams largeParams =
+          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
+        int startHeight = (int) largeParams.minHeight + 10;
+        int endHeight = (int) smallParams.maxHeight;
+
+        measureAndLayout(startHeight);
+
+        assertEquals("4U should be visible",
+                View.VISIBLE,
+                mLargeView.getVisibility());
+        assertFalse("There should be no animation on initial rendering.",
+                    mSizeAdaptiveLayout.getTransitionAnimation().isRunning());
+
+        measureAndLayout(endHeight);
+
+        assertEquals("1U should now be visible",
+                View.VISIBLE,
+                mSmallView.getVisibility());
+        assertTrue("There should be an animation on scale between views.",
+                   mSizeAdaptiveLayout.getTransitionAnimation().isRunning());
+    }
+
+    @SmallTest
+    public void testModestyPanelChangesColorWhite() {
+        inflate(R.layout.size_adaptive_color);
+        View panel = mSizeAdaptiveLayout.getModestyPanel();
+        assertTrue("ModestyPanel should have a ColorDrawable background",
+                   panel.getBackground() instanceof ColorDrawable);
+        ColorDrawable panelColor = (ColorDrawable) panel.getBackground();
+        ColorDrawable salColor = (ColorDrawable) mSizeAdaptiveLayout.getBackground();
+        assertEquals("ModestyPanel color should match the SizeAdaptiveLayout",
+                     panelColor.getColor(), salColor.getColor());
+    }
+
+    @SmallTest
+    public void testModestyPanelHasDefault() {
+        inflate(R.layout.size_adaptive);
+        View panel = mSizeAdaptiveLayout.getModestyPanel();
+        assertNull("SizeAdaptiveLayout should have no background for this test",
+                     mSizeAdaptiveLayout.getBackground());
+        assertTrue("ModestyPanel should have a ColorDrawable background",
+                   panel.getBackground() instanceof ColorDrawable);
+    }
+
+    private void measureAndLayout(int height) {
+        // manually measure it, and lay it out
+        int measureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);
+        mSizeAdaptiveLayout.measure(500, measureSpec);
+        mSizeAdaptiveLayout.layout(0, 0, 500, height);
+    }
+}
diff --git a/docs/html/shareables/training/LocationAware.zip b/docs/html/shareables/training/LocationAware.zip
index 46970cd..8ed97cb 100644
--- a/docs/html/shareables/training/LocationAware.zip
+++ b/docs/html/shareables/training/LocationAware.zip
Binary files differ
diff --git a/docs/html/training/location/locationmanager.jd b/docs/html/training/location/locationmanager.jd
index 5da1205..61abcbd 100644
--- a/docs/html/training/location/locationmanager.jd
+++ b/docs/html/training/location/locationmanager.jd
@@ -18,6 +18,7 @@
   <li><a href="locationmanager.html#TaskDeclarePermissions">Declare Proper Permissions in Android Manifest</a></li>
   <li><a href="locationmanager.html#TaskGetLocationManagerRef">Get a Reference to LocationManager</a></li>
   <li><a href="locationmanager.html#TaskPickLocationProvider">Pick a Location Provider</a></li>
+  <li><a href="locationmanager.html#TaskVerifyProvider">Verify the Location Provider is Enabled</a></li>
 </ol>
 
 <h2>You should also read</h2>
@@ -88,3 +89,32 @@
    ...
 }
 </pre>
+
+<h2 id="TaskVerifyProvider">Verify the Location Provider is Enabled</h2>
+
+<p>Some location providers such as the GPS can be disabled in Settings.  It is good practice to check whether the desired location provider is currently enabled by calling the {@link android.location.LocationManager#isProviderEnabled(java.lang.String) isProviderEnabled()} method.  If the location provider is disabled, you can offer the user an opportunity to enable it in Settings by firing an {@link android.content.Intent} with the {@link android.provider.Settings#ACTION_LOCATION_SOURCE_SETTINGS} action.</p>
+
+<pre>
+&#64;Override
+protected void onStart() {
+    super.onStart();
+
+    // This verification should be done during onStart() because the system calls
+    // this method when the user returns to the activity, which ensures the desired
+    // location provider is enabled each time the activity resumes from the stopped state.
+    LocationManager locationManager =
+            (LocationManager) getSystemService(Context.LOCATION_SERVICE);
+    final boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
+
+    if (!gpsEnabled) {
+        // Build an alert dialog here that requests that the user enable
+        // the location services, then when the user clicks the "OK" button,
+        // call enableLocationSettings()
+    }
+}
+
+private void enableLocationSettings() {
+    Intent settingsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
+    startActivity(settingsIntent);
+}
+</pre>
diff --git a/graphics/java/android/graphics/Insets.java b/graphics/java/android/graphics/Insets.java
new file mode 100644
index 0000000..c570cd4
--- /dev/null
+++ b/graphics/java/android/graphics/Insets.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2006 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.graphics;
+
+/**
+ * An Insets instance holds four integer offsets which describe changes to the four
+ * edges of a Rectangle. By convention, positive values move edges towards the
+ * centre of the rectangle.
+ * <p>
+ * Insets are immutable so may be treated as values.
+ *
+ * @hide
+ */
+public class Insets {
+    public static final Insets NONE = new Insets(0, 0, 0, 0);
+
+    public final int left;
+    public final int top;
+    public final int right;
+    public final int bottom;
+
+    private Insets(int left, int top, int right, int bottom) {
+        this.left = left;
+        this.top = top;
+        this.right = right;
+        this.bottom = bottom;
+    }
+
+    // Factory methods
+
+    /**
+     * Return an Insets instance with the appropriate values.
+     *
+     * @param left the left inset
+     * @param top the top inset
+     * @param right the right inset
+     * @param bottom the bottom inset
+     *
+     * @return Insets instance with the appropriate values
+     */
+    public static Insets of(int left, int top, int right, int bottom) {
+        if (left == 0 && top == 0 && right == 0 && bottom == 0) {
+            return NONE;
+        }
+        return new Insets(left, top, right, bottom);
+    }
+
+    /**
+     * Return an Insets instance with the appropriate values.
+     *
+     * @param r the rectangle from which to take the values
+     *
+     * @return an Insets instance with the appropriate values
+     */
+    public static Insets of(Rect r) {
+        return of(r.left, r.top, r.right, r.bottom);
+    }
+
+    /**
+     * Two Insets instances are equal iff they belong to the same class and their fields are
+     * pairwise equal.
+     *
+     * @param o the object to compare this instance with.
+     *
+     * @return true iff this object is equal {@code o}
+     */
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Insets insets = (Insets) o;
+
+        if (bottom != insets.bottom) return false;
+        if (left != insets.left) return false;
+        if (right != insets.right) return false;
+        if (top != insets.top) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = left;
+        result = 31 * result + top;
+        result = 31 * result + right;
+        result = 31 * result + bottom;
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "Insets{" +
+                "left=" + left +
+                ", top=" + top +
+                ", right=" + right +
+                ", bottom=" + bottom +
+                '}';
+    }
+}
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 3fc20b5..4beaecd 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -159,7 +159,7 @@
      * It will implicitly bind its texture to the GL_TEXTURE_EXTERNAL_OES texture target.
      */
     public void updateTexImage() {
-        nativeUpdateTexImage(); 
+        nativeUpdateTexImage();
     }
 
     /**
@@ -172,8 +172,6 @@
      * This can be used to access the SurfaceTexture image contents from multiple OpenGL ES
      * contexts.  Note, however, that the image contents are only accessible from one OpenGL ES
      * context at a time.
-     *
-     * @hide
      */
     public void detachFromGLContext() {
         int err = nativeDetachFromGLContext();
@@ -194,8 +192,6 @@
      *
      * @param texName The name of the OpenGL ES texture that will be created.  This texture name
      * must be unusued in the OpenGL ES context that is current on the calling thread.
-     *
-     * @hide
      */
     public void attachToGLContext(int texName) {
         int err = nativeAttachToGLContext(texName);
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 86e824b..7d1942a 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -705,6 +705,20 @@
     }
 
     /**
+     * Return in insets the layout insets suggested by this Drawable for use with alignment
+     * operations during layout. Positive values move toward the
+     * center of the Drawable. Returns true if this drawable
+     * actually has a layout insets, else false. When false is returned, the padding
+     * is always set to 0.
+     *
+     * @hide
+     */
+    public boolean getLayoutInsets(Rect insets) {
+        insets.set(0, 0, 0, 0);
+        return false;
+    }
+
+    /**
      * Make this drawable mutable. This operation cannot be reversed. A mutable
      * drawable is guaranteed to not share its state with any other drawable.
      * This is especially useful when you need to modify properties of drawables
@@ -965,9 +979,7 @@
             Rect pad, Rect layoutBounds, String srcName) {
 
         if (np != null) {
-            NinePatchDrawable npd = new NinePatchDrawable(res, bm, np, pad, srcName);
-            npd.setLayoutBounds(layoutBounds);
-            return npd;
+            return new NinePatchDrawable(res, bm, np, pad, layoutBounds, srcName);
         }
 
         return new BitmapDrawable(res, bm);
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index b0f7fd3..e10f9e8 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -90,6 +90,18 @@
         }
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public boolean getLayoutInsets(Rect insets) {
+        if (mCurrDrawable != null) {
+            return mCurrDrawable.getLayoutInsets(insets);
+        } else {
+            return super.getLayoutInsets(insets);
+        }
+    }
+
     @Override
     public void setAlpha(int alpha) {
         if (mAlpha != alpha) {
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 1272071..e502b7a 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -16,9 +16,17 @@
 
 package android.graphics.drawable;
 
-import android.graphics.*;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.NinePatch;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.Region;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
@@ -29,7 +37,7 @@
 import java.io.InputStream;
 
 /**
- * 
+ *
  * A resizeable bitmap, with stretchable areas that you define. This type of image
  * is defined in a .png file with a special format.
  *
@@ -47,7 +55,6 @@
     private NinePatchState mNinePatchState;
     private NinePatch mNinePatch;
     private Rect mPadding;
-    private Rect mLayoutBounds;
     private Paint mPaint;
     private boolean mMutated;
 
@@ -56,7 +63,7 @@
     // These are scaled to match the target density.
     private int mBitmapWidth;
     private int mBitmapHeight;
-    
+
     NinePatchDrawable() {
     }
 
@@ -69,7 +76,7 @@
     public NinePatchDrawable(Bitmap bitmap, byte[] chunk, Rect padding, String srcName) {
         this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), null);
     }
-    
+
     /**
      * Create drawable from raw nine-patch data, setting initial target density
      * based on the display metrics of the resources.
@@ -79,7 +86,19 @@
         this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), res);
         mNinePatchState.mTargetDensity = mTargetDensity;
     }
-    
+
+    /**
+     * Create drawable from raw nine-patch data, setting initial target density
+     * based on the display metrics of the resources.
+     *
+     * @hide
+     */
+    public NinePatchDrawable(Resources res, Bitmap bitmap, byte[] chunk,
+            Rect padding, Rect layoutInsets, String srcName) {
+        this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding, layoutInsets), res);
+        mNinePatchState.mTargetDensity = mTargetDensity;
+    }
+
     /**
      * Create drawable from existing nine-patch, not dealing with density.
      * @deprecated Use {@link #NinePatchDrawable(Resources, NinePatch)}
@@ -99,13 +118,6 @@
         mNinePatchState.mTargetDensity = mTargetDensity;
     }
 
-    /**
-     * @hide
-     */
-    void setLayoutBounds(Rect layoutBounds) {
-        mLayoutBounds = layoutBounds;
-    }
-
     private void setNinePatchState(NinePatchState state, Resources res) {
         mNinePatchState = state;
         mNinePatch = state.mNinePatch;
@@ -201,13 +213,26 @@
     public int getChangingConfigurations() {
         return super.getChangingConfigurations() | mNinePatchState.mChangingConfigurations;
     }
-    
+
     @Override
     public boolean getPadding(Rect padding) {
         padding.set(mPadding);
         return true;
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public boolean getLayoutInsets(Rect insets) {
+        Rect layoutInsets = mNinePatchState.mLayoutInsets;
+        if (layoutInsets == null) {
+            return super.getLayoutInsets(insets);
+        }
+        insets.set(layoutInsets);
+        return true;
+    }
+
     @Override
     public void setAlpha(int alpha) {
         if (mPaint == null && alpha == 0xFF) {
@@ -217,7 +242,7 @@
         getPaint().setAlpha(alpha);
         invalidateSelf();
     }
-    
+
     @Override
     public void setColorFilter(ColorFilter cf) {
         if (mPaint == null && cf == null) {
@@ -267,6 +292,7 @@
         options.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
 
         final Rect padding = new Rect();
+        final Rect layoutInsets = new Rect();
         Bitmap bitmap = null;
 
         try {
@@ -290,7 +316,7 @@
 
         setNinePatchState(new NinePatchState(
                 new NinePatch(bitmap, bitmap.getNinePatchChunk(), "XML 9-patch"),
-                padding, dither), r);
+                padding, layoutInsets, dither), r);
         mNinePatchState.mTargetDensity = mTargetDensity;
 
         a.recycle();
@@ -344,7 +370,7 @@
     public Region getTransparentRegion() {
         return mNinePatch.getTransparentRegion(getBounds());
     }
-    
+
     @Override
     public ConstantState getConstantState() {
         mNinePatchState.mChangingConfigurations = getChangingConfigurations();
@@ -361,27 +387,36 @@
         return this;
     }
 
-    final static class NinePatchState extends ConstantState {
+    private final static class NinePatchState extends ConstantState {
         final NinePatch mNinePatch;
         final Rect mPadding;
+        final Rect mLayoutInsets;
         final boolean mDither;
         int mChangingConfigurations;
         int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
 
         NinePatchState(NinePatch ninePatch, Rect padding) {
-            this(ninePatch, padding, DEFAULT_DITHER);
+            this(ninePatch, padding, new Rect(), DEFAULT_DITHER);
         }
 
-        NinePatchState(NinePatch ninePatch, Rect rect, boolean dither) {
+        NinePatchState(NinePatch ninePatch, Rect padding, Rect layoutInsets) {
+            this(ninePatch, padding, layoutInsets, DEFAULT_DITHER);
+        }
+
+        NinePatchState(NinePatch ninePatch, Rect rect, Rect layoutInsets, boolean dither) {
             mNinePatch = ninePatch;
             mPadding = rect;
+            mLayoutInsets = layoutInsets;
             mDither = dither;
         }
 
+        // Copy constructor
+
         NinePatchState(NinePatchState state) {
             mNinePatch = new NinePatch(state.mNinePatch);
             // Note we don't copy the padding because it is immutable.
             mPadding = state.mPadding;
+            mLayoutInsets = state.mLayoutInsets;
             mDither = state.mDither;
             mChangingConfigurations = state.mChangingConfigurations;
             mTargetDensity = state.mTargetDensity;
@@ -391,12 +426,12 @@
         public Drawable newDrawable() {
             return new NinePatchDrawable(this, null);
         }
-        
+
         @Override
         public Drawable newDrawable(Resources res) {
             return new NinePatchDrawable(this, res);
         }
-        
+
         @Override
         public int getChangingConfigurations() {
             return mChangingConfigurations;
diff --git a/include/utils/Trace.h b/include/utils/Trace.h
new file mode 100644
index 0000000..a0112d0
--- /dev/null
+++ b/include/utils/Trace.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef ANDROID_TRACE_H
+#define ANDROID_TRACE_H
+
+#define ATRACE_TAG_NEVER    0           // The "never" tag is never enabled.
+#define ATRACE_TAG_ALWAYS   (1<<0)      // The "always" tag is always enabled.
+#define ATRACE_TAG_GRAPHICS (1<<1)
+#define ATRACE_TAG_INPUT    (1<<2)
+#define ATRACE_TAG_VIEW     (1<<3)
+#define ATRACE_TAG_WEBVIEW  (1<<4)
+
+#define ATRACE_CALL()
+
+#define ATRACE_INT(name, value)
+
+#define ATRACE_ENABLED() false
+
+namespace android {
+
+class ScopedTrace {
+
+public:
+    inline ScopedTrace(uint64_t tag, const char* name) {}
+};
+
+}; // namespace android
+
+#endif // ANDROID_TRACE_H
diff --git a/media/java/android/media/Crypto.java b/media/java/android/media/Crypto.java
deleted file mode 100644
index 43e34fb..0000000
--- a/media/java/android/media/Crypto.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-/**
- * Crypto class can be used in conjunction with MediaCodec to decode
- * encrypted media data.
- * @hide
-*/
-public final class Crypto {
-    public static final native boolean isCryptoSchemeSupported(byte[] uuid);
-
-    public Crypto(byte[] uuid, byte[] initData) {
-        native_setup(uuid, initData);
-    }
-
-    public final native boolean requiresSecureDecoderComponent(String mime);
-
-    @Override
-    protected void finalize() {
-        native_finalize();
-    }
-
-    public native final void release();
-    private static native final void native_init();
-    private native final void native_setup(byte[] uuid, byte[] initData);
-    private native final void native_finalize();
-
-    static {
-        System.loadLibrary("media_jni");
-        native_init();
-    }
-
-    private int mNativeContext;
-}
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 410383d..a65c2aa 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -16,7 +16,7 @@
 
 package android.media;
 
-import android.media.Crypto;
+import android.media.MediaCrypto;
 import android.view.Surface;
 import java.nio.ByteBuffer;
 import java.util.Map;
@@ -24,7 +24,122 @@
 /**
  * MediaCodec class can be used to access low-level media codec, i.e.
  * encoder/decoder components.
- * @hide
+ *
+ * <p>MediaCodec is generally used like this:
+ * <pre>
+ * MediaCodec codec = MediaCodec.createDecoderByType(type);
+ * codec.configure(format, ...);
+ * codec.start();
+ * ByteBuffer[] inputBuffers = codec.getInputBuffers();
+ * ByteBuffer[] outputBuffers = codec.getOutputBuffers();
+ * Map<String, Object> format = codec.getOutputFormat();
+ * for (;;) {
+ *   int inputBufferIndex = codec.dequeueInputBuffer(timeoutUs);
+ *   if (inputBufferIndex &gt;= 0) {
+ *     // fill inputBuffers[inputBufferIndex] with valid data
+ *     ...
+ *     codec.queueInputBuffer(inputBufferIndex, ...);
+ *   }
+ *
+ *   int outputBufferIndex = codec.dequeueOutputBuffer(timeoutUs);
+ *   if (outputBufferIndex &gt;= 0) {
+ *     // outputBuffer is ready to be processed or rendered.
+ *     ...
+ *     codec.releaseOutputBuffer(outputBufferIndex, ...);
+ *   } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+ *     outputBuffers = codec.getOutputBuffers();
+ *   } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+ *     // Subsequent data will conform to new format.
+ *     format = codec.getOutputFormat();
+ *     ...
+ *   }
+ * }
+ * codec.stop();
+ * codec.release();
+ * codec = null;
+ * </pre>
+ *
+ * Each codec maintains a number of input and output buffers that are
+ * referred to by index in API calls.
+ * The contents of these buffers is represented by the ByteBuffer[] arrays
+ * accessible through getInputBuffers() and getOutputBuffers().
+ *
+ * After a successful call to {@link #start} the client "owns" neither
+ * input nor output buffers, subsequent calls to {@link #dequeueInputBuffer}
+ * and {@link #dequeueOutputBuffer} then transfer ownership from the codec
+ * to the client.<p>
+ * The client is not required to resubmit/release buffers immediately
+ * to the codec, the sample code above simply does this for simplicity's sake.<p>
+ * Once the client has an input buffer available it can fill it with data
+ * and submit it it to the codec via a call to {@link #queueInputBuffer}.<p>
+ * The codec in turn will return an output buffer to the client in response
+ * to {@link #dequeueOutputBuffer}. After the output buffer has been processed
+ * a call to {@link #releaseOutputBuffer} will return it to the codec.
+ * If a video surface has been provided in the call to {@link #configure},
+ * {@link #releaseOutputBuffer} optionally allows rendering of the buffer
+ * to the surface.<p>
+ *
+ * Input buffers (for decoders) and Output buffers (for encoders) contain
+ * encoded data according to the format's type. For video types this data
+ * is all the encoded data representing a single moment in time, for audio
+ * data this is slightly relaxed in that a buffer may contain multiple
+ * encoded frames of audio. In either case, buffers do not start and end on
+ * arbitrary byte boundaries, this is not a stream of bytes, it's a stream
+ * of access units.<p>
+ *
+ * Most formats also require the actual data to be prefixed by a number
+ * of buffers containing setup data, or codec specific data, i.e. the
+ * first few buffers submitted to the codec object after starting it must
+ * be codec specific data marked as such using the flag {@link #FLAG_CODECCONFIG}
+ * in a call to {@link #queueInputBuffer}.
+ *
+ * Once the client reaches the end of the input data it signals the end of
+ * the input stream by specifying a flag of {@link #FLAG_EOS} in the call to
+ * {@link #queueInputBuffer}. The codec will continue to return output buffers
+ * until it eventually signals the end of the output stream by specifying
+ * the same flag ({@link #FLAG_EOS}) on the BufferInfo returned in
+ * {@link #dequeueOutputBuffer}.
+ *
+ * In order to start decoding data that's not adjacent to previously submitted
+ * data (i.e. after a seek) it is necessary to {@link #flush} the decoder.
+ * Any input or output buffers the client may own at the point of the flush are
+ * immediately revoked, i.e. after a call to {@link #flush} the client does not
+ * own any buffers anymore.
+ * Note that the format of the data submitted after a flush must not change,
+ * flush does not support format discontinuities,
+ * for this a full stop(), configure(), start() cycle is necessary.
+ *
+ * The format of the media data is specified as string/value pairs represented
+ * as a Map<String, Object>.<p>
+ *
+ * Fields common to all formats:
+ *
+ * <table>
+ * <tr><th>Name</th><th>Value Type</th><th>Description</th></tr>
+ * <tr><td>mime</td><td>String</td><td>The type of the format.</td></tr>
+ * <tr><td>max-input-size</td><td>Integer</td><td>optional, maximum size of a buffer of input data</td></tr>
+ * <tr><td>bitrate</td><td>Integer</td><td><b>encoder-only</b>, desired bitrate in bits/second</td></tr>
+ * </table>
+ *
+ * Video formats have the following fields:
+ * <table>
+ * <tr><th>Name</th><th>Value Type</th><th>Description</th></tr>
+ * <tr><td>width</td><td>Integer</td><td></td></tr>
+ * <tr><td>height</td><td>Integer</td><td></td></tr>
+ * <tr><td>color-format</td><td>Integer</td><td><b>encoder-only</b></td></tr>
+ * <tr><td>frame-rate</td><td>Integer or Float</td><td><b>encoder-only</b></td></tr>
+ * <tr><td>i-frame-interval</td><td>Integer</td><td><b>encoder-only</b></td></tr>
+ * <tr><td>stride</td><td>Integer</td><td><b>encoder-only</b>, optional, defaults to width</td></tr>
+ * <tr><td>slice-height</td><td>Integer</td><td><b>encoder-only</b>, optional, defaults to height</td></tr>
+ * </table>
+ *
+ * Audio formats have the following fields:
+ * <table>
+ * <tr><th>Name</th><th>Value Type</th><th>Description</th></tr>
+ * <tr><td>channel-count</td><td>Integer</td><td></td></tr>
+ * <tr><td>sample-rate</td><td>Integer</td><td></td></tr>
+ * </table>
+ *
 */
 final public class MediaCodec {
     /** Per buffer metadata includes an offset and size specifying
@@ -32,43 +147,62 @@
     */
     public final static class BufferInfo {
         public void set(
-                int offset, int size, long timeUs, int flags) {
-            mOffset = offset;
-            mSize = size;
-            mPresentationTimeUs = timeUs;
-            mFlags = flags;
+                int newOffset, int newSize, long newTimeUs, int newFlags) {
+            offset = newOffset;
+            size = newSize;
+            presentationTimeUs = newTimeUs;
+            flags = newFlags;
         }
 
-        public int mOffset;
-        public int mSize;
-        public long mPresentationTimeUs;
-        public int mFlags;
+        public int offset;
+        public int size;
+        public long presentationTimeUs;
+        public int flags;
     };
 
     // The follow flag constants MUST stay in sync with their equivalents
     // in MediaCodec.h !
-    public static int FLAG_SYNCFRAME   = 1;
-    public static int FLAG_CODECCONFIG = 2;
-    public static int FLAG_EOS         = 4;
+
+    /** This indicates that the buffer marked as such contains the data
+        for a sync frame.
+    */
+    public static final int FLAG_SYNCFRAME   = 1;
+
+    /** This indicated that the buffer marked as such contains codec
+        initialization / codec specific data instead of media data.
+    */
+    public static final int FLAG_CODECCONFIG = 2;
+
+    /** This signals the end of stream, i.e. no buffers will be available
+        after this, unless of course, {@link #flush} follows.
+    */
+    public static final int FLAG_EOS         = 4;
 
     // The following mode constants MUST stay in sync with their equivalents
     // in media/hardware/CryptoAPI.h !
-    public static int MODE_UNENCRYPTED = 0;
-    public static int MODE_AES_CTR     = 1;
+    public static final int MODE_UNENCRYPTED = 0;
+    public static final int MODE_AES_CTR     = 1;
 
-    /** Instantiate a codec component by mime type. For decoder components
-        this is the mime type of media that this decoder should be able to
-        decoder, for encoder components it's the type of media this encoder
-        should encode _to_.
+    /** Instantiate a decoder supporting input data of the given mime type.
+      * @param type The mime type of the input data.
     */
-    public static MediaCodec CreateByType(String type, boolean encoder) {
-        return new MediaCodec(type, true /* nameIsType */, encoder);
+    public static MediaCodec createDecoderByType(String type) {
+        return new MediaCodec(type, true /* nameIsType */, false /* encoder */);
+    }
+
+    /** Instantiate an encoder supporting output data of the given mime type.
+      * @param type The desired mime type of the output data.
+    */
+    public static MediaCodec createEncoderByType(String type) {
+        return new MediaCodec(type, true /* nameIsType */, true /* encoder */);
     }
 
     /** If you know the exact name of the component you want to instantiate
         use this method to instantiate it. Use with caution.
+        Likely to be used with information obtained from {@link android.media.MediaCodecList}
+        @param name The name of the codec to be instantiated.
     */
-    public static MediaCodec CreateByComponentName(String name) {
+    public static MediaCodec createByCodecName(String name) {
         return new MediaCodec(
                 name, false /* nameIsType */, false /* unused */);
     }
@@ -88,35 +222,14 @@
     // to do this for you at some point in the future.
     public native final void release();
 
+    /** If this codec is to be used as an encoder, pass this flag.
+      */
     public static int CONFIGURE_FLAG_ENCODE = 1;
 
     /** Configures a component.
-     *  @param format A map of string/value pairs describing the input format
-     *                (decoder) or the desired output format.
      *
-     *                Video formats have the following fields:
-     *                  "mime"          - String
-     *                  "width"         - Integer
-     *                  "height"        - Integer
-     *                  optional "max-input-size"       - Integer
-     *
-     *                Audio formats have the following fields:
-     *                  "mime"          - String
-     *                  "channel-count" - Integer
-     *                  "sample-rate"   - Integer
-     *                  optional "max-input-size"       - Integer
-     *
-     *                If the format is used to configure an encoder, additional
-     *                fields must be included:
-     *                  "bitrate" - Integer (in bits/sec)
-     *
-     *                for video formats:
-     *                  "color-format"          - Integer
-     *                  "frame-rate"            - Integer or Float
-     *                  "i-frame-interval"      - Integer
-     *                  optional "stride"       - Integer, defaults to "width"
-     *                  optional "slice-height" - Integer, defaults to "height"
-     *
+     *  @param format The format of the input data (decoder) or the desired
+     *                format of the output data (encoder).
      *  @param surface Specify a surface on which to render the output of this
      *                 decoder.
      *  @param crypto  Specify a crypto object to facilitate secure decryption
@@ -126,7 +239,7 @@
     */
     public void configure(
             Map<String, Object> format,
-            Surface surface, Crypto crypto, int flags) {
+            Surface surface, MediaCrypto crypto, int flags) {
         String[] keys = null;
         Object[] values = null;
 
@@ -147,18 +260,23 @@
 
     private native final void native_configure(
             String[] keys, Object[] values,
-            Surface surface, Crypto crypto, int flags);
+            Surface surface, MediaCrypto crypto, int flags);
 
     /** After successfully configuring the component, call start. On return
      *  you can query the component for its input/output buffers.
     */
     public native final void start();
 
+    /** Finish the decode/encode session, note that the codec instance
+      * remains active and ready to be {@link #start}ed again.
+      * To ensure that it is available to other client call {@link #release}
+      * and don't just rely on garbage collection to eventually do this for you.
+    */
     public native final void stop();
 
     /** Flush both input and output ports of the component, all indices
-     *  previously returned in calls to dequeueInputBuffer and
-     *  dequeueOutputBuffer become invalid.
+     *  previously returned in calls to {@link #dequeueInputBuffer} and
+     *  {@link #dequeueOutputBuffer} become invalid.
     */
     public native final void flush();
 
@@ -169,24 +287,36 @@
      *  preceded by "codec specific data", i.e. setup data used to initialize
      *  the codec such as PPS/SPS in the case of AVC video or code tables
      *  in the case of vorbis audio.
-     *  The class MediaExtractor provides codec specific data as part of
+     *  The class {@link android.media.MediaExtractor} provides codec
+     *  specific data as part of
      *  the returned track format in entries named "csd-0", "csd-1" ...
      *
      *  These buffers should be submitted using the flag {@link #FLAG_CODECCONFIG}.
      *
      *  To indicate that this is the final piece of input data (or rather that
      *  no more input data follows unless the decoder is subsequently flushed)
-     *  specify the flag {@link FLAG_EOS}.
+     *  specify the flag {@link #FLAG_EOS}.
+     *
+     *  @param index The index of a client-owned input buffer previously returned
+     *               in a call to {@link #dequeueInputBuffer}.
+     *  @param offset The byte offset into the input buffer at which the data starts.
+     *  @param size The number of bytes of valid input data.
+     *  @param presentationTimeUs The time at which this buffer should be rendered.
+     *  @param flags A bitmask of flags {@link #FLAG_SYNCFRAME},
+     *               {@link #FLAG_CODECCONFIG} or {@link #FLAG_EOS}.
     */
     public native final void queueInputBuffer(
             int index,
             int offset, int size, long presentationTimeUs, int flags);
 
-    /** Similar to {@link queueInputBuffer} but submits a buffer that is
+    /** Similar to {@link #queueInputBuffer} but submits a buffer that is
      *  potentially encrypted. The buffer's data is considered to be
      *  partitioned into "subSamples", each subSample starts with a
      *  (potentially empty) run of plain, unencrypted bytes followed
      *  by a (also potentially empty) run of encrypted bytes.
+     *  @param index The index of a client-owned input buffer previously returned
+     *               in a call to {@link #dequeueInputBuffer}.
+     *  @param offset The byte offset into the input buffer at which the data starts.
      *  @param numBytesOfClearData The number of leading unencrypted bytes in
      *                             each subSample.
      *  @param numBytesOfEncryptedData The number of trailing encrypted bytes
@@ -212,27 +342,48 @@
             long presentationTimeUs,
             int flags);
 
-    // Returns the index of an input buffer to be filled with valid data
-    // or -1 if no such buffer is currently available.
-    // This method will return immediately if timeoutUs == 0, wait indefinitely
-    // for the availability of an input buffer if timeoutUs < 0 or wait up
-    // to "timeoutUs" microseconds if timeoutUs > 0.
+    /** Returns the index of an input buffer to be filled with valid data
+     *  or -1 if no such buffer is currently available.
+     *  This method will return immediately if timeoutUs == 0, wait indefinitely
+     *  for the availability of an input buffer if timeoutUs &lt; 0 or wait up
+     *  to "timeoutUs" microseconds if timeoutUs &gt; 0.
+     *  @param timeoutUs The timeout in microseconds, a negative timeout indicates "infinite".
+    */
     public native final int dequeueInputBuffer(long timeoutUs);
 
-    // Returns the index of an output buffer that has been successfully
-    // decoded or one of the INFO_* constants below.
-    // The provided "info" will be filled with buffer meta data.
+    /** If a non-negative timeout had been specified in the call
+     * to {@link #dequeueOutputBuffer}, indicates that the call timed out.
+    */
     public static final int INFO_TRY_AGAIN_LATER        = -1;
+
+    /** The output format has changed, subsequent data will follow the new
+     *  format. {@link #getOutputFormat} returns the new format.
+    */
     public static final int INFO_OUTPUT_FORMAT_CHANGED  = -2;
+
+    /** The output buffers have changed, the client must refer to the new
+     *  set of output buffers returned by {@link #getOutputBuffers} from
+     *  this point on.
+    */
     public static final int INFO_OUTPUT_BUFFERS_CHANGED = -3;
 
-    /** Dequeue an output buffer, block at most "timeoutUs" microseconds. */
+    /** Dequeue an output buffer, block at most "timeoutUs" microseconds.
+     *  Returns the index of an output buffer that has been successfully
+     *  decoded or one of the INFO_* constants below.
+     *  @param info Will be filled with buffer meta data.
+     *  @param timeoutUs The timeout in microseconds, a negative timeout indicates "infinite".
+    */
     public native final int dequeueOutputBuffer(
             BufferInfo info, long timeoutUs);
 
-    // If you are done with a buffer, use this call to return the buffer to
-    // the codec. If you previously specified a surface when configuring this
-    // video decoder you can optionally render the buffer.
+    /** If you are done with a buffer, use this call to return the buffer to
+     *  the codec. If you previously specified a surface when configuring this
+     *  video decoder you can optionally render the buffer.
+     *  @param index The index of a client-owned output buffer previously returned
+     *               in a call to {@link #dequeueOutputBuffer}.
+     *  @param render If a valid surface was specified when configuring the codec,
+     *                passing true renders this output buffer to the surface.
+    */
     public native final void releaseOutputBuffer(int index, boolean render);
 
     /** Call this after dequeueOutputBuffer signals a format change by returning
diff --git a/media/java/android/media/MediaCodecList.java b/media/java/android/media/MediaCodecList.java
index b46ce96..1772e9c 100644
--- a/media/java/android/media/MediaCodecList.java
+++ b/media/java/android/media/MediaCodecList.java
@@ -20,22 +20,42 @@
  * MediaCodecList class can be used to enumerate available codecs,
  * find a codec supporting a given format and query the capabilities
  * of a given codec.
- * @hide
 */
 final public class MediaCodecList {
+    /** Count the number of available codecs.
+      */
     public static native final int countCodecs();
+
+    /** Retrieve the codec name at the specified index. */
     public static native final String getCodecName(int index);
+
+    /** Query if the codec at the specified index is an encoder. */
     public static native final boolean isEncoder(int index);
+
+    /** Query the media types supported by the codec at the specified index */
     public static native final String[] getSupportedTypes(int index);
 
     public static final class CodecProfileLevel {
-        public int mProfile;
-        public int mLevel;
+        /** Defined in the OpenMAX IL specs, depending on the type of media
+          * this can be OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263PROFILETYPE
+          * or OMX_VIDEO_MPEG4PROFILETYPE.
+        */
+        public int profile;
+
+        /** Defined in the OpenMAX IL specs, depending on the type of media
+          * this can be OMX_VIDEO_AVCLEVELTYPE, OMX_VIDEO_H263LEVELTYPE
+          * or OMX_VIDEO_MPEG4LEVELTYPE.
+        */
+        public int level;
     };
 
     public static final class CodecCapabilities {
-        public CodecProfileLevel[] mProfileLevels;
-        public int[] mColorFormats;
+        public CodecProfileLevel[] profileLevels;
+
+        /** Defined in the OpenMAX IL specs, color format values are drawn from
+          * OMX_COLOR_FORMATTYPE.
+        */
+        public int[] colorFormats;
     };
     public static native final CodecCapabilities getCodecCapabilities(
             int index, String type);
diff --git a/media/java/android/media/MediaCrypto.java b/media/java/android/media/MediaCrypto.java
new file mode 100644
index 0000000..b84ed72
--- /dev/null
+++ b/media/java/android/media/MediaCrypto.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * MediaCrypto class can be used in conjunction with {@link android.media.MediaCodec}
+ * to decode encrypted media data.
+ *
+ * Crypto schemes are assigned 16 byte UUIDs,
+ * the method {@link #isCryptoSchemeSupported} can be used to query if a given
+ * scheme is supported on the device.
+ *
+*/
+public final class MediaCrypto {
+    /** Query if the given scheme identified by its UUID is supported on
+      * this device.
+      * @param uuid The UUID of the crypto scheme.
+    */
+    public static final native boolean isCryptoSchemeSupported(byte[] uuid);
+
+    /** Instantiate a MediaCrypto object using opaque, crypto scheme specific
+      * data.
+      * @param uuid The UUID of the crypto scheme.
+      * @param initData Opaque initialization data specific to the crypto scheme.
+    */
+    public MediaCrypto(byte[] uuid, byte[] initData) throws RuntimeException {
+        native_setup(uuid, initData);
+    }
+
+    /** Query if the crypto scheme requires the use of a secure decoder
+      * to decode data of the given mime type.
+      * @param mime The mime type of the media data
+    */
+    public final native boolean requiresSecureDecoderComponent(String mime);
+
+    @Override
+    protected void finalize() {
+        native_finalize();
+    }
+
+    public native final void release();
+    private static native final void native_init();
+    private native final void native_setup(byte[] uuid, byte[] initData);
+    private native final void native_finalize();
+
+    static {
+        System.loadLibrary("media_jni");
+        native_init();
+    }
+
+    private int mNativeContext;
+}
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 9c3b6a7..3f8b2ca 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -16,63 +16,227 @@
 
 package android.media;
 
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.net.Uri;
+import java.io.FileDescriptor;
+import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.Map;
 
 /**
- * MediaExtractor
- * @hide
+ * MediaExtractor facilitates extraction of demuxed, typically encoded,  media data
+ * from a data source.
+ * <p>It is generally used like this:
+ * <pre>
+ * MediaExtractor extractor = new MediaExtractor();
+ * extractor.setDataSource(...);
+ * int numTracks = extractor.countTracks();
+ * for (int i = 0; i &lt; numTracks; ++i) {
+ *   Map%lt;String, Object&gt; format = extractor.getTrackFormat(i);
+ *   String mime = (String)format.get("mime");
+ *   if (weAreInterestedInThisTrack) {
+ *     extractor.selectTrack(i);
+ *   }
+ * }
+ * ByteBuffer inputBuffer = ByteBuffer.allocate(...)
+ * while (extractor.readSampleData(inputBuffer, ...) &gt;= 0) {
+ *   int trackIndex = extractor.getTrackIndex();
+ *   long presentationTimeUs = extractor.getSampleTime();
+ *   ...
+ *   extractor.advance();
+ * }
+ *
+ * extractor.release();
+ * extractor = null;
+ * </pre>
 */
 final public class MediaExtractor {
-    public MediaExtractor(String path) {
-        native_setup(path);
+    public MediaExtractor() {
+        native_setup();
     }
 
+    /**
+     * Sets the data source as a content Uri.
+     *
+     * @param context the Context to use when resolving the Uri
+     * @param uri the Content URI of the data you want to extract from.
+     * @param headers the headers to be sent together with the request for the data
+     */
+    public final void setDataSource(
+            Context context, Uri uri, Map<String, String> headers)
+        throws IOException {
+        String scheme = uri.getScheme();
+        if(scheme == null || scheme.equals("file")) {
+            setDataSource(uri.getPath());
+            return;
+        }
+
+        AssetFileDescriptor fd = null;
+        try {
+            ContentResolver resolver = context.getContentResolver();
+            fd = resolver.openAssetFileDescriptor(uri, "r");
+            if (fd == null) {
+                return;
+            }
+            // Note: using getDeclaredLength so that our behavior is the same
+            // as previous versions when the content provider is returning
+            // a full file.
+            if (fd.getDeclaredLength() < 0) {
+                setDataSource(fd.getFileDescriptor());
+            } else {
+                setDataSource(
+                        fd.getFileDescriptor(),
+                        fd.getStartOffset(),
+                        fd.getDeclaredLength());
+            }
+            return;
+        } catch (SecurityException ex) {
+        } catch (IOException ex) {
+        } finally {
+            if (fd != null) {
+                fd.close();
+            }
+        }
+
+        setDataSource(uri.toString(), headers);
+    }
+
+    /**
+     * Sets the data source (file-path or http URL) to use.
+     *
+     * @param path the path of the file, or the http URL
+     * @param headers the headers associated with the http request for the stream you want to play
+     */
+    public final void setDataSource(String path, Map<String, String> headers) {
+        String[] keys = null;
+        String[] values = null;
+
+        if (headers != null) {
+            keys = new String[headers.size()];
+            values = new String[headers.size()];
+
+            int i = 0;
+            for (Map.Entry<String, String> entry: headers.entrySet()) {
+                keys[i] = entry.getKey();
+                values[i] = entry.getValue();
+                ++i;
+            }
+        }
+        setDataSource(path, keys, values);
+    }
+
+    private native final void setDataSource(
+            String path, String[] keys, String[] values);
+
+    /**
+     * Sets the data source (file-path or http URL) to use.
+     *
+     * @param path the path of the file, or the http URL of the stream
+     *
+     * <p>When <code>path</code> refers to a local file, the file may actually be opened by a
+     * process other than the calling application.  This implies that the pathname
+     * should be an absolute path (as any other process runs with unspecified current working
+     * directory), and that the pathname should reference a world-readable file.
+     * As an alternative, the application could first open the file for reading,
+     * and then use the file descriptor form {@link #setDataSource(FileDescriptor)}.
+     */
+    public final void setDataSource(String path) {
+        setDataSource(path, null, null);
+    }
+
+    /**
+     * Sets the data source (FileDescriptor) to use. It is the caller's responsibility
+     * to close the file descriptor. It is safe to do so as soon as this call returns.
+     *
+     * @param fd the FileDescriptor for the file you want to extract from.
+     */
+    public final void setDataSource(FileDescriptor fd) {
+        setDataSource(fd, 0, 0x7ffffffffffffffL);
+    }
+
+    /**
+     * Sets the data source (FileDescriptor) to use.  The FileDescriptor must be
+     * seekable (N.B. a LocalSocket is not seekable). It is the caller's responsibility
+     * to close the file descriptor. It is safe to do so as soon as this call returns.
+     *
+     * @param fd the FileDescriptor for the file you want to extract from.
+     * @param offset the offset into the file where the data to be extracted starts, in bytes
+     * @param length the length in bytes of the data to be extracted
+     */
+    public native final void setDataSource(
+            FileDescriptor fd, long offset, long length);
+
     @Override
     protected void finalize() {
         native_finalize();
     }
 
-    // Make sure you call this when you're done to free up any resources
-    // instead of relying on the garbage collector to do this for you at
-    // some point in the future.
+    /** Make sure you call this when you're done to free up any resources
+     *  instead of relying on the garbage collector to do this for you at
+     *   some point in the future.
+    */
     public native final void release();
 
+    /** Count the number of tracks found in the data source.
+     */
     public native int countTracks();
+
+    /** Get the track format at the specified index.
+      * More detail on the representation can be found at {@link android.media.MediaCodec}
+    */
     public native Map<String, Object> getTrackFormat(int index);
 
-    // Subsequent calls to "readSampleData", "getSampleTrackIndex" and
-    // "getSampleTime" only retrieve information for the subset of tracks
-    // selected by the call below.
-    // Selecting the same track multiple times has no effect, the track
-    // is only selected once.
+    /** Subsequent calls to {@link #readSampleData}, {@link #getSampleTrackIndex} and
+     *  {@link #getSampleTime} only retrieve information for the subset of tracks
+     *  selected by the call below.
+     *  Selecting the same track multiple times has no effect, the track
+     *  only selected once.
+     *  Media data will be returned in the order of their timestamps.
+    */
     public native void selectTrack(int index);
 
-    // All selected tracks seek near the requested time. The next sample
-    // returned for each selected track will be a sync sample.
+    /** All selected tracks seek near the requested time. The next sample
+     *  returned for each selected track will be a sync sample.
+    */
     public native void seekTo(long timeUs);
 
+    /** Advance to the next sample. Returns false if no more sample data
+     *  is available (end of stream).
+     */
     public native boolean advance();
 
-    // Retrieve the current encoded sample and store it in the byte buffer
-    // starting at the given offset. Returns the sample size.
+    /** Retrieve the current encoded sample and store it in the byte buffer
+     *  starting at the given offset. Returns the sample size (or -1 if
+     *  no more samples are available).
+    */
     public native int readSampleData(ByteBuffer byteBuf, int offset);
 
-    // Returns the track index the current sample originates from.
+    /** Returns the track index the current sample originates from (or -1
+     *  if no more samples are available)
+    */
     public native int getSampleTrackIndex();
 
-    // Returns the current sample's presentation time in microseconds.
+    /** Returns the current sample's presentation time in microseconds.
+     *  or -1 if no more samples are available.
+    */
     public native long getSampleTime();
 
     // Keep these in sync with their equivalents in NuMediaExtractor.h
+    /** The sample is a sync sample */
     public static final int SAMPLE_FLAG_SYNC      = 1;
+
+    /** The sample is (at least partially) encrypted, see also the documentation
+     *  for {@link android.media.MediaCodec#queueSecureInputBuffer}
+    */
     public static final int SAMPLE_FLAG_ENCRYPTED = 2;
 
-    // Returns the current sample's flags.
+    /** Returns the current sample's flags. */
     public native int getSampleFlags();
 
     private static native final void native_init();
-    private native final void native_setup(String path);
+    private native final void native_setup();
     private native final void native_finalize();
 
     static {
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index a3361d4..98e1bc5 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -2,7 +2,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-    android_media_Crypto.cpp \
+    android_media_MediaCrypto.cpp \
     android_media_MediaCodec.cpp \
     android_media_MediaCodecList.cpp \
     android_media_MediaExtractor.cpp \
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 01d3833..979ffb0 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -20,7 +20,7 @@
 
 #include "android_media_MediaCodec.h"
 
-#include "android_media_Crypto.h"
+#include "android_media_MediaCrypto.h"
 #include "android_media_Utils.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/android_view_Surface.h"
@@ -656,7 +656,7 @@
 
     { "native_configure",
       "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;"
-      "Landroid/media/Crypto;I)V",
+      "Landroid/media/MediaCrypto;I)V",
       (void *)android_media_MediaCodec_native_configure },
 
     { "start", "()V", (void *)android_media_MediaCodec_start },
diff --git a/media/jni/android_media_MediaCodecList.cpp b/media/jni/android_media_MediaCodecList.cpp
index 2b8f91e..7139560 100644
--- a/media/jni/android_media_MediaCodecList.cpp
+++ b/media/jni/android_media_MediaCodecList.cpp
@@ -118,10 +118,10 @@
         env->NewObjectArray(profileLevels.size(), profileLevelClazz, NULL);
 
     jfieldID profileField =
-        env->GetFieldID(profileLevelClazz, "mProfile", "I");
+        env->GetFieldID(profileLevelClazz, "profile", "I");
 
     jfieldID levelField =
-        env->GetFieldID(profileLevelClazz, "mLevel", "I");
+        env->GetFieldID(profileLevelClazz, "level", "I");
 
     for (size_t i = 0; i < profileLevels.size(); ++i) {
         const MediaCodecList::ProfileLevel &src = profileLevels.itemAt(i);
@@ -139,7 +139,7 @@
 
     jfieldID profileLevelsField = env->GetFieldID(
             capsClazz,
-            "mProfileLevels",
+            "profileLevels",
             "[Landroid/media/MediaCodecList$CodecProfileLevel;");
 
     env->SetObjectField(caps, profileLevelsField, profileLevelArray);
@@ -155,7 +155,7 @@
     }
 
     jfieldID colorFormatsField = env->GetFieldID(
-            capsClazz, "mColorFormats", "[I");
+            capsClazz, "colorFormats", "[I");
 
     env->SetObjectField(caps, colorFormatsField, colorFormatsArray);
 
diff --git a/media/jni/android_media_Crypto.cpp b/media/jni/android_media_MediaCrypto.cpp
similarity index 79%
rename from media/jni/android_media_Crypto.cpp
rename to media/jni/android_media_MediaCrypto.cpp
index e1a60a1..f4f0953 100644
--- a/media/jni/android_media_Crypto.cpp
+++ b/media/jni/android_media_MediaCrypto.cpp
@@ -15,10 +15,10 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "Crypto-JNI"
+#define LOG_TAG "MediaCrypto-JNI"
 #include <utils/Log.h>
 
-#include "android_media_Crypto.h"
+#include "android_media_MediaCrypto.h"
 
 #include "android_runtime/AndroidRuntime.h"
 #include "jni.h"
@@ -124,7 +124,7 @@
 
 // static
 sp<ICrypto> JCrypto::GetCrypto(JNIEnv *env, jobject obj) {
-    jclass clazz = env->FindClass("android/media/Crypto");
+    jclass clazz = env->FindClass("android/media/MediaCrypto");
     CHECK(clazz != NULL);
 
     if (!env->IsInstanceOf(obj, clazz)) {
@@ -158,19 +158,19 @@
     return old;
 }
 
-static void android_media_Crypto_release(JNIEnv *env, jobject thiz) {
+static void android_media_MediaCrypto_release(JNIEnv *env, jobject thiz) {
     setCrypto(env, thiz, NULL);
 }
 
-static void android_media_Crypto_native_init(JNIEnv *env) {
-    jclass clazz = env->FindClass("android/media/Crypto");
+static void android_media_MediaCrypto_native_init(JNIEnv *env) {
+    jclass clazz = env->FindClass("android/media/MediaCrypto");
     CHECK(clazz != NULL);
 
     gFields.context = env->GetFieldID(clazz, "mNativeContext", "I");
     CHECK(gFields.context != NULL);
 }
 
-static void android_media_Crypto_native_setup(
+static void android_media_MediaCrypto_native_setup(
         JNIEnv *env, jobject thiz,
         jbyteArray uuidObj, jbyteArray initDataObj) {
     jsize uuidLength = env->GetArrayLength(uuidObj);
@@ -186,16 +186,23 @@
     jboolean isCopy;
     jbyte *uuid = env->GetByteArrayElements(uuidObj, &isCopy);
 
-    jsize initDataLength = env->GetArrayLength(initDataObj);
-    jbyte *initData = env->GetByteArrayElements(initDataObj, &isCopy);
+    jsize initDataLength = 0;
+    jbyte *initData = NULL;
+
+    if (initDataObj != NULL) {
+        initDataLength = env->GetArrayLength(initDataObj);
+        initData = env->GetByteArrayElements(initDataObj, &isCopy);
+    }
 
     sp<JCrypto> crypto = new JCrypto(
             env, thiz, (const uint8_t *)uuid, initData, initDataLength);
 
     status_t err = crypto->initCheck();
 
-    env->ReleaseByteArrayElements(initDataObj, initData, 0);
-    initData = NULL;
+    if (initDataObj != NULL) {
+        env->ReleaseByteArrayElements(initDataObj, initData, 0);
+        initData = NULL;
+    }
 
     env->ReleaseByteArrayElements(uuidObj, uuid, 0);
     uuid = NULL;
@@ -203,7 +210,7 @@
     if (err != OK) {
         jniThrowException(
                 env,
-                "java/io/IOException",
+                "java/lang/RuntimeException",
                 "Failed to instantiate crypto object.");
         return;
     }
@@ -211,12 +218,12 @@
     setCrypto(env,thiz, crypto);
 }
 
-static void android_media_Crypto_native_finalize(
+static void android_media_MediaCrypto_native_finalize(
         JNIEnv *env, jobject thiz) {
-    android_media_Crypto_release(env, thiz);
+    android_media_MediaCrypto_release(env, thiz);
 }
 
-static jboolean android_media_Crypto_isCryptoSchemeSupported(
+static jboolean android_media_MediaCrypto_isCryptoSchemeSupported(
         JNIEnv *env, jobject thiz, jbyteArray uuidObj) {
     jsize uuidLength = env->GetArrayLength(uuidObj);
 
@@ -239,7 +246,7 @@
     return result;
 }
 
-static jboolean android_media_Crypto_requiresSecureDecoderComponent(
+static jboolean android_media_MediaCrypto_requiresSecureDecoderComponent(
         JNIEnv *env, jobject thiz, jstring mimeObj) {
     if (mimeObj == NULL) {
         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
@@ -268,24 +275,24 @@
 }
 
 static JNINativeMethod gMethods[] = {
-    { "release", "()V", (void *)android_media_Crypto_release },
-    { "native_init", "()V", (void *)android_media_Crypto_native_init },
+    { "release", "()V", (void *)android_media_MediaCrypto_release },
+    { "native_init", "()V", (void *)android_media_MediaCrypto_native_init },
 
     { "native_setup", "([B[B)V",
-      (void *)android_media_Crypto_native_setup },
+      (void *)android_media_MediaCrypto_native_setup },
 
     { "native_finalize", "()V",
-      (void *)android_media_Crypto_native_finalize },
+      (void *)android_media_MediaCrypto_native_finalize },
 
     { "isCryptoSchemeSupported", "([B)Z",
-      (void *)android_media_Crypto_isCryptoSchemeSupported },
+      (void *)android_media_MediaCrypto_isCryptoSchemeSupported },
 
     { "requiresSecureDecoderComponent", "(Ljava/lang/String;)Z",
-      (void *)android_media_Crypto_requiresSecureDecoderComponent },
+      (void *)android_media_MediaCrypto_requiresSecureDecoderComponent },
 };
 
 int register_android_media_Crypto(JNIEnv *env) {
     return AndroidRuntime::registerNativeMethods(env,
-                "android/media/Crypto", gMethods, NELEM(gMethods));
+                "android/media/MediaCrypto", gMethods, NELEM(gMethods));
 }
 
diff --git a/media/jni/android_media_Crypto.h b/media/jni/android_media_MediaCrypto.h
similarity index 100%
rename from media/jni/android_media_Crypto.h
rename to media/jni/android_media_MediaCrypto.h
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 8c661b7..9883962 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -63,8 +63,13 @@
     mClass = NULL;
 }
 
-status_t JMediaExtractor::setDataSource(const char *path) {
-    return mImpl->setDataSource(path);
+status_t JMediaExtractor::setDataSource(
+        const char *path, const KeyedVector<String8, String8> *headers) {
+    return mImpl->setDataSource(path, headers);
+}
+
+status_t JMediaExtractor::setDataSource(int fd, off64_t offset, off64_t size) {
+    return mImpl->setDataSource(fd, offset, size);
 }
 
 size_t JMediaExtractor::countTracks() const {
@@ -200,7 +205,7 @@
 
     if (extractor == NULL) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return NULL;
+        return -1;
     }
 
     return extractor->countTracks();
@@ -380,24 +385,42 @@
 }
 
 static void android_media_MediaExtractor_native_setup(
-        JNIEnv *env, jobject thiz, jstring path) {
+        JNIEnv *env, jobject thiz) {
     sp<JMediaExtractor> extractor = new JMediaExtractor(env, thiz);
+    setMediaExtractor(env,thiz, extractor);
+}
 
-    if (path == NULL) {
+static void android_media_MediaExtractor_setDataSource(
+        JNIEnv *env, jobject thiz,
+        jstring pathObj, jobjectArray keysArray, jobjectArray valuesArray) {
+    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
+
+    if (extractor == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+
+    if (pathObj == NULL) {
         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         return;
     }
 
-    const char *tmp = env->GetStringUTFChars(path, NULL);
-
-    if (tmp == NULL) {
+    KeyedVector<String8, String8> headers;
+    if (!ConvertKeyValueArraysToKeyedVector(
+                env, keysArray, valuesArray, &headers)) {
         return;
     }
 
-    status_t err = extractor->setDataSource(tmp);
+    const char *path = env->GetStringUTFChars(pathObj, NULL);
 
-    env->ReleaseStringUTFChars(path, tmp);
-    tmp = NULL;
+    if (path == NULL) {
+        return;
+    }
+
+    status_t err = extractor->setDataSource(path, &headers);
+
+    env->ReleaseStringUTFChars(pathObj, path);
+    path = NULL;
 
     if (err != OK) {
         jniThrowException(
@@ -406,8 +429,34 @@
                 "Failed to instantiate extractor.");
         return;
     }
+}
 
-    setMediaExtractor(env,thiz, extractor);
+static void android_media_MediaExtractor_setDataSourceFd(
+        JNIEnv *env, jobject thiz,
+        jobject fileDescObj, jlong offset, jlong length) {
+    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
+
+    if (extractor == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+
+    if (fileDescObj == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+
+    int fd = jniGetFDFromFileDescriptor(env, fileDescObj);
+
+    status_t err = extractor->setDataSource(fd, offset, length);
+
+    if (err != OK) {
+        jniThrowException(
+                env,
+                "java/io/IOException",
+                "Failed to instantiate extractor.");
+        return;
+    }
 }
 
 static void android_media_MediaExtractor_native_finalize(
@@ -443,11 +492,18 @@
 
     { "native_init", "()V", (void *)android_media_MediaExtractor_native_init },
 
-    { "native_setup", "(Ljava/lang/String;)V",
+    { "native_setup", "()V",
       (void *)android_media_MediaExtractor_native_setup },
 
     { "native_finalize", "()V",
       (void *)android_media_MediaExtractor_native_finalize },
+
+    { "setDataSource", "(Ljava/lang/String;[Ljava/lang/String;"
+                       "[Ljava/lang/String;)V",
+      (void *)android_media_MediaExtractor_setDataSource },
+
+    { "setDataSource", "(Ljava/io/FileDescriptor;JJ)V",
+      (void *)android_media_MediaExtractor_setDataSourceFd },
 };
 
 int register_android_media_MediaExtractor(JNIEnv *env) {
diff --git a/media/jni/android_media_MediaExtractor.h b/media/jni/android_media_MediaExtractor.h
index 49a64d6..1aacea2 100644
--- a/media/jni/android_media_MediaExtractor.h
+++ b/media/jni/android_media_MediaExtractor.h
@@ -19,7 +19,9 @@
 
 #include <media/stagefright/foundation/ABase.h>
 #include <utils/Errors.h>
+#include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
+#include <utils/String8.h>
 
 #include "jni.h"
 
@@ -30,7 +32,11 @@
 struct JMediaExtractor : public RefBase {
     JMediaExtractor(JNIEnv *env, jobject thiz);
 
-    status_t setDataSource(const char *path);
+    status_t setDataSource(
+            const char *path,
+            const KeyedVector<String8, String8> *headers);
+
+    status_t setDataSource(int fd, off64_t offset, off64_t size);
 
     size_t countTracks() const;
     status_t getTrackFormat(size_t index, jobject *format) const;
diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp
index 1190448..a4d88ff 100644
--- a/media/jni/android_media_Utils.cpp
+++ b/media/jni/android_media_Utils.cpp
@@ -85,6 +85,16 @@
     return env->NewObject(clazz, integerConstructID, value);
 }
 
+static jobject makeLongObject(JNIEnv *env, int64_t value) {
+    jclass clazz = env->FindClass("java/lang/Long");
+    CHECK(clazz != NULL);
+
+    jmethodID longConstructID = env->GetMethodID(clazz, "<init>", "(J)V");
+    CHECK(longConstructID != NULL);
+
+    return env->NewObject(clazz, longConstructID, value);
+}
+
 static jobject makeFloatObject(JNIEnv *env, float value) {
     jclass clazz = env->FindClass("java/lang/Float");
     CHECK(clazz != NULL);
@@ -158,6 +168,15 @@
                 break;
             }
 
+            case AMessage::kTypeInt64:
+            {
+                int64_t val;
+                CHECK(msg->findInt64(key, &val));
+
+                valueObj = makeLongObject(env, val);
+                break;
+            }
+
             case AMessage::kTypeFloat:
             {
                 float val;
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 2a4d59b..8acbae3 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -1298,7 +1298,9 @@
                             }
 
                             // Update the pause state.
+                            boolean pausing = false;
                             if (mPaused != mRequestPaused) {
+                                pausing = mRequestPaused;
                                 mPaused = mRequestPaused;
                                 sGLThreadManager.notifyAll();
                                 if (LOG_PAUSE_RESUME) {
@@ -1324,12 +1326,16 @@
                                 lostEglContext = false;
                             }
 
-                            // Do we need to release the EGL surface?
-                            if (mHaveEglSurface && mPaused) {
+                            // When pausing, release the EGL surface:
+                            if (pausing && mHaveEglSurface) {
                                 if (LOG_SURFACE) {
                                     Log.i("GLThread", "releasing EGL surface because paused tid=" + getId());
                                 }
                                 stopEglSurfaceLocked();
+                            }
+
+                            // When pausing, optionally release the EGL Context:
+                            if (pausing && mHaveEglContext) {
                                 GLSurfaceView view = mGLSurfaceViewWeakRef.get();
                                 boolean preserveEglContextOnPause = view == null ?
                                         false : view.mPreserveEGLContextOnPause;
@@ -1339,6 +1345,10 @@
                                         Log.i("GLThread", "releasing EGL context because paused tid=" + getId());
                                     }
                                 }
+                            }
+
+                            // When pausing, optionally terminate EGL:
+                            if (pausing) {
                                 if (sGLThreadManager.shouldTerminateEGLWhenPausing()) {
                                     mEglHelper.finish();
                                     if (LOG_SURFACE) {
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 7013862..42eef13 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"ማሳወቂያዎች"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"ብሉቱዝ አያይዝ"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"የግቤት ስልቶችን አዘጋጅ"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"የሚዳሰስ የቁልፍ ሰሌዳ"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"መተግበሪያ <xliff:g id="APPLICATION">%1$s</xliff:g> የUSB መሣሪያን ለመድረስ ይፍቀድ?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"መተግበሪያ <xliff:g id="APPLICATION">%1$s</xliff:g> የUSB ተቀጥላ ላይ እንዲደርስ ፍቀድ?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"የዚህ USB ተቀጥላ ሲያያዝ <xliff:g id="ACTIVITY">%1$s</xliff:g>ይከፈት?"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 201f72c..9d6051e 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"التنبيهات"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"تم إنشاء الاتصال بالإنترنت عن طريق البلوتوث."</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"إعداد أسلوب الإدخال"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"لوحة مفاتيح فعلية"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"هل تريد السماح للتطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> بالدخول إلى جهاز USB؟"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"هل تريد السماح للتطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> بالدخول إلى ملحق USB؟"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"هل تريد فتح <xliff:g id="ACTIVITY">%1$s</xliff:g> عند توصيل جهاز USB هذا؟"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 0ebced0..427abce 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificacions"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth sense fil"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configura els mètodes d\'entrada"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclat físic"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Vols permetre que l\'aplicació <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi al dispositiu USB?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Vols permetre que l\'aplicació <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi a l\'accessori USB?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Vols que s\'obri <xliff:g id="ACTIVITY">%1$s</xliff:g> quan aquest dispositiu USB estigui connectat?"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 39d5c33..e3d82b1 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Benachrichtigungen"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth-Tethering aktiv"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Eingabemethoden einrichten"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Physische Tastatur"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"App <xliff:g id="APPLICATION">%1$s</xliff:g> Zugriff auf USB-Gerät gewähren?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"App <xliff:g id="APPLICATION">%1$s</xliff:g> Zugriff auf USB-Zubehör gewähren?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"<xliff:g id="ACTIVITY">%1$s</xliff:g> öffnen, wenn dieses USB-Gerät verbunden ist?"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 48158db..5511b1a 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Ειδοποιήσεις"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Έγινε σύνδεση μέσω Bluetooth"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Ρύθμιση μεθόδων εισαγωγής"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Φυσικό πληκτρολόγιο"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Να επιτρέπεται στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> η πρόσβαση στη συσκευή USB;"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Να επιτρέπεται στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> η πρόσβαση στο αξεσουάρ USB;"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Άνοιγμα του <xliff:g id="ACTIVITY">%1$s</xliff:g> κατά τη σύνδεση αυτής της συσκευής USB;"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 4db7130..96c8c23 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificaciones"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth anclado"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos de intro."</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclado físico"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"¿Deseas que la aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> acceda al dispositivo USB?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"¿Deseas que la aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> acceda al accesorio USB?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"¿Abrir <xliff:g id="ACTIVITY">%1$s</xliff:g> cuando este dispositivo USB esté conectado?"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index f7f73d7..0b3e4e4 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificaciones"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth anclado"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos de introducción"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclado físico"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"¿Permitir que la aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> acceda al dispositivo USB?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"¿Permitir que la aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> acceda al accesorio USB?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"¿Quieres abrir <xliff:g id="ACTIVITY">%1$s</xliff:g> al conectar este dispositivo USB?"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 569e929..df25d5e 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"اعلان ها"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"اتصال اینترنتی با بلوتوث تلفن همراه"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"تنظیم روش‌های ورودی"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"صفحه کلید فیزیکی"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"به برنامه <xliff:g id="APPLICATION">%1$s</xliff:g> اجازه می دهید به دستگاه USB دسترسی داشته باشد؟"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"به برنامه <xliff:g id="APPLICATION">%1$s</xliff:g> اجازه میدهد تا به وسیله جانبی USB دسترسی داشته باشد؟"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"وقتی این دستگاه USB وصل است، <xliff:g id="ACTIVITY">%1$s</xliff:g> باز شود؟"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 93e6b62..370d234 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Ilmoitukset"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth yhdistetty"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Määritä syöttötavat"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fyysinen näppäimistö"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Annetaanko sovellukselle <xliff:g id="APPLICATION">%1$s</xliff:g> lupa käyttää USB-laitetta?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Annetaanko sovellukselle <xliff:g id="APPLICATION">%1$s</xliff:g> lupa käyttää USB-lisälaitetta?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Avataanko <xliff:g id="ACTIVITY">%1$s</xliff:g> tämän USB-laitteen ollessa kytkettynä?"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 741f1b4..9805f90 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"सूचनाएं"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth टीदर किया गया"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"इनपुट पद्धति सेट करें"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"भौतिक कीबोर्ड"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"एप्लिकेशन <xliff:g id="APPLICATION">%1$s</xliff:g> को USB उपकरण तक पहुंचने दें?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"एप्लिकेशन <xliff:g id="APPLICATION">%1$s</xliff:g> को USB सहायक उपकरण तक पहुंचने दें?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"जब यह USB उपकरण कनेक्ट किया जाए, तब <xliff:g id="ACTIVITY">%1$s</xliff:g> को खोलें?"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 1c28b57..87a9d45 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Értesítések"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth megosztva"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Beviteli módok beállítása"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fizikai billentyűzet"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"A(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazás hozzáférhet az USB-eszközhöz?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"A(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazás hozzáférhet az USB-kiegészítőhöz?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"<xliff:g id="ACTIVITY">%1$s</xliff:g> megnyitása, ha USB-kiegészítő csatlakoztatva van?"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index bc5e873..03fba7e 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"התראות"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth קשור"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"הגדר שיטות קלט"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"מקלדת פיזית"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"לאפשר ליישום <xliff:g id="APPLICATION">%1$s</xliff:g> גישה להתקן ה-USB?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"לאפשר ליישום <xliff:g id="APPLICATION">%1$s</xliff:g> גישה לאביזר ה-USB?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"האם לפתוח את <xliff:g id="ACTIVITY">%1$s</xliff:g> כאשר מכשיר USB זה מחובר?"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 01d76eb..4818ca9 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"通知"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetoothテザリング接続"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"入力方法をセットアップ"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"物理キーボード"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"アプリ「<xliff:g id="APPLICATION">%1$s</xliff:g>」にUSBデバイスへのアクセスを許可しますか?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"アプリ「<xliff:g id="APPLICATION">%1$s</xliff:g>」にUSBアクセサリへのアクセスを許可しますか?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"このUSBデバイスが接続されたときに<xliff:g id="ACTIVITY">%1$s</xliff:g>を開きますか?"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 88194df..3321912 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"알림"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"블루투스 테더링됨"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"입력 방법 설정"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"물리적 키보드"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱이 USB 기기에 액세스하도록 허용하시겠습니까?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱이 USB 액세서리에 액세스하도록 허용하시겠습니까?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"USB 기기가 연결될 때 <xliff:g id="ACTIVITY">%1$s</xliff:g>(을)를 여시겠습니까?"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 942e159..831fa41 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Pranešimai"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"„Bluetooth“ susieta"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Nustatyti įvesties metodus"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fizinė klaviatūra"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Leisti programai „<xliff:g id="APPLICATION">%1$s</xliff:g>“ pasiekti USB įrenginį?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Leisti programai „<xliff:g id="APPLICATION">%1$s</xliff:g>“ pasiekti USB priedą?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Atidaryti <xliff:g id="ACTIVITY">%1$s</xliff:g>, kai prijungtas šis USB įrenginys?"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index b5c9130..158c850 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Paziņojumi"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth piesaiste"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Iestatīt ievades metodes"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fiziskā tastatūra"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Vai ļaut lietotnei <xliff:g id="APPLICATION">%1$s</xliff:g> piekļūt šai USB ierīcei?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Vai ļaut lietotnei <xliff:g id="APPLICATION">%1$s</xliff:g> piekļūt šim USB piederumam?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Vai atvērt darbību <xliff:g id="ACTIVITY">%1$s</xliff:g>, kad tiek pievienota šī USB ierīce?"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index f08013d..899a204 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Pemberitahuan"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth ditambatkan"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Sediakan kaedah input"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Papan kekunci fizikal"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Benarkan aplikasi <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses peranti USB?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Benarkan aplikasi <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses aksesori USB?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Buka <xliff:g id="ACTIVITY">%1$s</xliff:g> apabila peranti USB ini disambungkan?"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 5314ba3..e05e2c9 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Meldingen"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth getetherd"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Invoermethoden instellen"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fysiek toetsenbord"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"De app <xliff:g id="APPLICATION">%1$s</xliff:g> toegang geven tot het USB-apparaat?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"De app <xliff:g id="APPLICATION">%1$s</xliff:g> toegang geven tot het USB-accessoire?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"<xliff:g id="ACTIVITY">%1$s</xliff:g> openen wanneer dit USB-apparaat wordt aangesloten?"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 26e3989..0618eb5 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Powiadomienia"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth – podłączono"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfiguruj metody wprowadzania"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Klawiatura fizyczna"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na dostęp do urządzenia USB?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na dostęp do urządzenia USB?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Czy otworzyć <xliff:g id="ACTIVITY">%1$s</xliff:g> po podłączeniu tego urządzenia USB?"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index a5999e3..6a278ba 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificações"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth ligado"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos introdução"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclado físico"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Permitir que a aplicação <xliff:g id="APPLICATION">%1$s</xliff:g> aceda ao dispositivo USB?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Permitir que a aplicação <xliff:g id="APPLICATION">%1$s</xliff:g> aceda ao acessório USB?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Abrir <xliff:g id="ACTIVITY">%1$s</xliff:g> quando este dispositivo USB estiver ligado?"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 02bef77..23a2ba5 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificações"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth vinculado"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos de entrada"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclado físico"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Permitir que o aplicativo <xliff:g id="APPLICATION">%1$s</xliff:g> acesse o dispositivo USB?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Permitir que o aplicativo <xliff:g id="APPLICATION">%1$s</xliff:g> acesse o acessório USB?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Abrir <xliff:g id="ACTIVITY">%1$s</xliff:g> quando este dispositivo USB estiver conectado?"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 4057599..3753309 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Уведомления"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Общий модем доступен через Bluetooth"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Настройка способов ввода"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Физическая клавиатура"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Открыть приложению \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ к USB-устройству?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Открыть приложению \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ к USB-устройству?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Запускать <xliff:g id="ACTIVITY">%1$s</xliff:g> при подключении этого USB-устройства?"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 67368ac..599f99c 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Upozornenia"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Zdieľané dátové pripojenie cez Bluetooth"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Nastavenie metód vstupu"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fyzická klávesnica"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Povoliť aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g> prístup k zariadeniu USB?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Povoliť aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g> prístup k periférnemu zariadeniu USB?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Chcete pri pripojení tohto zariadenia USB otvoriť aplikáciu <xliff:g id="ACTIVITY">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 77aef3d..fb229e2 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Obvestila"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Internetna povezava prek Bluetootha"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Nastavi načine vnosa"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fizična tipkovnica"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Želite programu <xliff:g id="APPLICATION">%1$s</xliff:g> dovoliti dostop do naprave USB?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Želite dovoliti programu <xliff:g id="APPLICATION">%1$s</xliff:g> dostop do dodatka USB?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Želite, da se odpre <xliff:g id="ACTIVITY">%1$s</xliff:g>, ko priključite to napravo USB?"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index ba4edea..8eaa126 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Aviseringar"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Internetdelning via Bluetooth"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfigurera inmatningsmetoder"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fysiskt tangentbord"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Vill du tillåta att appen <xliff:g id="APPLICATION">%1$s</xliff:g> använder USB-enheten?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Vill du tillåta att appen <xliff:g id="APPLICATION">%1$s</xliff:g> använder USB-tillbehöret?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Vill du öppna <xliff:g id="ACTIVITY">%1$s</xliff:g> när den här USB-enheten ansluts?"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 8a6b050..19bd4ab 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -46,8 +46,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Arifa"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth imefungwa"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Weka mbinu za ingizo"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Kibodi halisi"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Ruhusu programu <xliff:g id="APPLICATION">%1$s</xliff:g> kufikia kifaa cha USB?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Ruhusu programu <xliff:g id="APPLICATION">%1$s</xliff:g> kufikia kifaa cha ziada cha USB?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Je, ungetaka kufungua  <xliff:g id="ACTIVITY">%1$s</xliff:g>wakati kifaa cha USB kimeunganishwa?"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 55ecfae..2054121e 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Mga Notification"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Na-tether ang bluetooth"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"I-set up paraan ng pag-input"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Aktwal na keyboard"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Payagan ang app na <xliff:g id="APPLICATION">%1$s</xliff:g> na i-access ang USB device?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Payagan ang app na <xliff:g id="APPLICATION">%1$s</xliff:g> na i-access ang USB accessory?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Buksan ang <xliff:g id="ACTIVITY">%1$s</xliff:g> kapag nakakonekta ang USB device na ito?"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index f0aa516..ca422f7 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Bildirimler"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth paylaşımı tamam"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Giriş yöntemlerini ayarla"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fiziksel klavye"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının USB cihazına erişmesine izin verilsin mi?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının USB aksesuarına erişmesine izin verilsin mi?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Bu USB cihaz bağlandığında <xliff:g id="ACTIVITY">%1$s</xliff:g> açılsın mı?"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index abd024a..05ab87c 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Thông báo"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth được dùng làm điểm truy cập Internet"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Thiết lập phương thức nhập"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Bàn phím thực"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Cho phép ứng dụng <xliff:g id="APPLICATION">%1$s</xliff:g> truy cập thiết bị USB?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Cho phép ứng dụng <xliff:g id="APPLICATION">%1$s</xliff:g> truy cập phụ kiện USB?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Mở <xliff:g id="ACTIVITY">%1$s</xliff:g> khi thiết bị USB này được kết nối?"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index ec92713c..c862d74 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"通知"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"已通过蓝牙共享网络"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"设置输入法"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"物理键盘"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"允许应用“<xliff:g id="APPLICATION">%1$s</xliff:g>”访问该 USB 设备吗?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"允许应用“<xliff:g id="APPLICATION">%1$s</xliff:g>”访问该 USB 配件吗?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"要在连接此 USB 设备时打开<xliff:g id="ACTIVITY">%1$s</xliff:g>吗?"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 27dd8fd..91f6566 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -48,8 +48,7 @@
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Izaziso"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Ukusebenzisa i-Bluetooth njengemodemu"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Izilungiselelo zezindlela zokufakwayo"</string>
-    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
-    <skip />
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Ukwakheka kwekhibhodi"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Vumela insiza <xliff:g id="APPLICATION">%1$s</xliff:g> ukuthi ufinyelele ezintweni eziphuma ne-USB?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Vumela insiza <xliff:g id="APPLICATION">%1$s</xliff:g> ukuthi ufinyelele ezintweni eziphuma ne-USB?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Vula <xliff:g id="ACTIVITY">%1$s</xliff:g> uma ledivayisi ye-USB ixhunyiwe?"</string>
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 352decf..359074a 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -875,6 +875,19 @@
         return null;
     }
 
+    @Override
+    public boolean isActiveNetworkMetered() {
+        enforceAccessPermission();
+        final NetworkState state = getNetworkStateUnchecked(mActiveDefaultNetwork);
+        if (state != null) {
+            try {
+                return mPolicyManager.isNetworkMetered(state);
+            } catch (RemoteException e) {
+            }
+        }
+        return false;
+    }
+
     public boolean setRadios(boolean turnOn) {
         boolean result = true;
         enforceChangePermission();
diff --git a/services/java/com/android/server/NsdService.java b/services/java/com/android/server/NsdService.java
index a3ac8d0..8014e27 100644
--- a/services/java/com/android/server/NsdService.java
+++ b/services/java/com/android/server/NsdService.java
@@ -167,6 +167,18 @@
                                 NsdManager.ERROR);
                     }
                     break;
+                case NsdManager.UNREGISTER_SERVICE:
+                    if (DBG) Slog.d(TAG, "unregister service");
+                    clientInfo = mClients.get(msg.replyTo);
+                    int regId = msg.arg1;
+                    if (clientInfo.mRegisteredIds.remove(new Integer(regId)) &&
+                            unregisterService(regId)) {
+                        mReplyChannel.replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_SUCCEEDED);
+                    } else {
+                        mReplyChannel.replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED,
+                                NsdManager.ERROR);
+                    }
+                    break;
                 case NsdManager.UPDATE_SERVICE:
                     if (DBG) Slog.d(TAG, "Update service");
                     //TODO: implement
@@ -237,6 +249,8 @@
     }
 
     public Messenger getMessenger() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET,
+            "NsdService");
         return new Messenger(mAsyncServiceHandler);
     }
 
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 2d2a881..9a371c6 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -37,6 +37,7 @@
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
+import android.hardware.SystemSensorManager;
 import android.os.BatteryManager;
 import android.os.BatteryStats;
 import android.os.Binder;
@@ -2946,7 +2947,7 @@
     }
 
     void systemReady() {
-        mSensorManager = new SensorManager(mHandlerThread.getLooper());
+        mSensorManager = new SystemSensorManager(mHandlerThread.getLooper());
         mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
         // don't bother with the light sensor if auto brightness is handled in hardware
         if (mUseSoftwareAutoBrightness) {
diff --git a/services/java/com/android/server/RecognitionManagerService.java b/services/java/com/android/server/RecognitionManagerService.java
index 8e55512..85224d8 100644
--- a/services/java/com/android/server/RecognitionManagerService.java
+++ b/services/java/com/android/server/RecognitionManagerService.java
@@ -75,7 +75,10 @@
             try {
                 mContext.getPackageManager().getServiceInfo(comp, 0);
             } catch (NameNotFoundException e) {
-                setCurRecognizer(null);
+                comp = findAvailRecognizer(null);
+                if (comp != null) {
+                    setCurRecognizer(comp);
+                }
             }
         } else {
             comp = findAvailRecognizer(null);
diff --git a/services/java/com/android/server/VibratorService.java b/services/java/com/android/server/VibratorService.java
index 7561b0b..6282c31 100755
--- a/services/java/com/android/server/VibratorService.java
+++ b/services/java/com/android/server/VibratorService.java
@@ -144,10 +144,10 @@
                 new ContentObserver(mH) {
                     @Override
                     public void onChange(boolean selfChange) {
-                        updateVibrateInputDevicesSetting();
+                        updateInputDeviceVibrators();
                     }
                 });
-        updateVibrateInputDevicesSetting();
+        updateInputDeviceVibrators();
     }
 
     public boolean hasVibrator() {
@@ -334,36 +334,30 @@
         }
     }
 
-    private void updateVibrateInputDevicesSetting() {
-        synchronized (mInputDeviceVibrators) {
-            mVibrateInputDevicesSetting = false;
-            try {
-                mVibrateInputDevicesSetting = Settings.System.getInt(mContext.getContentResolver(),
-                        Settings.System.VIBRATE_INPUT_DEVICES) > 0;
-            } catch (SettingNotFoundException snfe) {
-            }
-
-            if (mVibrateInputDevicesSetting) {
-                if (!mInputDeviceListenerRegistered) {
-                    mInputDeviceListenerRegistered = true;
-                    mIm.registerInputDeviceListener(this, mH);
-                }
-            } else {
-                if (mInputDeviceListenerRegistered) {
-                    mInputDeviceListenerRegistered = false;
-                    mIm.unregisterInputDeviceListener(this);
-                }
-            }
-
-            updateInputDeviceVibrators();
-        }
-    }
-
     private void updateInputDeviceVibrators() {
         synchronized (mVibrations) {
             doCancelVibrateLocked();
 
             synchronized (mInputDeviceVibrators) {
+                mVibrateInputDevicesSetting = false;
+                try {
+                    mVibrateInputDevicesSetting = Settings.System.getInt(mContext.getContentResolver(),
+                            Settings.System.VIBRATE_INPUT_DEVICES) > 0;
+                } catch (SettingNotFoundException snfe) {
+                }
+
+                if (mVibrateInputDevicesSetting) {
+                    if (!mInputDeviceListenerRegistered) {
+                        mInputDeviceListenerRegistered = true;
+                        mIm.registerInputDeviceListener(this, mH);
+                    }
+                } else {
+                    if (mInputDeviceListenerRegistered) {
+                        mInputDeviceListenerRegistered = false;
+                        mIm.unregisterInputDeviceListener(this);
+                    }
+                }
+
                 mInputDeviceVibrators.clear();
                 if (mVibrateInputDevicesSetting) {
                     int[] ids = mIm.getInputDeviceIds();
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index e2a2c83..bb38cd9 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -1202,6 +1202,8 @@
         pw.println();
         pw.println("WifiWatchdogStateMachine dump");
         mWifiWatchdogStateMachine.dump(pw);
+        pw.println("WifiStateMachine dump");
+        mWifiStateMachine.dump(fd, pw, args);
     }
 
     private class WifiLock extends DeathRecipient {
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 754a4dd..ed2a6c0 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1004,14 +1004,16 @@
             mNotificationTimeout = info.notificationTimeout;
             mIsDefault = (info.flags & DEFAULT) != 0;
 
-            final int targetSdkVersion =
-                info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion;
-            // TODO: Uncomment this line and remove the line below when JellyBean
-            // SDK version is finalized.
-            // if (targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN) {
-            if (targetSdkVersion > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
-                mIncludeNotImportantViews =
-                    (info.flags & INCLUDE_NOT_IMPORTANT_VIEWS) != 0;
+            if (!mIsAutomation) {
+                final int targetSdkVersion =
+                    info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion;
+                // TODO: Uncomment this line and remove the line below when JellyBean
+                // SDK version is finalized.
+                // if (targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN) {
+                if (targetSdkVersion > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
+                    mIncludeNotImportantViews =
+                        (info.flags & INCLUDE_NOT_IMPORTANT_VIEWS) != 0;
+                }
             }
 
             synchronized (mLock) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index e37adc7..77bec41 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1808,16 +1808,18 @@
 
     final ProcessRecord getProcessRecordLocked(
             String processName, int uid) {
-        // Temporary hack to make Settings run per user
-        if (uid == Process.SYSTEM_UID && !processName.equals("com.android.settings")) {
+        if (uid == Process.SYSTEM_UID) {
             // The system gets to run in any process.  If there are multiple
             // processes with the same uid, just pick the first (this
             // should never happen).
             SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
                     processName);
-            return procs != null ? procs.valueAt(0) : null;
+            if (procs == null) return null;
+            final int N = procs.size();
+            for (int i = 0; i < N; i++) {
+                if (UserId.isSameUser(procs.keyAt(i), uid)) return procs.valueAt(i);
+            }
         }
-        // uid = applyUserId(uid);
         ProcessRecord proc = mProcessNames.get(processName, uid);
         return proc;
     }
@@ -6183,7 +6185,9 @@
                 if (cpi == null) {
                     return null;
                 }
-
+                if (isSingleton(cpi.processName, cpi.applicationInfo)) {
+                    userId = 0;
+                }
                 cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo, userId);
 
                 String msg;
@@ -10923,6 +10927,9 @@
                     return null;
                 }
                 if (userId > 0) {
+                    if (isSingleton(sInfo.processName, sInfo.applicationInfo)) {
+                        userId = 0;
+                    }
                     sInfo.applicationInfo = getAppInfoForUser(sInfo.applicationInfo, userId);
                 }
                 ComponentName name = new ComponentName(
@@ -11740,7 +11747,22 @@
             }
         }
     }
-    
+
+    boolean isSingleton(String componentProcessName, ApplicationInfo aInfo) {
+        boolean result = false;
+        if (UserId.getAppId(aInfo.uid) >= Process.FIRST_APPLICATION_UID) {
+            result = false;
+        } else if (componentProcessName == aInfo.packageName) {
+            result = (aInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0;
+        } else if ("system".equals(componentProcessName)) {
+            result = true;
+        }
+        if (DEBUG_MU) {
+            Slog.v(TAG, "isSingleton(" + componentProcessName + ", " + aInfo + ") = " + result);
+        }
+        return result;
+    }
+
     public int bindService(IApplicationThread caller, IBinder token,
             Intent service, String resolvedType,
             IServiceConnection connection, int flags, int userId) {
@@ -11808,6 +11830,11 @@
             if (res.record == null) {
                 return -1;
             }
+            if (isSingleton(res.record.processName, res.record.appInfo)) {
+                userId = 0;
+                res = retrieveServiceLocked(service, resolvedType, Binder.getCallingPid(),
+                        Binder.getCallingUid(), 0);
+            }
             ServiceRecord s = res.record;
 
             final long origId = Binder.clearCallingIdentity();
@@ -12740,7 +12767,11 @@
                 if (ai != null) {
                     receivers = new ArrayList();
                     ResolveInfo ri = new ResolveInfo();
-                    ri.activityInfo = getActivityInfoForUser(ai, userId);
+                    if (isSingleton(ai.processName, ai.applicationInfo)) {
+                        ri.activityInfo = getActivityInfoForUser(ai, 0);
+                    } else {
+                        ri.activityInfo = getActivityInfoForUser(ai, userId);
+                    }
                     receivers.add(ri);
                 }
             } else {
@@ -14894,16 +14925,14 @@
         if (info == null) return null;
         ApplicationInfo newInfo = new ApplicationInfo(info);
         newInfo.uid = applyUserId(info.uid, userId);
-        if (newInfo.uid >= Process.FIRST_APPLICATION_UID) {
-            newInfo.dataDir = USER_DATA_DIR + userId + "/"
-                    + info.packageName;
-        }
+        newInfo.dataDir = USER_DATA_DIR + userId + "/"
+                + info.packageName;
         return newInfo;
     }
 
     ActivityInfo getActivityInfoForUser(ActivityInfo aInfo, int userId) {
-        if (aInfo == null || aInfo.applicationInfo.uid < Process.FIRST_APPLICATION_UID
-                || userId < 1) {
+        if (aInfo == null
+                || (userId < 1 && aInfo.applicationInfo.uid < UserId.PER_USER_RANGE)) {
             return aInfo;
         }
 
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index a098f18..cce8e7a 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -558,6 +558,11 @@
                             pendingOptions.getCustomEnterResId(),
                             pendingOptions.getCustomExitResId());
                     break;
+                case ActivityOptions.ANIM_SCALE_UP:
+                    service.mWindowManager.overridePendingAppTransitionScaleUp(
+                            pendingOptions.getStartX(), pendingOptions.getStartY(),
+                            pendingOptions.getStartWidth(), pendingOptions.getStartHeight());
+                    break;
                 case ActivityOptions.ANIM_THUMBNAIL:
                     service.mWindowManager.overridePendingAppTransitionThumb(
                             pendingOptions.getThumbnail(),
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 6596e1f..2c53186 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -2345,8 +2345,9 @@
         }
 
         if (err == ActivityManager.START_SUCCESS) {
+            final int userId = aInfo != null ? UserId.getUserId(aInfo.applicationInfo.uid) : 0;
             Slog.i(TAG, "START {" + intent.toShortString(true, true, true, false)
-                    + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
+                    + " u=" + userId + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
         }
 
         ActivityRecord sourceRecord = null;
@@ -2943,6 +2944,9 @@
         // Collect information about the target of the Intent.
         ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
                 profileFile, profileFd, userId);
+        if (mService.isSingleton(aInfo.processName, aInfo.applicationInfo)) {
+            userId = 0;
+        }
         aInfo = mService.getActivityInfoForUser(aInfo, userId);
 
         synchronized (mService) {
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
index 1b83e0b..47b8c0a 100644
--- a/services/java/com/android/server/am/BroadcastQueue.java
+++ b/services/java/com/android/server/am/BroadcastQueue.java
@@ -719,8 +719,10 @@
                     info.activityInfo.applicationInfo.packageName,
                     info.activityInfo.name);
             if (r.callingUid != Process.SYSTEM_UID) {
-                info.activityInfo = mService.getActivityInfoForUser(info.activityInfo, UserId
-                        .getUserId(r.callingUid));
+                boolean isSingleton = mService.isSingleton(info.activityInfo.processName,
+                        info.activityInfo.applicationInfo);
+                int targetUserId = isSingleton ? 0 : UserId.getUserId(r.callingUid);
+                info.activityInfo = mService.getActivityInfoForUser(info.activityInfo,targetUserId);
             }
             r.curReceiver = info.activityInfo;
             if (DEBUG_MU && r.callingUid > UserId.PER_USER_RANGE) {
diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java
index e819432..7640eff 100644
--- a/services/java/com/android/server/input/InputManagerService.java
+++ b/services/java/com/android/server/input/InputManagerService.java
@@ -16,11 +16,16 @@
 
 package com.android.server.input;
 
+import com.android.internal.os.AtomicFile;
+import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
 import com.android.server.Watchdog;
 
 import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
 
+import android.Manifest;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -63,15 +68,23 @@
 import android.view.WindowManagerPolicy;
 import android.view.KeyCharacterMap.UnavailableException;
 
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+
+import libcore.io.IoUtils;
+import libcore.util.Objects;
 
 /*
  * Wraps the C++ InputManager and provides its callbacks.
@@ -91,9 +104,8 @@
     private final Callbacks mCallbacks;
     private final InputManagerHandler mHandler;
 
-    // Used to simulate a persistent data store for keyboard layouts.
-    // TODO: Replace with the real thing.
-    private final HashMap<String, String> mFakeRegistry = new HashMap<String, String>();
+    // Persistent data store.  Must be locked each time during use.
+    private final PersistentDataStore mDataStore = new PersistentDataStore();
 
     // List of currently registered input devices changed listeners by process id.
     private Object mInputDevicesLock = new Object();
@@ -635,7 +647,9 @@
             throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
         }
 
-        return mFakeRegistry.get(inputDeviceDescriptor);
+        synchronized (mDataStore) {
+            return mDataStore.getKeyboardLayout(inputDeviceDescriptor);
+        }
     }
 
     @Override // Binder call
@@ -650,7 +664,13 @@
             throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
         }
 
-        mFakeRegistry.put(inputDeviceDescriptor, keyboardLayoutDescriptor);
+        synchronized (mDataStore) {
+            try {
+                mDataStore.setKeyboardLayout(inputDeviceDescriptor, keyboardLayoutDescriptor);
+            } finally {
+                mDataStore.saveIfNeeded();
+            }
+        }
     }
 
     /**
@@ -862,7 +882,7 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
+        if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
                 != PackageManager.PERMISSION_GRANTED) {
             pw.println("Permission Denial: can't dump InputManager from from pid="
                     + Binder.getCallingPid()
@@ -1198,4 +1218,186 @@
             onVibratorTokenDied(this);
         }
     }
+
+    /**
+     * Manages persistent state recorded by the input manager service as an XML file.
+     * Caller must acquire lock on the data store before accessing it.
+     *
+     * File format:
+     * <code>
+     * &lt;input-mananger-state>
+     *   &lt;input-devices>
+     *     &lt;input-device descriptor="xxxxx" keyboard-layout="yyyyy" />
+     *   &gt;input-devices>
+     * &gt;/input-manager-state>
+     * </code>
+     */
+    private static final class PersistentDataStore {
+        // Input device state by descriptor.
+        private final HashMap<String, InputDeviceState> mInputDevices =
+                new HashMap<String, InputDeviceState>();
+        private final AtomicFile mAtomicFile;
+
+        // True if the data has been loaded.
+        private boolean mLoaded;
+
+        // True if there are changes to be saved.
+        private boolean mDirty;
+
+        public PersistentDataStore() {
+            mAtomicFile = new AtomicFile(new File("/data/system/input-manager-state.xml"));
+        }
+
+        public void saveIfNeeded() {
+            if (mDirty) {
+                save();
+                mDirty = false;
+            }
+        }
+
+        public String getKeyboardLayout(String inputDeviceDescriptor) {
+            InputDeviceState state = getInputDeviceState(inputDeviceDescriptor, false);
+            return state != null ? state.keyboardLayoutDescriptor : null;
+        }
+
+        public boolean setKeyboardLayout(String inputDeviceDescriptor,
+                String keyboardLayoutDescriptor) {
+            InputDeviceState state = getInputDeviceState(inputDeviceDescriptor, true);
+            if (!Objects.equal(state.keyboardLayoutDescriptor, keyboardLayoutDescriptor)) {
+                state.keyboardLayoutDescriptor = keyboardLayoutDescriptor;
+                setDirty();
+                return true;
+            }
+            return false;
+        }
+
+        private InputDeviceState getInputDeviceState(String inputDeviceDescriptor,
+                boolean createIfAbsent) {
+            loadIfNeeded();
+            InputDeviceState state = mInputDevices.get(inputDeviceDescriptor);
+            if (state == null && createIfAbsent) {
+                state = new InputDeviceState();
+                mInputDevices.put(inputDeviceDescriptor, state);
+                setDirty();
+            }
+            return state;
+        }
+
+        private void loadIfNeeded() {
+            if (!mLoaded) {
+                load();
+                mLoaded = true;
+            }
+        }
+
+        private void setDirty() {
+            mDirty = true;
+        }
+
+        private void clearState() {
+            mInputDevices.clear();
+        }
+
+        private void load() {
+            clearState();
+
+            final InputStream is;
+            try {
+                is = mAtomicFile.openRead();
+            } catch (FileNotFoundException ex) {
+                return;
+            }
+
+            XmlPullParser parser;
+            try {
+                parser = Xml.newPullParser();
+                parser.setInput(new BufferedInputStream(is), null);
+                loadFromXml(parser);
+            } catch (IOException ex) {
+                Slog.w(TAG, "Failed to load input manager persistent store data.", ex);
+                clearState();
+            } catch (XmlPullParserException ex) {
+                Slog.w(TAG, "Failed to load input manager persistent store data.", ex);
+                clearState();
+            } finally {
+                IoUtils.closeQuietly(is);
+            }
+        }
+
+        private void save() {
+            final FileOutputStream os;
+            try {
+                os = mAtomicFile.startWrite();
+                boolean success = false;
+                try {
+                    XmlSerializer serializer = new FastXmlSerializer();
+                    serializer.setOutput(new BufferedOutputStream(os), "utf-8");
+                    saveToXml(serializer);
+                    serializer.flush();
+                    success = true;
+                } finally {
+                    if (success) {
+                        mAtomicFile.finishWrite(os);
+                    } else {
+                        mAtomicFile.failWrite(os);
+                    }
+                }
+            } catch (IOException ex) {
+                Slog.w(TAG, "Failed to save input manager persistent store data.", ex);
+            }
+        }
+
+        private void loadFromXml(XmlPullParser parser)
+                throws IOException, XmlPullParserException {
+            XmlUtils.beginDocument(parser, "input-manager-state");
+            final int outerDepth = parser.getDepth();
+            while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+                if (parser.getName().equals("input-devices")) {
+                    loadInputDevicesFromXml(parser);
+                }
+            }
+        }
+
+        private void loadInputDevicesFromXml(XmlPullParser parser)
+                throws IOException, XmlPullParserException {
+            final int outerDepth = parser.getDepth();
+            while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+                if (parser.getName().equals("input-device")) {
+                    String descriptor = parser.getAttributeValue(null, "descriptor");
+                    if (descriptor == null) {
+                        throw new XmlPullParserException(
+                                "Missing descriptor attribute on input-device");
+                    }
+                    InputDeviceState state = new InputDeviceState();
+                    state.keyboardLayoutDescriptor =
+                            parser.getAttributeValue(null, "keyboard-layout");
+                    mInputDevices.put(descriptor, state);
+                }
+            }
+        }
+
+        private void saveToXml(XmlSerializer serializer) throws IOException {
+            serializer.startDocument(null, true);
+            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+            serializer.startTag(null, "input-manager-state");
+            serializer.startTag(null, "input-devices");
+            for (Map.Entry<String, InputDeviceState> entry : mInputDevices.entrySet()) {
+                final String descriptor = entry.getKey();
+                final InputDeviceState state = entry.getValue();
+                serializer.startTag(null, "input-device");
+                serializer.attribute(null, "descriptor", descriptor);
+                if (state.keyboardLayoutDescriptor != null) {
+                    serializer.attribute(null, "keyboard-layout", state.keyboardLayoutDescriptor);
+                }
+                serializer.endTag(null, "input-device");
+            }
+            serializer.endTag(null, "input-devices");
+            serializer.endTag(null, "input-manager-state");
+            serializer.endDocument();
+        }
+    }
+
+    private static final class InputDeviceState {
+        public String keyboardLayoutDescriptor;
+    }
 }
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 5408c42..1e17067 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -1391,6 +1391,22 @@
     }
 
     @Override
+    public boolean isNetworkMetered(NetworkState state) {
+        final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
+
+        final NetworkPolicy policy;
+        synchronized (mRulesLock) {
+            policy = findPolicyForNetworkLocked(ident);
+        }
+
+        if (policy != null) {
+            return policy.metered;
+        } else {
+            return false;
+        }
+    }
+
+    @Override
     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         mContext.enforceCallingOrSelfPermission(DUMP, TAG);
 
@@ -1814,11 +1830,6 @@
         mHandler.getLooper().getQueue().addIdleHandler(handler);
     }
 
-    public static boolean isAirplaneModeOn(Context context) {
-        return Settings.System.getInt(
-                context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) != 0;
-    }
-
     private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
         final int size = source.size();
         for (int i = 0; i < size; i++) {
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 4382a03..2a67e02 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -26,6 +26,7 @@
 import static android.content.Intent.EXTRA_UID;
 import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
+import static android.net.ConnectivityManager.isNetworkTypeMobile;
 import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
 import static android.net.NetworkStats.IFACE_ALL;
 import static android.net.NetworkStats.SET_ALL;
@@ -33,7 +34,7 @@
 import static android.net.NetworkStats.SET_FOREGROUND;
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
-import static android.net.NetworkTemplate.buildTemplateMobileAll;
+import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
 import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
 import static android.net.TrafficStats.MB_IN_BYTES;
 import static android.provider.Settings.Secure.NETSTATS_DEV_BUCKET_DURATION;
@@ -54,6 +55,8 @@
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
+import static com.android.internal.util.ArrayUtils.appendElement;
+import static com.android.internal.util.ArrayUtils.contains;
 import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
 import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
@@ -194,6 +197,8 @@
     private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap();
     /** Current default active iface. */
     private String mActiveIface;
+    /** Set of any ifaces associated with mobile networks since boot. */
+    private String[] mMobileIfaces = new String[0];
 
     private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
             new DropBoxNonMonotonicObserver();
@@ -517,6 +522,11 @@
     }
 
     @Override
+    public String[] getMobileIfaces() {
+        return mMobileIfaces;
+    }
+
+    @Override
     public void incrementOperationCount(int uid, int tag, int operationCount) {
         if (Binder.getCallingUid() != uid) {
             mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
@@ -735,6 +745,13 @@
                 }
 
                 ident.add(NetworkIdentity.buildNetworkIdentity(mContext, state));
+
+                // remember any ifaces associated with mobile networks
+                if (isNetworkTypeMobile(state.networkInfo.getType())) {
+                    if (!contains(mMobileIfaces, iface)) {
+                        mMobileIfaces = appendElement(String.class, mMobileIfaces, iface);
+                    }
+                }
             }
         }
     }
@@ -861,7 +878,7 @@
         NetworkStats.Entry uidTotal;
 
         // collect mobile sample
-        template = buildTemplateMobileAll(getActiveSubscriberId(mContext));
+        template = buildTemplateMobileWildcard();
         devTotal = mDevRecorder.getTotalSinceBootLocked(template);
         xtTotal = new NetworkStats.Entry();
         uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
@@ -1022,12 +1039,6 @@
         }
     };
 
-    private static String getActiveSubscriberId(Context context) {
-        final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
-                Context.TELEPHONY_SERVICE);
-        return telephony.getSubscriberId();
-    }
-
     private boolean isBandwidthControlEnabled() {
         try {
             return mNetworkManager.isBandwidthControlEnabled();
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index b8fca61..72aab7b 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -50,6 +50,7 @@
 
 import android.Manifest;
 import android.app.ActivityManagerNative;
+import android.app.ActivityOptions;
 import android.app.IActivityManager;
 import android.app.StatusBarManager;
 import android.app.admin.DevicePolicyManager;
@@ -497,6 +498,7 @@
     // mOpeningApps and mClosingApps are the lists of tokens that will be
     // made visible or hidden at the next transition.
     int mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
+    int mNextAppTransitionType = ActivityOptions.ANIM_NONE;
     String mNextAppTransitionPackage;
     Bitmap mNextAppTransitionThumbnail;
     IRemoteCallback mNextAppTransitionCallback;
@@ -504,6 +506,8 @@
     int mNextAppTransitionExit;
     int mNextAppTransitionStartX;
     int mNextAppTransitionStartY;
+    int mNextAppTransitionStartWidth;
+    int mNextAppTransitionStartHeight;
     boolean mAppTransitionReady = false;
     boolean mAppTransitionRunning = false;
     boolean mAppTransitionTimeout = false;
@@ -3072,6 +3076,50 @@
         return null;
     }
 
+    private Animation createScaleUpAnimationLocked(int transit, boolean enter) {
+        Animation a;
+        // Pick the desired duration.  If this is an inter-activity transition,
+        // it  is the standard duration for that.  Otherwise we use the longer
+        // task transition duration.
+        int duration;
+        switch (transit) {
+            case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
+            case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
+                duration = mContext.getResources().getInteger(
+                        com.android.internal.R.integer.config_shortAnimTime);
+                break;
+            default:
+                duration = 500;
+                break;
+        }
+        if (enter) {
+            // Entering app zooms out from the center of the initial rect.
+            Animation scale = new ScaleAnimation(
+                    mNextAppTransitionStartWidth/mAppDisplayWidth, 1,
+                    mNextAppTransitionStartHeight/mAppDisplayHeight, 1,
+                    mNextAppTransitionStartX + mNextAppTransitionStartWidth/2,
+                    mNextAppTransitionStartY + mNextAppTransitionStartHeight/2);
+            AnimationSet set = new AnimationSet(true);
+            Animation alpha = new AlphaAnimation(0, 1);
+            scale.setDuration(duration);
+            set.addAnimation(scale);
+            alpha.setDuration(duration);
+            set.addAnimation(alpha);
+            a = set;
+        } else {
+            // Exiting app just holds in place.
+            a = new AlphaAnimation(1, 1);
+            a.setDuration(duration);
+        }
+        a.setFillAfter(true);
+        final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext,
+                com.android.internal.R.interpolator.decelerate_quint);
+        a.setInterpolator(interpolator);
+        a.initialize(mAppDisplayWidth, mAppDisplayHeight,
+                mAppDisplayWidth, mAppDisplayHeight);
+        return a;
+    }
+
     private Animation createThumbnailAnimationLocked(int transit,
             boolean enter, boolean thumb) {
         Animation a;
@@ -3090,7 +3138,6 @@
             default:
                 duration = 500;
                 break;
-            
         }
         if (thumb) {
             // Animation for zooming thumbnail from its initial size to
@@ -3138,12 +3185,15 @@
         if (okToDisplay()) {
             Animation a;
             boolean initialized = false;
-            if (mNextAppTransitionThumbnail != null) {
-                a = createThumbnailAnimationLocked(transit, enter, false);
-                initialized = true;
-            } else if (mNextAppTransitionPackage != null) {
+            if (mNextAppTransitionType == ActivityOptions.ANIM_CUSTOM) {
                 a = loadAnimation(mNextAppTransitionPackage, enter ?
                         mNextAppTransitionEnter : mNextAppTransitionExit);
+            } else if (mNextAppTransitionType == ActivityOptions.ANIM_SCALE_UP) {
+                a = createScaleUpAnimationLocked(transit, enter);
+                initialized = true;
+            } else if (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL) {
+                a = createThumbnailAnimationLocked(transit, enter, false);
+                initialized = true;
             } else {
                 int animAttr = 0;
                 switch (transit) {
@@ -3738,6 +3788,7 @@
     public void overridePendingAppTransition(String packageName,
             int enterAnim, int exitAnim) {
         if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
+            mNextAppTransitionType = ActivityOptions.ANIM_CUSTOM;
             mNextAppTransitionPackage = packageName;
             mNextAppTransitionThumbnail = null;
             mNextAppTransitionEnter = enterAnim;
@@ -3745,9 +3796,23 @@
         }
     }
 
+    public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
+            int startHeight) {
+        if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
+            mNextAppTransitionType = ActivityOptions.ANIM_SCALE_UP;
+            mNextAppTransitionPackage = null;
+            mNextAppTransitionThumbnail = null;
+            mNextAppTransitionStartX = startX;
+            mNextAppTransitionStartY = startY;
+            mNextAppTransitionStartWidth = startWidth;
+            mNextAppTransitionStartHeight = startHeight;
+        }
+    }
+
     public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
             int startY, IRemoteCallback startedCallback) {
         if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
+            mNextAppTransitionType = ActivityOptions.ANIM_THUMBNAIL;
             mNextAppTransitionPackage = null;
             mNextAppTransitionThumbnail = srcThumb;
             mNextAppTransitionStartX = startX;
@@ -7848,6 +7913,7 @@
                 }
             }
 
+            mNextAppTransitionType = ActivityOptions.ANIM_NONE;
             mNextAppTransitionPackage = null;
             mNextAppTransitionThumbnail = null;
             if (mNextAppTransitionCallback != null) {
@@ -8812,6 +8878,7 @@
 
         if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
             mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
+            mNextAppTransitionType = ActivityOptions.ANIM_NONE;
             mNextAppTransitionPackage = null;
             mNextAppTransitionThumbnail = null;
             mAppTransitionReady = true;
@@ -9352,20 +9419,34 @@
                     pw.print(Integer.toHexString(mNextAppTransition));
                     pw.print(" mAppTransitionReady="); pw.println(mAppTransitionReady);
             pw.print("  mAppTransitionRunning="); pw.print(mAppTransitionRunning);
-                    pw.print(" mAppTransitionTimeout="); pw.println( mAppTransitionTimeout);
-            if (mNextAppTransitionPackage != null) {
-                pw.print("  mNextAppTransitionPackage=");
-                    pw.print(mNextAppTransitionPackage);
-                    pw.print(" mNextAppTransitionEnter=0x");
-                    pw.print(Integer.toHexString(mNextAppTransitionEnter));
-                    pw.print(" mNextAppTransitionExit=0x");
-                    pw.print(Integer.toHexString(mNextAppTransitionExit));
+                    pw.print(" mAppTransitionTimeout="); pw.println(mAppTransitionTimeout);
+            if (mNextAppTransitionType != ActivityOptions.ANIM_NONE) {
+                pw.print("  mNextAppTransitionType="); pw.println(mNextAppTransitionType);
             }
-            if (mNextAppTransitionThumbnail != null) {
-                pw.print("  mNextAppTransitionThumbnail=");
-                    pw.print(mNextAppTransitionThumbnail);
-                    pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX);
-                    pw.print(" mNextAppTransitionStartY="); pw.println(mNextAppTransitionStartY);
+            switch (mNextAppTransitionType) {
+                case ActivityOptions.ANIM_CUSTOM:
+                    pw.print("  mNextAppTransitionPackage=");
+                            pw.print(mNextAppTransitionPackage);
+                            pw.print(" mNextAppTransitionEnter=0x");
+                            pw.print(Integer.toHexString(mNextAppTransitionEnter));
+                            pw.print(" mNextAppTransitionExit=0x");
+                            pw.print(Integer.toHexString(mNextAppTransitionExit));
+                    break;
+                case ActivityOptions.ANIM_SCALE_UP:
+                    pw.print("  mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX);
+                            pw.print(" mNextAppTransitionStartY=");
+                            pw.println(mNextAppTransitionStartY);
+                    pw.print("  mNextAppTransitionStartWidth=");
+                            pw.print(mNextAppTransitionStartWidth);
+                            pw.print(" mNextAppTransitionStartHeight=");
+                            pw.println(mNextAppTransitionStartHeight);
+                    break;
+                case ActivityOptions.ANIM_THUMBNAIL:
+                    pw.print("  mNextAppTransitionThumbnail=");
+                            pw.print(mNextAppTransitionThumbnail);
+                            pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX);
+                            pw.print(" mNextAppTransitionStartY="); pw.println(mNextAppTransitionStartY);
+                    break;
             }
             pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
                     pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 8cfdb79..183beb1 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -64,8 +64,8 @@
     /*
      * Calling Line Identification Restriction (CLIR)
      */
-    private static final String CLIR_ON = "*31#+";
-    private static final String CLIR_OFF = "#31#+";
+    private static final String CLIR_ON = "*31#";
+    private static final String CLIR_OFF = "#31#";
 
     /*
      * TOA = TON + NPI
@@ -213,23 +213,26 @@
 
         int len = phoneNumber.length();
         StringBuilder ret = new StringBuilder(len);
-        boolean firstCharAdded = false;
 
         for (int i = 0; i < len; i++) {
             char c = phoneNumber.charAt(i);
-            if (isDialable(c) && (c != '+' || !firstCharAdded)) {
-                firstCharAdded = true;
+            // Character.digit() supports ASCII and Unicode digits (fullwidth, Arabic-Indic, etc.)
+            int digit = Character.digit(c, 10);
+            if (digit != -1) {
+                ret.append(digit);
+            } else if (c == '+') {
+                // Allow '+' as first character or after CLIR MMI prefix
+                String prefix = ret.toString();
+                if (prefix.length() == 0 || prefix.equals(CLIR_ON) || prefix.equals(CLIR_OFF)) {
+                    ret.append(c);
+                }
+            } else if (isDialable(c)) {
                 ret.append(c);
             } else if (isStartsPostDial (c)) {
                 break;
             }
         }
 
-        int pos = addPlusChar(phoneNumber);
-        if (pos >= 0 && ret.length() > pos) {
-            ret.insert(pos, '+');
-        }
-
         return ret.toString();
     }
 
@@ -283,7 +286,11 @@
 
         for (int i = 0; i < len; i++) {
             char c = phoneNumber.charAt(i);
-            if (isNonSeparator(c)) {
+            // Character.digit() supports ASCII and Unicode digits (fullwidth, Arabic-Indic, etc.)
+            int digit = Character.digit(c, 10);
+            if (digit != -1) {
+                ret.append(digit);
+            } else if (isNonSeparator(c)) {
                 ret.append(c);
             }
         }
@@ -371,28 +378,6 @@
         }
     }
 
-    /** GSM codes
-     *  Finds if a GSM code includes the international prefix (+).
-     *
-     * @param number the number to dial.
-     *
-     * @return the position where the + char will be inserted, -1 if the GSM code was not found.
-     */
-    private static int
-    addPlusChar(String number) {
-        int pos = -1;
-
-        if (number.startsWith(CLIR_OFF)) {
-            pos = CLIR_OFF.length() - 1;
-        }
-
-        if (number.startsWith(CLIR_ON)) {
-            pos = CLIR_ON.length() - 1;
-        }
-
-        return pos;
-    }
-
     /**
      * Extracts the post-dial sequence of DTMF control digits, pauses, and
      * waits. Strips separators. This string may be empty, but will not be null
@@ -1504,7 +1489,11 @@
         int len = phoneNumber.length();
         for (int i = 0; i < len; i++) {
             char c = phoneNumber.charAt(i);
-            if ((i == 0 && c == '+') || PhoneNumberUtils.isISODigit(c)) {
+            // Character.digit() supports ASCII and Unicode digits (fullwidth, Arabic-Indic, etc.)
+            int digit = Character.digit(c, 10);
+            if (digit != -1) {
+                sb.append(digit);
+            } else if (i == 0 && c == '+') {
                 sb.append(c);
             } else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
                 return normalizeNumber(PhoneNumberUtils.convertKeypadLettersToDigits(phoneNumber));
@@ -1513,6 +1502,27 @@
         return sb.toString();
     }
 
+    /**
+     * Replace arabic/unicode digits with decimal digits.
+     * @param number
+     *            the number to be normalized.
+     * @return the replaced number.
+     *
+     * @hide
+     */
+    public static String replaceUnicodeDigits(String number) {
+        StringBuilder normalizedDigits = new StringBuilder(number.length());
+        for (char c : number.toCharArray()) {
+            int digit = Character.digit(c, 10);
+            if (digit != -1) {
+                normalizedDigits.append(digit);
+            } else {
+                normalizedDigits.append(c);
+            }
+        }
+        return normalizedDigits.toString();
+    }
+
     // Three and four digit phone numbers for either special services,
     // or 3-6 digit addresses from the network (eg carrier-originated SMS messages) should
     // not match.
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index 5d1f758..b1a5872 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.database.Cursor;
+import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.location.CountryDetector;
 import android.net.Uri;
@@ -107,10 +108,33 @@
     /**
      * Drawable representing the caller image.  This is essentially
      * a cache for the image data tied into the connection /
-     * callerinfo object.  The isCachedPhotoCurrent flag indicates
-     * if the image data needs to be reloaded.
+     * callerinfo object.
+     *
+     * This might be a high resolution picture which is more suitable
+     * for full-screen image view than for smaller icons used in some
+     * kinds of notifications.
+     *
+     * The {@link #isCachedPhotoCurrent} flag indicates if the image
+     * data needs to be reloaded.
      */
     public Drawable cachedPhoto;
+    /**
+     * Bitmap representing the caller image which has possibly lower
+     * resolution than {@link #cachedPhoto} and thus more suitable for
+     * icons (like notification icons).
+     *
+     * In usual cases this is just down-scaled image of {@link #cachedPhoto}.
+     * If the down-scaling fails, this will just become null.
+     *
+     * The {@link #isCachedPhotoCurrent} flag indicates if the image
+     * data needs to be reloaded.
+     */
+    public Bitmap cachedPhotoIcon;
+    /**
+     * Boolean which indicates if {@link #cachedPhoto} and
+     * {@link #cachedPhotoIcon} is fresh enough. If it is false,
+     * those images aren't pointing to valid objects.
+     */
     public boolean isCachedPhotoCurrent;
 
     private boolean mIsEmergency;
diff --git a/tests/GridLayoutTest/AndroidManifest.xml b/tests/GridLayoutTest/AndroidManifest.xml
index 141e8fa..677220d 100644
--- a/tests/GridLayoutTest/AndroidManifest.xml
+++ b/tests/GridLayoutTest/AndroidManifest.xml
@@ -83,6 +83,13 @@
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
+
+        <activity android:name="LayoutInsetsTest" android:label="LayoutInsetsTest">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
     </application>
 
 
diff --git a/tests/GridLayoutTest/res/drawable/btn_default.xml b/tests/GridLayoutTest/res/drawable/btn_default.xml
new file mode 100644
index 0000000..c6cfda0
--- /dev/null
+++ b/tests/GridLayoutTest/res/drawable/btn_default.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_window_focused="false" android:state_enabled="true"
+        android:drawable="@drawable/my_btn_default_normal" />
+    <item android:state_window_focused="false" android:state_enabled="false"
+        android:drawable="@drawable/my_btn_default_normal" />
+    <item android:state_pressed="true" 
+        android:drawable="@drawable/my_btn_default_pressed" />
+    <item android:state_focused="true" android:state_enabled="true"
+        android:drawable="@drawable/my_btn_default_selected" />
+    <item android:state_enabled="true"
+        android:drawable="@drawable/my_btn_default_normal" />
+    <item android:state_focused="true"
+        android:drawable="@drawable/my_btn_default_normal_disable_focused" />
+    <item
+         android:drawable="@drawable/my_btn_default_normal_disable" />
+</selector>
diff --git a/tests/GridLayoutTest/res/drawable/my_btn_default_normal.9.png b/tests/GridLayoutTest/res/drawable/my_btn_default_normal.9.png
new file mode 100644
index 0000000..cd0b7d5
--- /dev/null
+++ b/tests/GridLayoutTest/res/drawable/my_btn_default_normal.9.png
Binary files differ
diff --git a/tests/GridLayoutTest/res/drawable/my_btn_default_normal_disable.9.png b/tests/GridLayoutTest/res/drawable/my_btn_default_normal_disable.9.png
new file mode 100755
index 0000000..f4f01c7
--- /dev/null
+++ b/tests/GridLayoutTest/res/drawable/my_btn_default_normal_disable.9.png
Binary files differ
diff --git a/tests/GridLayoutTest/res/drawable/my_btn_default_normal_disable_focused.9.png b/tests/GridLayoutTest/res/drawable/my_btn_default_normal_disable_focused.9.png
new file mode 100755
index 0000000..5376db2
--- /dev/null
+++ b/tests/GridLayoutTest/res/drawable/my_btn_default_normal_disable_focused.9.png
Binary files differ
diff --git a/tests/GridLayoutTest/res/drawable/my_btn_default_pressed.9.png b/tests/GridLayoutTest/res/drawable/my_btn_default_pressed.9.png
new file mode 100755
index 0000000..4312c27
--- /dev/null
+++ b/tests/GridLayoutTest/res/drawable/my_btn_default_pressed.9.png
Binary files differ
diff --git a/tests/GridLayoutTest/res/drawable/my_btn_default_selected.9.png b/tests/GridLayoutTest/res/drawable/my_btn_default_selected.9.png
new file mode 100755
index 0000000..06b7790
--- /dev/null
+++ b/tests/GridLayoutTest/res/drawable/my_btn_default_selected.9.png
Binary files differ
diff --git a/tests/GridLayoutTest/res/layout/grid7.xml b/tests/GridLayoutTest/res/layout/grid7.xml
index b9e58d7..0e5be0c 100644
--- a/tests/GridLayoutTest/res/layout/grid7.xml
+++ b/tests/GridLayoutTest/res/layout/grid7.xml
@@ -17,7 +17,7 @@
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
         android:layout_height="match_parent">
-    android:columnCount="2"
+
     <Space
             android:layout_row="0"
             android:layout_column="0"
diff --git a/tests/GridLayoutTest/src/com/android/test/layout/LayoutInsetsTest.java b/tests/GridLayoutTest/src/com/android/test/layout/LayoutInsetsTest.java
new file mode 100644
index 0000000..74daccc
--- /dev/null
+++ b/tests/GridLayoutTest/src/com/android/test/layout/LayoutInsetsTest.java
@@ -0,0 +1,59 @@
+package com.android.test.layout;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.GridLayout;
+import android.widget.Space;
+import android.widget.TextView;
+
+import static android.text.InputType.TYPE_CLASS_TEXT;
+import static android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
+import static android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD;
+import static android.widget.GridLayout.*;
+import static android.widget.GridLayout.FILL;
+import static android.widget.GridLayout.spec;
+
+public class LayoutInsetsTest extends Activity {
+    public static View create(Context context) {
+        GridLayout p = new GridLayout(context);
+        p.setUseDefaultMargins(true);
+        p.setAlignmentMode(ALIGN_BOUNDS);
+        p.setOrientation(VERTICAL);
+
+        {
+            TextView c = new TextView(context);
+            c.setTextSize(32);
+            c.setText("Email setup");
+            p.addView(c);
+        }
+        {
+            Button c = new Button(context);
+            c.setBackgroundResource(R.drawable.btn_default);
+            c.setText("Manual setup");
+            p.addView(c);
+            c.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    Button b = (Button) v;
+                    b.setEnabled(false);
+                }
+            });
+        }
+
+        return p;
+    }
+
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        //getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.ICE_CREAM_SANDWICH;
+        getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.JELLY_BEAN;
+        setContentView(create(this));
+    }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/element.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/element.rs
index 0c42d84..419ce07 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/element.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/element.rs
@@ -101,7 +101,7 @@
     _RS_ASSERT(rsElementGetDataKind(complexElem) == RS_KIND_USER);
     _RS_ASSERT(rsElementGetDataType(complexElem) == RS_TYPE_NONE);
     _RS_ASSERT(rsElementGetVectorSize(complexElem) == 1);
-    _RS_ASSERT(rsElementGetSizeBytes(complexElem) == sizeof(*complexStruct));
+    _RS_ASSERT(rsElementGetBytesSize(complexElem) == sizeof(*complexStruct));
 
     char buffer[64];
     for (uint32_t i = 0; i < subElemCount; i ++) {
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/program_raster.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/program_raster.rs
index 11b8c30..3d6b502 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/program_raster.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/program_raster.rs
@@ -7,10 +7,10 @@
 static bool test_program_raster_getters() {
     bool failed = false;
 
-    _RS_ASSERT(rsgProgramRasterGetPointSpriteEnabled(pointSpriteEnabled) == true);
+    _RS_ASSERT(rsgProgramRasterIsPointSpriteEnabled(pointSpriteEnabled) == true);
     _RS_ASSERT(rsgProgramRasterGetCullMode(pointSpriteEnabled) == RS_CULL_BACK);
 
-    _RS_ASSERT(rsgProgramRasterGetPointSpriteEnabled(cullMode) == false);
+    _RS_ASSERT(rsgProgramRasterIsPointSpriteEnabled(cullMode) == false);
     _RS_ASSERT(rsgProgramRasterGetCullMode(cullMode) == RS_CULL_FRONT);
 
     if (failed) {
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/program_store.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/program_store.rs
index 3cd8a20..2ae5636 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/program_store.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/program_store.rs
@@ -15,92 +15,92 @@
     bool failed = false;
 
     _RS_ASSERT(rsgProgramStoreGetDepthFunc(depthFunc) == RS_DEPTH_FUNC_GREATER);
-    _RS_ASSERT(rsgProgramStoreGetDepthMask(depthFunc) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskR(depthFunc) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskG(depthFunc) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskB(depthFunc) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskA(depthFunc) == false);
-    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(depthFunc) == false);
     _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(depthFunc) == RS_BLEND_SRC_ZERO);
     _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(depthFunc) == RS_BLEND_DST_ZERO);
 
     _RS_ASSERT(rsgProgramStoreGetDepthFunc(depthWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
-    _RS_ASSERT(rsgProgramStoreGetDepthMask(depthWriteEnable) == true);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskR(depthWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskG(depthWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskB(depthWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskA(depthWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(depthWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(depthWriteEnable) == true);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(depthWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(depthWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(depthWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( depthWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(depthWriteEnable) == false);
     _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(depthWriteEnable) == RS_BLEND_SRC_ZERO);
     _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(depthWriteEnable) == RS_BLEND_DST_ZERO);
 
     _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorRWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
-    _RS_ASSERT(rsgProgramStoreGetDepthMask(colorRWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskR(colorRWriteEnable) == true);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskG(colorRWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskB(colorRWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskA(colorRWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(colorRWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(colorRWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(colorRWriteEnable) == true);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(colorRWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(colorRWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( colorRWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(colorRWriteEnable) == false);
     _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorRWriteEnable) == RS_BLEND_SRC_ZERO);
     _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorRWriteEnable) == RS_BLEND_DST_ZERO);
 
     _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorGWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
-    _RS_ASSERT(rsgProgramStoreGetDepthMask(colorGWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskR(colorGWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskG(colorGWriteEnable) == true);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskB(colorGWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskA(colorGWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(colorGWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(colorGWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(colorGWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(colorGWriteEnable) == true);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(colorGWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( colorGWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(colorGWriteEnable) == false);
     _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorGWriteEnable) == RS_BLEND_SRC_ZERO);
     _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorGWriteEnable) == RS_BLEND_DST_ZERO);
 
     _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorBWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
-    _RS_ASSERT(rsgProgramStoreGetDepthMask(colorBWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskR(colorBWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskG(colorBWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskB(colorBWriteEnable) == true);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskA(colorBWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(colorBWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(colorBWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(colorBWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(colorBWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(colorBWriteEnable) == true);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( colorBWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(colorBWriteEnable) == false);
     _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorBWriteEnable) == RS_BLEND_SRC_ZERO);
     _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorBWriteEnable) == RS_BLEND_DST_ZERO);
 
     _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorAWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
-    _RS_ASSERT(rsgProgramStoreGetDepthMask(colorAWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskR(colorAWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskG(colorAWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskB(colorAWriteEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskA(colorAWriteEnable) == true);
-    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(colorAWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(colorAWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(colorAWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(colorAWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(colorAWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( colorAWriteEnable) == true);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(colorAWriteEnable) == false);
     _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorAWriteEnable) == RS_BLEND_SRC_ZERO);
     _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorAWriteEnable) == RS_BLEND_DST_ZERO);
 
     _RS_ASSERT(rsgProgramStoreGetDepthFunc(ditherEnable) == RS_DEPTH_FUNC_ALWAYS);
-    _RS_ASSERT(rsgProgramStoreGetDepthMask(ditherEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskR(ditherEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskG(ditherEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskB(ditherEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskA(ditherEnable) == false);
-    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(ditherEnable) == true);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(ditherEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(ditherEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(ditherEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(ditherEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( ditherEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(ditherEnable) == true);
     _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(ditherEnable) == RS_BLEND_SRC_ZERO);
     _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(ditherEnable) == RS_BLEND_DST_ZERO);
 
     _RS_ASSERT(rsgProgramStoreGetDepthFunc(blendSrc) == RS_DEPTH_FUNC_ALWAYS);
-    _RS_ASSERT(rsgProgramStoreGetDepthMask(blendSrc) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskR(blendSrc) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskG(blendSrc) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskB(blendSrc) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskA(blendSrc) == false);
-    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(blendSrc) == false);
     _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(blendSrc) == RS_BLEND_SRC_DST_COLOR);
     _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(blendSrc) == RS_BLEND_DST_ZERO);
 
     _RS_ASSERT(rsgProgramStoreGetDepthFunc(blendDst) == RS_DEPTH_FUNC_ALWAYS);
-    _RS_ASSERT(rsgProgramStoreGetDepthMask(blendDst) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskR(blendDst) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskG(blendDst) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskB(blendDst) == false);
-    _RS_ASSERT(rsgProgramStoreGetColorMaskA(blendDst) == false);
-    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(blendDst) == false);
     _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(blendDst) == RS_BLEND_SRC_ZERO);
     _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(blendDst) == RS_BLEND_DST_DST_ALPHA);
 
diff --git a/tests/SmokeTest/Android.mk b/tests/SmokeTest/Android.mk
index 0adfd4c..591a84e 100644
--- a/tests/SmokeTest/Android.mk
+++ b/tests/SmokeTest/Android.mk
@@ -6,11 +6,11 @@
 # This builds "SmokeTestApp"
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_PACKAGE_NAME := SmokeTestApp
 
+LOCAL_SDK_VERSION := 8
+
 include $(BUILD_PACKAGE)
 
 # This builds "SmokeTest"
-include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/SmokeTest/tests/Android.mk b/tests/SmokeTest/tests/Android.mk
index 86bf23d..18e682e 100644
--- a/tests/SmokeTest/tests/Android.mk
+++ b/tests/SmokeTest/tests/Android.mk
@@ -4,8 +4,6 @@
 # We only want this apk build for tests.
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 # Include all test java files.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
@@ -17,5 +15,7 @@
 
 LOCAL_INSTRUMENTATION_FOR := SmokeTestApp
 
+LOCAL_SDK_VERSION := 8
+
 include $(BUILD_PACKAGE)
 
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index cbd591f..a4473c8 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -1192,10 +1192,14 @@
             if (targetSdk < 4) {
                 if (!hasWriteExternalStoragePermission) {
                     printf("uses-permission:'android.permission.WRITE_EXTERNAL_STORAGE'\n");
+                    printf("uses-implied-permission:'android.permission.WRITE_EXTERNAL_STORAGE'," \
+                            "'targetSdkVersion < 4'\n");
                     hasWriteExternalStoragePermission = true;
                 }
                 if (!hasReadPhoneStatePermission) {
                     printf("uses-permission:'android.permission.READ_PHONE_STATE'\n");
+                    printf("uses-implied-permission:'android.permission.READ_PHONE_STATE'," \
+                            "'targetSdkVersion < 4'\n");
                 }
             }
 
@@ -1203,15 +1207,21 @@
             // force them to always take READ_EXTERNAL_STORAGE as well.
             if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) {
                 printf("uses-permission:'android.permission.READ_EXTERNAL_STORAGE'\n");
+                printf("uses-implied-permission:'android.permission.READ_EXTERNAL_STORAGE'," \
+                        "'requested WRITE_EXTERNAL_STORAGE'\n");
             }
 
             // Pre-JellyBean call log permission compatibility.
             if (targetSdk < 16) {
                 if (!hasReadCallLogPermission && hasReadContactsPermission) {
                     printf("uses-permission:'android.permission.READ_CALL_LOG'\n");
+                    printf("uses-implied-permission:'android.permission.READ_CALL_LOG'," \
+                            "'targetSdkVersion < 16 and requested READ_CONTACTS'\n");
                 }
                 if (!hasWriteCallLogPermission && hasWriteContactsPermission) {
                     printf("uses-permission:'android.permission.WRITE_CALL_LOG'\n");
+                    printf("uses-implied-permission:'android.permission.WRITE_CALL_LOG'," \
+                            "'targetSdkVersion < 16 and requested WRITE_CONTACTS'\n");
                 }
             }
 
@@ -1223,10 +1233,18 @@
              */
             // Camera-related back-compatibility logic
             if (!specCameraFeature) {
-                if (reqCameraFlashFeature || reqCameraAutofocusFeature) {
+                if (reqCameraFlashFeature) {
                     // if app requested a sub-feature (autofocus or flash) and didn't
                     // request the base camera feature, we infer that it meant to
                     printf("uses-feature:'android.hardware.camera'\n");
+                    printf("uses-implied-feature:'android.hardware.camera'," \
+                            "'requested android.hardware.camera.flash feature'\n");
+                } else if (reqCameraAutofocusFeature) {
+                    // if app requested a sub-feature (autofocus or flash) and didn't
+                    // request the base camera feature, we infer that it meant to
+                    printf("uses-feature:'android.hardware.camera'\n");
+                    printf("uses-implied-feature:'android.hardware.camera'," \
+                            "'requested android.hardware.camera.autofocus feature'\n");
                 } else if (hasCameraPermission) {
                     // if app wants to use camera but didn't request the feature, we infer 
                     // that it meant to, and further that it wants autofocus
@@ -1234,6 +1252,8 @@
                     printf("uses-feature:'android.hardware.camera'\n");
                     if (!specCameraAutofocusFeature) {
                         printf("uses-feature:'android.hardware.camera.autofocus'\n");
+                        printf("uses-implied-feature:'android.hardware.camera.autofocus'," \
+                                "'requested android.permission.CAMERA permission'\n");
                     }
                 }
             }
@@ -1245,16 +1265,22 @@
                 // if app either takes a location-related permission or requests one of the
                 // sub-features, we infer that it also meant to request the base location feature
                 printf("uses-feature:'android.hardware.location'\n");
+                printf("uses-implied-feature:'android.hardware.location'," \
+                        "'requested a location access permission'\n");
             }
             if (!specGpsFeature && hasGpsPermission) {
                 // if app takes GPS (FINE location) perm but does not request the GPS
                 // feature, we infer that it meant to
                 printf("uses-feature:'android.hardware.location.gps'\n");
+                printf("uses-implied-feature:'android.hardware.location.gps'," \
+                        "'requested android.permission.ACCESS_FINE_LOCATION permission'\n");
             }
             if (!specNetworkLocFeature && hasCoarseLocPermission) {
                 // if app takes Network location (COARSE location) perm but does not request the
                 // network location feature, we infer that it meant to
                 printf("uses-feature:'android.hardware.location.network'\n");
+                printf("uses-implied-feature:'android.hardware.location.network'," \
+                        "'requested android.permission.ACCESS_COURSE_LOCATION permission'\n");
             }
 
             // Bluetooth-related compatibility logic
@@ -1262,6 +1288,9 @@
                 // if app takes a Bluetooth permission but does not request the Bluetooth
                 // feature, we infer that it meant to
                 printf("uses-feature:'android.hardware.bluetooth'\n");
+                printf("uses-implied-feature:'android.hardware.bluetooth'," \
+                        "'requested android.permission.BLUETOOTH or android.permission.BLUETOOTH_ADMIN " \
+                        "permission and targetSdkVersion > 4'\n");
             }
 
             // Microphone-related compatibility logic
@@ -1269,6 +1298,8 @@
                 // if app takes the record-audio permission but does not request the microphone
                 // feature, we infer that it meant to
                 printf("uses-feature:'android.hardware.microphone'\n");
+                printf("uses-implied-feature:'android.hardware.microphone'," \
+                        "'requested android.permission.RECORD_AUDIO permission'\n");
             }
 
             // WiFi-related compatibility logic
@@ -1276,6 +1307,10 @@
                 // if app takes one of the WiFi permissions but does not request the WiFi
                 // feature, we infer that it meant to
                 printf("uses-feature:'android.hardware.wifi'\n");
+                printf("uses-implied-feature:'android.hardware.wifi'," \
+                        "'requested android.permission.ACCESS_WIFI_STATE, " \
+                        "android.permission.CHANGE_WIFI_STATE, or " \
+                        "android.permission.CHANGE_WIFI_MULTICAST_STATE permission'\n");
             }
 
             // Telephony-related compatibility logic
@@ -1283,6 +1318,8 @@
                 // if app takes one of the telephony permissions or requests a sub-feature but
                 // does not request the base telephony feature, we infer that it meant to
                 printf("uses-feature:'android.hardware.telephony'\n");
+                printf("uses-implied-feature:'android.hardware.telephony'," \
+                        "'requested a telephony-related permission or feature'\n");
             }
 
             // Touchscreen-related back-compatibility logic
@@ -1292,11 +1329,15 @@
                 // Note that specTouchscreenFeature is true if the tag is present, regardless
                 // of whether its value is true or false, so this is safe
                 printf("uses-feature:'android.hardware.touchscreen'\n");
+                printf("uses-implied-feature:'android.hardware.touchscreen'," \
+                        "'assumed you require a touch screen unless explicitly made optional'\n");
             }
             if (!specMultitouchFeature && reqDistinctMultitouchFeature) {
                 // if app takes one of the telephony permissions or requests a sub-feature but
                 // does not request the base telephony feature, we infer that it meant to
                 printf("uses-feature:'android.hardware.touchscreen.multitouch'\n");
+                printf("uses-implied-feature:'android.hardware.touchscreen.multitouch'," \
+                        "'requested android.hardware.touchscreen.multitouch.distinct feature'\n");
             }
 
             // Landscape/portrait-related compatibility logic
@@ -1306,9 +1347,13 @@
                 // orientation is required.
                 if (reqScreenLandscapeFeature) {
                     printf("uses-feature:'android.hardware.screen.landscape'\n");
+                    printf("uses-implied-feature:'android.hardware.screen.landscape'," \
+                            "'one or more activities have specified a landscape orientation'\n");
                 }
                 if (reqScreenPortraitFeature) {
                     printf("uses-feature:'android.hardware.screen.portrait'\n");
+                    printf("uses-implied-feature:'android.hardware.screen.portrait'," \
+                            "'one or more activities have specified a portrait orientation'\n");
                 }
             }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
index e6c9351..44d28fa 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
@@ -229,6 +229,12 @@
     }
 
     @Override
+    public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
+            int startHeight) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
     public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
             IRemoteCallback startedCallback) throws RemoteException {
         // TODO Auto-generated method stub
diff --git a/wifi/java/android/net/wifi/StateChangeResult.java b/wifi/java/android/net/wifi/StateChangeResult.java
index 8ab5982..b15c4a6 100644
--- a/wifi/java/android/net/wifi/StateChangeResult.java
+++ b/wifi/java/android/net/wifi/StateChangeResult.java
@@ -23,12 +23,15 @@
  * @hide
  */
 public class StateChangeResult {
-    StateChangeResult(int networkId, String BSSID, SupplicantState state) {
+    StateChangeResult(int networkId, String SSID, String BSSID, SupplicantState state) {
         this.state = state;
+        this.SSID = SSID;
         this.BSSID = BSSID;
         this.networkId = networkId;
     }
+
     int networkId;
+    String SSID;
     String BSSID;
     SupplicantState state;
 }
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index 3bd03f5..a447c86 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -637,6 +637,9 @@
          * id=network-id state=new-state
          */
         private void handleSupplicantStateChange(String dataString) {
+            String SSID = null;
+            int index = dataString.lastIndexOf("SSID=");
+            if (index != -1) SSID = dataString.substring(index + 5);
             String[] dataTokens = dataString.split(" ");
 
             String BSSID = null;
@@ -657,7 +660,6 @@
                 try {
                     value = Integer.parseInt(nameValue[1]);
                 } catch (NumberFormatException e) {
-                    Log.w(TAG, "STATE-CHANGE non-integer parameter: " + token);
                     continue;
                 }
 
@@ -680,7 +682,7 @@
             if (newSupplicantState == SupplicantState.INVALID) {
                 Log.w(TAG, "Invalid supplicant state: " + newState);
             }
-            notifySupplicantStateChange(networkId, BSSID, newSupplicantState);
+            notifySupplicantStateChange(networkId, SSID, BSSID, newSupplicantState);
         }
     }
 
@@ -729,11 +731,13 @@
      * Send the state machine a notification that the state of the supplicant
      * has changed.
      * @param networkId the configured network on which the state change occurred
+     * @param SSID network name
+     * @param BSSID network address
      * @param newState the new {@code SupplicantState}
      */
-    void notifySupplicantStateChange(int networkId, String BSSID, SupplicantState newState) {
+    void notifySupplicantStateChange(int networkId, String SSID, String BSSID, SupplicantState newState) {
         mStateMachine.sendMessage(mStateMachine.obtainMessage(SUPPLICANT_STATE_CHANGE_EVENT,
-                new StateChangeResult(networkId, BSSID, newState)));
+                new StateChangeResult(networkId, SSID, BSSID, newState)));
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index cc0df52..2f14098 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -669,6 +669,7 @@
 
         setInitialState(mInitialState);
 
+        setProcessedMessagesSize(100);
         if (DBG) setDbg(true);
 
         //start the state machine
@@ -1121,6 +1122,37 @@
         return sb.toString();
     }
 
+    @Override
+    protected boolean recordProcessedMessage(Message msg) {
+        //Ignore screen on/off & common messages when driver has started
+        if (getCurrentState() == mConnectedState || getCurrentState() == mDisconnectedState) {
+            switch (msg.what) {
+                case CMD_LOAD_DRIVER:
+                case CMD_START_SUPPLICANT:
+                case CMD_START_DRIVER:
+                case CMD_SET_SCAN_MODE:
+                case CMD_SET_HIGH_PERF_MODE:
+                case CMD_SET_SUSPEND_OPTIMIZATIONS:
+                case CMD_CLEAR_SUSPEND_OPTIMIZATIONS:
+                case CMD_ENABLE_BACKGROUND_SCAN:
+                case CMD_ENABLE_ALL_NETWORKS:
+                return false;
+            }
+        }
+
+        switch (msg.what) {
+            case CMD_START_SCAN:
+            case CMD_ENABLE_RSSI_POLL:
+            case CMD_RSSI_POLL:
+            case CMD_DELAYED_STOP_DRIVER:
+            case WifiMonitor.SCAN_RESULTS_EVENT:
+            case WifiWatchdogStateMachine.RSSI_FETCH:
+                return false;
+            default:
+                return true;
+        }
+    }
+
     /*********************************************************
      * Internal private functions
      ********************************************************/
@@ -1409,23 +1441,6 @@
         mScanResults = scanList;
     }
 
-    private String fetchSSID() {
-        String status = mWifiNative.status();
-        if (status == null) {
-            return null;
-        }
-        // extract ssid from a series of "name=value"
-        String[] lines = status.split("\n");
-        for (String line : lines) {
-            String[] prop = line.split(" *= *");
-            if (prop.length < 2) continue;
-            String name = prop[0];
-            String value = prop[1];
-            if (name.equalsIgnoreCase("ssid")) return value;
-        }
-        return null;
-    }
-
     /*
      * Fetch RSSI and linkspeed on current connection
      */
@@ -1586,6 +1601,7 @@
             /* BSSID is valid only in ASSOCIATING state */
             mWifiInfo.setBSSID(stateChangeResult.BSSID);
         }
+        mWifiInfo.setSSID(stateChangeResult.SSID);
 
         mSupplicantStateTracker.sendMessage(Message.obtain(message));
 
@@ -2015,7 +2031,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
@@ -2068,7 +2083,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
@@ -2148,7 +2162,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
@@ -2169,7 +2182,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
@@ -2250,7 +2262,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
@@ -2274,7 +2285,6 @@
         public boolean processMessage(Message message) {
             if (DBG) log(getName() + message.toString() + "\n");
             WifiConfiguration config;
-            boolean eventLoggingEnabled = true;
             switch(message.what) {
                 case CMD_STOP_SUPPLICANT:   /* Supplicant stopped by user */
                     transitionTo(mSupplicantStoppingState);
@@ -2291,7 +2301,6 @@
                     sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
                     break;
                 case WifiMonitor.SCAN_RESULTS_EVENT:
-                    eventLoggingEnabled = false;
                     setScanResults(mWifiNative.scanResults());
                     sendScanResultsAvailableBroadcast();
                     mScanResultIsPending = false;
@@ -2381,9 +2390,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            if (eventLoggingEnabled) {
-                EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
-            }
             return HANDLED;
         }
 
@@ -2459,7 +2465,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
@@ -2505,7 +2510,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
@@ -2564,14 +2568,12 @@
         @Override
         public boolean processMessage(Message message) {
             if (DBG) log(getName() + message.toString() + "\n");
-            boolean eventLoggingEnabled = true;
             switch(message.what) {
                case CMD_SET_SCAN_TYPE:
                     mSetScanActive = (message.arg1 == SCAN_ACTIVE);
                     mWifiNative.setScanMode(mSetScanActive);
                     break;
                 case CMD_START_SCAN:
-                    eventLoggingEnabled = false;
                     boolean forceActive = (message.arg1 == SCAN_ACTIVE);
                     if (forceActive && !mSetScanActive) {
                         mWifiNative.setScanMode(forceActive);
@@ -2681,9 +2683,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            if (eventLoggingEnabled) {
-                EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
-            }
             return HANDLED;
         }
         @Override
@@ -2731,7 +2730,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
@@ -2764,7 +2762,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
@@ -2801,7 +2798,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
@@ -2923,8 +2919,6 @@
                     mLastNetworkId = message.arg1;
                     mLastBssid = (String) message.obj;
 
-                    //TODO: make supplicant modification to push this in events
-                    mWifiInfo.setSSID(fetchSSID());
                     mWifiInfo.setBSSID(mLastBssid);
                     mWifiInfo.setNetworkId(mLastNetworkId);
                     /* send event to CM & network change broadcast */
@@ -2940,7 +2934,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
@@ -2959,7 +2952,6 @@
         @Override
         public boolean processMessage(Message message) {
             if (DBG) log(getName() + message.toString() + "\n");
-            boolean eventLoggingEnabled = true;
             switch (message.what) {
               case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
                   handlePreDhcpSetup();
@@ -2988,7 +2980,6 @@
                     }
                     break;
                 case CMD_START_SCAN:
-                    eventLoggingEnabled = false;
                     /* When the network is connected, re-scanning can trigger
                      * a reconnection. Put it in scan-only mode during scan.
                      * When scan results are received, the mode is switched
@@ -3031,7 +3022,6 @@
                 case WifiMonitor.NETWORK_CONNECTION_EVENT:
                     break;
                 case CMD_RSSI_POLL:
-                    eventLoggingEnabled = false;
                     if (message.arg1 == mRssiPollToken) {
                         // Get Info and continue polling
                         fetchRssiAndLinkSpeedNative();
@@ -3052,7 +3042,6 @@
                     }
                     break;
                 case WifiWatchdogStateMachine.RSSI_FETCH:
-                    eventLoggingEnabled = false;
                     fetchRssiAndLinkSpeedNative();
                     replyToMessage(message, WifiWatchdogStateMachine.RSSI_FETCH_SUCCEEDED,
                             mWifiInfo.getRssi());
@@ -3061,9 +3050,6 @@
                     return NOT_HANDLED;
             }
 
-            if (eventLoggingEnabled) {
-                EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
-            }
             return HANDLED;
         }
 
@@ -3131,7 +3117,6 @@
               default:
                   return NOT_HANDLED;
           }
-          EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
           return HANDLED;
       }
     }
@@ -3168,7 +3153,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
@@ -3202,7 +3186,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
         @Override
@@ -3240,7 +3223,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
@@ -3343,7 +3325,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
 
@@ -3432,7 +3413,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
 
@@ -3504,7 +3484,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
@@ -3548,7 +3527,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
@@ -3598,7 +3576,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
@@ -3629,7 +3606,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
@@ -3692,7 +3668,6 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
     }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 35f37a8..df14bb9 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -22,8 +22,8 @@
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
 import android.net.nsd.DnsSdTxtRecord;
-import android.net.wifi.p2p.nsd.WifiP2pBonjourServiceInfo;
-import android.net.wifi.p2p.nsd.WifiP2pBonjourServiceResponse;
+import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo;
+import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceResponse;
 import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
 import android.net.wifi.p2p.nsd.WifiP2pServiceRequest;
 import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
@@ -56,21 +56,20 @@
  * callbacks provided by the application. The application needs to do an initialization with
  * {@link #initialize} before doing any p2p operation.
  *
- * <p> Application actions {@link #discoverPeers}, {@link #connect}, {@link #cancelConnect},
- * {@link #createGroup} and {@link #removeGroup} need a {@link ActionListener} instance for
- * receiving callbacks {@link ActionListener#onSuccess} or {@link ActionListener#onFailure}.
- * Action callbacks indicate whether the initiation of the action was a success or a failure.
+ * <p> Most application calls need a {@link ActionListener} instance for receiving callbacks
+ * {@link ActionListener#onSuccess} or {@link ActionListener#onFailure}. Action callbacks
+ * indicate whether the initiation of the action was a success or a failure.
  * Upon failure, the reason of failure can be one of {@link #ERROR}, {@link #P2P_UNSUPPORTED}
  * or {@link #BUSY}.
  *
  * <p> An application can initiate discovery of peers with {@link #discoverPeers}. An initiated
  * discovery request from an application stays active until the device starts connecting to a peer
- * or forms a p2p group. The {@link ActionListener} callbacks provide feedback on whether the
- * discovery initiation was successful or failure. Additionally, applications can listen
- * to {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent action to know when the peer list changes.
+ * ,forms a p2p group or there is an explicit {@link #stopPeerDiscovery}.
+ * Applications can listen to {@link #WIFI_P2P_DISCOVERY_CHANGED_ACTION} to know if a peer-to-peer
+ * discovery is running or stopped. Additionally, {@link #WIFI_P2P_PEERS_CHANGED_ACTION} indicates
+ * if the peer list has changed.
  *
- * <p> When the peer list change intent {@link #WIFI_P2P_PEERS_CHANGED_ACTION} is received
- * or when an application needs to fetch the current list of peers, it can request the list
+ * <p> When an application needs to fetch the current list of peers, it can request the list
  * of peers with {@link #requestPeers}. When the peer list is available
  * {@link PeerListListener#onPeersAvailable} is called with the device list.
  *
@@ -78,7 +77,7 @@
  * {@link WifiP2pConfig} for details on setting up the configuration. For communication with legacy
  * Wi-Fi devices that do not support p2p, an app can create a group using {@link #createGroup}
  * which creates an access point whose details can be fetched with {@link #requestGroupInfo}.
-*
+ *
  * <p> After a successful group formation through {@link #createGroup} or through {@link #connect},
  * use {@link #requestConnectionInfo} to fetch the connection details. The connection info
  * {@link WifiP2pInfo} contains the address of the group owner
@@ -86,8 +85,36 @@
  * if the current device is a p2p group owner. A p2p client can thus communicate with
  * the p2p group owner through a socket connection.
  *
- * <p> Android has no platform support for service discovery yet, so applications could
- * run a service discovery protocol to discover services on the peer-to-peer netework.
+ * <p> With peer discovery using {@link  #discoverPeers}, an application discovers the neighboring
+ * peers, but has no good way to figure out which peer to establish a connection with. For example,
+ * if a game application is interested in finding all the neighboring peers that are also running
+ * the same game, it has no way to find out until after the connection is setup. Pre-association
+ * service discovery is meant to address this issue of filtering the peers based on the running
+ * services.
+ *
+ * <p>With pre-association service discovery, an application can advertise a service for a
+ * application on a peer device prior to a connection setup between the devices.
+ * Currently, DNS based service discovery (Bonjour) and Upnp are the higher layer protocols
+ * supported. Get Bonjour resources at dns-sd.org and Upnp resources at upnp.org
+ * As an example, a video application can discover a Upnp capable media renderer
+ * prior to setting up a Wi-fi p2p connection with the device.
+ *
+ * <p> An application can advertise a Upnp or a Bonjour service with a call to
+ * {@link #addLocalService}. After a local service is added,
+ * the framework automatically responds to a peer application discovering the service prior
+ * to establishing a p2p connection. A call to {@link #removeLocalService} removes a local
+ * service and {@link #clearLocalServices} can be used to clear all local services.
+ *
+ * <p> An application that is looking for peer devices that support certain services
+ * can do so with a call to  {@link #discoverServices}. Prior to initiating the discovery,
+ * application can add service discovery request with a call to {@link #addServiceRequest},
+ * remove a service discovery request with a call to {@link #removeServiceRequest} or clear
+ * all requests with a call to {@link #clearServiceRequests}. When no service requests remain,
+ * a previously running service discovery will stop.
+ *
+ * The application is notified of a result of service discovery request through listener callbacks
+ * set through {@link #setDnsSdResponseListeners} for Bonjour or
+ * {@link #setUpnpServiceResponseListener} for Upnp.
  *
  * <p class="note"><strong>Note:</strong>
  * Registering an application handler with {@link #initialize} requires the permissions
@@ -443,30 +470,28 @@
 
     /**
     * Interface for callback invocation when service discovery response other than
-    * UPnP or Bonjour is received
-    * @hide
+    * Upnp or Bonjour is received
     */
     public interface ServiceResponseListener {
 
         /**
          * The requested service response is available.
          *
-         * @param serviceType service type. see the service type of
-         * {@link WifiP2pServiceInfo}
+         * @param protocolType protocol type. currently only
+         * {@link WifiP2pServiceInfo#SERVICE_TYPE_VENDOR_SPECIFIC}.
          * @param responseData service discovery response data based on the requested
          *  service protocol type. The format depends on the service type.
          * @param srcDevice source device.
          */
-        public void onServiceAvailable(int serviceType,
+        public void onServiceAvailable(int protocolType,
                 byte[] responseData, WifiP2pDevice srcDevice);
     }
 
     /**
      * Interface for callback invocation when Bonjour service discovery response
      * is received
-     * @hide
      */
-    public interface BonjourServiceResponseListener {
+    public interface DnsSdServiceResponseListener {
 
         /**
          * The requested Bonjour service response is available.
@@ -479,7 +504,7 @@
          * e.g) "_ipp._tcp.local."
          * @param srcDevice source device.
          */
-        public void onBonjourServiceAvailable(String instanceName,
+        public void onDnsSdServiceAvailable(String instanceName,
                 String registrationType, WifiP2pDevice srcDevice);
 
    }
@@ -487,9 +512,8 @@
     /**
      * Interface for callback invocation when Bonjour TXT record is available
      * for a service
-     * @hide
      */
-   public interface BonjourTxtRecordListener {
+   public interface DnsSdTxtRecordListener {
         /**
          * The requested Bonjour service response is available.
          *
@@ -501,7 +525,7 @@
          * @param record txt record.
          * @param srcDevice source device.
          */
-        public void onBonjourTxtRecordAvailable(String fullDomainName,
+        public void onDnsSdTxtRecordAvailable(String fullDomainName,
                 DnsSdTxtRecord record,
                 WifiP2pDevice srcDevice);
    }
@@ -509,7 +533,6 @@
     /**
      * Interface for callback invocation when upnp service discovery response
      * is received
-     * @hide
      * */
     public interface UpnpServiceResponseListener {
 
@@ -542,8 +565,8 @@
         private final static int INVALID_LISTENER_KEY = 0;
         private ChannelListener mChannelListener;
         private ServiceResponseListener mServRspListener;
-        private BonjourServiceResponseListener mBonjourServRspListener;
-        private BonjourTxtRecordListener mBonjourTxtListener;
+        private DnsSdServiceResponseListener mDnsSdServRspListener;
+        private DnsSdTxtRecordListener mDnsSdTxtListener;
         private UpnpServiceResponseListener mUpnpServRspListener;
         private HashMap<Integer, Object> mListenerMap = new HashMap<Integer, Object>();
         private Object mListenerMapLock = new Object();
@@ -632,8 +655,8 @@
         }
 
         private void handleServiceResponse(WifiP2pServiceResponse resp) {
-            if (resp instanceof WifiP2pBonjourServiceResponse) {
-                handleBonjourServiceResponse((WifiP2pBonjourServiceResponse)resp);
+            if (resp instanceof WifiP2pDnsSdServiceResponse) {
+                handleDnsSdServiceResponse((WifiP2pDnsSdServiceResponse)resp);
             } else if (resp instanceof WifiP2pUpnpServiceResponse) {
                 if (mUpnpServRspListener != null) {
                     handleUpnpServiceResponse((WifiP2pUpnpServiceResponse)resp);
@@ -651,17 +674,17 @@
                     resp.getSrcDevice());
         }
 
-        private void handleBonjourServiceResponse(WifiP2pBonjourServiceResponse resp) {
-            if (resp.getDnsType() == WifiP2pBonjourServiceInfo.DNS_TYPE_PTR) {
-                if (mBonjourServRspListener != null) {
-                    mBonjourServRspListener.onBonjourServiceAvailable(
+        private void handleDnsSdServiceResponse(WifiP2pDnsSdServiceResponse resp) {
+            if (resp.getDnsType() == WifiP2pDnsSdServiceInfo.DNS_TYPE_PTR) {
+                if (mDnsSdServRspListener != null) {
+                    mDnsSdServRspListener.onDnsSdServiceAvailable(
                             resp.getInstanceName(),
                             resp.getDnsQueryName(),
                             resp.getSrcDevice());
                 }
-            } else if (resp.getDnsType() == WifiP2pBonjourServiceInfo.DNS_TYPE_TXT) {
-                if (mBonjourTxtListener != null) {
-                    mBonjourTxtListener.onBonjourTxtRecordAvailable(
+            } else if (resp.getDnsType() == WifiP2pDnsSdServiceInfo.DNS_TYPE_TXT) {
+                if (mDnsSdTxtListener != null) {
+                    mDnsSdTxtListener.onDnsSdTxtRecordAvailable(
                             resp.getDnsQueryName(),
                             resp.getTxtRecord(),
                             resp.getSrcDevice());
@@ -749,10 +772,16 @@
         c.mAsyncChannel.sendMessage(DISCOVER_PEERS, 0, c.putListener(listener));
     }
 
-    /**
-     * TODO: Add more documentation before opening up
-     * Cancel peer discovery
-     * @hide
+   /**
+     * Stop an ongoing peer discovery
+     *
+     * <p> The function call immediately returns after sending a stop request
+     * to the framework. The application is notified of a success or failure to initiate
+     * stop through listener callbacks {@link ActionListener#onSuccess} or
+     * {@link ActionListener#onFailure}.
+     *
+     * @param c is the channel created at {@link #initialize}
+     * @param listener for callbacks on success or failure. Can be null.
      */
     public void stopPeerDiscovery(Channel c, ActionListener listener) {
         checkChannel(c);
@@ -843,27 +872,25 @@
     }
 
     /**
-     * Register a local service of service discovery.
+     * Register a local service for service discovery. If a local service is registered,
+     * the framework automatically responds to a service discovery request from a peer.
      *
      * <p> The function call immediately returns after sending a request to add a local
      * service to the framework. The application is notified of a success or failure to
      * add service through listener callbacks {@link ActionListener#onSuccess} or
      * {@link ActionListener#onFailure}.
      *
-     * <p>The service information is set through the subclass of {@link WifiP2pServiceInfo}.<br>
-     * e.g )  {@link WifiP2pUpnpServiceInfo#newInstance} or
-     *  {@link WifiP2pBonjourServiceInfo#newInstance}
+     * <p>The service information is set through {@link WifiP2pServiceInfo}.<br>
+     * or its subclass calls  {@link WifiP2pUpnpServiceInfo#newInstance} or
+     *  {@link WifiP2pDnsSdServiceInfo#newInstance} for a Upnp or Bonjour service
+     * respectively
      *
-     * <p>If a local service is added, the framework responds the appropriate service discovery
-     *  request automatically.
-     *
-     * <p>These service information will be clear when p2p is disabled or call
+     * <p>The service information can be cleared with calls to
      *  {@link #removeLocalService} or {@link #clearLocalServices}.
      *
      * @param c is the channel created at {@link #initialize}
      * @param servInfo is a local service information.
      * @param listener for callbacks on success or failure. Can be null.
-     * @hide
      */
     public void addLocalService(Channel c, WifiP2pServiceInfo servInfo, ActionListener listener) {
         checkChannel(c);
@@ -872,7 +899,7 @@
     }
 
     /**
-     * Unregister a specified local service of service discovery.
+     * Remove a registered local service added with {@link #addLocalService}
      *
      * <p> The function call immediately returns after sending a request to remove a
      * local service to the framework. The application is notified of a success or failure to
@@ -882,7 +909,6 @@
      * @param c is the channel created at {@link #initialize}
      * @param servInfo is the local service information.
      * @param listener for callbacks on success or failure. Can be null.
-     * @hide
      */
     public void removeLocalService(Channel c, WifiP2pServiceInfo servInfo,
             ActionListener listener) {
@@ -901,7 +927,6 @@
      *
      * @param c is the channel created at {@link #initialize}
      * @param listener for callbacks on success or failure. Can be null.
-     * @hide
      */
     public void clearLocalServices(Channel c, ActionListener listener) {
         checkChannel(c);
@@ -910,12 +935,14 @@
 
     /**
      * Register a callback to be invoked on receiving service discovery response.
+     * Used only for vendor specific protocol right now. For Bonjour or Upnp, use
+     * {@link #setDnsSdResponseListeners} or {@link #setUpnpServiceResponseListener}
+     * respectively.
      *
      * <p> see {@link #discoverServices} for the detail.
      *
      * @param c is the channel created at {@link #initialize}
      * @param listener for callbacks on receiving service discovery response.
-     * @hide
      */
     public void setServiceResponseListener(Channel c,
             ServiceResponseListener listener) {
@@ -930,15 +957,14 @@
      * <p> see {@link #discoverServices} for the detail.
      *
      * @param c
-     * @param servlistener is for listening to a Bonjour service response
-     * @param txtListener is for listening to a Bonjour TXT record
-     * @hide
+     * @param servListener is for listening to a Bonjour service response
+     * @param txtListener is for listening to a Bonjour TXT record response
      */
-    public void setBonjourResponseListeners(Channel c,
-            BonjourServiceResponseListener servListener, BonjourTxtRecordListener txtListener) {
+    public void setDnsSdResponseListeners(Channel c,
+            DnsSdServiceResponseListener servListener, DnsSdTxtRecordListener txtListener) {
         checkChannel(c);
-        c.mBonjourServRspListener = servListener;
-        c.mBonjourTxtListener = txtListener;
+        c.mDnsSdServRspListener = servListener;
+        c.mDnsSdTxtListener = txtListener;
     }
 
     /**
@@ -949,7 +975,6 @@
      *
      * @param c is the channel created at {@link #initialize}
      * @param listener for callbacks on receiving service discovery response.
-     * @hide
      */
     public void setUpnpServiceResponseListener(Channel c,
             UpnpServiceResponseListener listener) {
@@ -971,11 +996,10 @@
      *
      * <p>The application is notified of the response against the service discovery request
      * through listener callbacks registered by {@link #setServiceResponseListener} or
-     * {@link #setBonjourServiceResponseListener}, or {@link #setUpnpServiceResponseListener}.
+     * {@link #setDnsSdResponseListeners}, or {@link #setUpnpServiceResponseListener}.
      *
      * @param c is the channel created at {@link #initialize}
      * @param listener for callbacks on success or failure. Can be null.
-     * @hide
      */
     public void discoverServices(Channel c, ActionListener listener) {
         checkChannel(c);
@@ -993,14 +1017,13 @@
      * <p>After service discovery request is added, you can initiate service discovery by
      * {@link #discoverServices}.
      *
-     * <p>These information will be clear when wifi p2p is disabled or
+     * <p>The added service requests can be cleared with calls to
      * {@link #removeServiceRequest(Channel, WifiP2pServiceRequest, ActionListener)} or
-     * {@link #clearServiceRequests(Channel, ActionListener)} is called.
+     * {@link #clearServiceRequests(Channel, ActionListener)}.
      *
      * @param c is the channel created at {@link #initialize}
      * @param req is the service discovery request.
      * @param listener for callbacks on success or failure. Can be null.
-     * @hide
      */
     public void addServiceRequest(Channel c,
             WifiP2pServiceRequest req, ActionListener listener) {
@@ -1011,7 +1034,7 @@
     }
 
     /**
-     * Remove a specified service discovery request.
+     * Remove a specified service discovery request added with {@link #addServiceRequest}
      *
      * <p> The function call immediately returns after sending a request to remove service
      * discovery request to the framework. The application is notified of a success or failure to
@@ -1021,7 +1044,6 @@
      * @param c is the channel created at {@link #initialize}
      * @param req is the service discovery request.
      * @param listener for callbacks on success or failure. Can be null.
-     * @hide
      */
     public void removeServiceRequest(Channel c, WifiP2pServiceRequest req,
             ActionListener listener) {
@@ -1041,7 +1063,6 @@
      *
      * @param c is the channel created at {@link #initialize}
      * @param listener for callbacks on success or failure. Can be null.
-     * @hide
      */
     public void clearServiceRequests(Channel c, ActionListener listener) {
         checkChannel(c);
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pBonjourServiceRequest.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pBonjourServiceRequest.java
deleted file mode 100644
index d1635f1..0000000
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pBonjourServiceRequest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2012 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.p2p.nsd;
-
-
-/**
- * A class for a request of bonjour service discovery.
- * @hide
- */
-public class WifiP2pBonjourServiceRequest extends WifiP2pServiceRequest {
-
-    /**
-     * This constructor is only used in newInstance().
-     *
-     * @param query The part of service specific query.
-     * @hide
-     */
-    private WifiP2pBonjourServiceRequest(String query) {
-        super(WifiP2pServiceInfo.SERVICE_TYPE_BONJOUR, query);
-    }
-
-    /**
-     * This constructor is only used in newInstance().
-     * @hide
-     */
-    private WifiP2pBonjourServiceRequest() {
-        super(WifiP2pServiceInfo.SERVICE_TYPE_BONJOUR, null);
-    }
-
-    private WifiP2pBonjourServiceRequest(String registrationType, int dnsType, int version) {
-        super(WifiP2pServiceInfo.SERVICE_TYPE_BONJOUR, WifiP2pBonjourServiceInfo.createRequest(
-                registrationType,
-                WifiP2pBonjourServiceInfo.DNS_TYPE_PTR,
-                WifiP2pBonjourServiceInfo.VERSION_1));
-    }
-
-    /**
-     * Create a service discovery request to search all Bonjour services.
-     *
-     * @return service request for Bonjour.
-     */
-    public static WifiP2pBonjourServiceRequest newInstance() {
-        return new WifiP2pBonjourServiceRequest();
-    }
-
-    /**
-     * Create a service discovery request to resolve the instance name with the specified
-     * registration type.
-     *
-     * @param registrationType registration type. Cannot be null <br>
-     * e.g) <br>
-     *  "_afpovertcp._tcp.local."(Apple File Sharing over TCP)<br>
-     *  "_ipp._tcp.local." (IP Printing over TCP)<br>
-     * @return service request for Bonjour.
-     */
-    public static WifiP2pBonjourServiceRequest newInstance(String registrationType) {
-        if (registrationType == null) {
-            throw new IllegalArgumentException("registration type cannot be null");
-        }
-        return new WifiP2pBonjourServiceRequest(registrationType,
-                WifiP2pBonjourServiceInfo.DNS_TYPE_PTR,
-                WifiP2pBonjourServiceInfo.VERSION_1);
-    }
-
-    /**
-     * Create a service discovery request to get the TXT data from the specified
-     * service.
-     *
-     * @param instanceName instance name. Cannot be null. <br>
-     *  "MyPrinter"
-     * @param registrationType registration type. Cannot be null. <br>
-     * e.g) <br>
-     *  "_afpovertcp._tcp.local."(Apple File Sharing over TCP)<br>
-     *  "_ipp._tcp.local." (IP Printing over TCP)<br>
-     * @return service request for Bonjour.
-     */
-    public static WifiP2pBonjourServiceRequest newInstance(String instanceName,
-            String registrationType) {
-        if (instanceName == null || registrationType == null) {
-            throw new IllegalArgumentException(
-                    "instance name or registration type cannot be null");
-        }
-        String fullDomainName = instanceName + "." + registrationType;
-        return new WifiP2pBonjourServiceRequest(fullDomainName,
-                WifiP2pBonjourServiceInfo.DNS_TYPE_TXT,
-                WifiP2pBonjourServiceInfo.VERSION_1);
-    }
-}
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pBonjourServiceInfo.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
similarity index 78%
rename from wifi/java/android/net/wifi/p2p/nsd/WifiP2pBonjourServiceInfo.java
rename to wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
index ed278d5..54b7ac4 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pBonjourServiceInfo.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
@@ -25,10 +25,15 @@
 import java.util.Map;
 
 /**
- * A class for Bonjour service information.
- * @hide
+ * A class for storing Bonjour service information that is advertised
+ * over a Wi-Fi peer-to-peer setup.
+ *
+ * {@see android.net.wifi.p2p.WifiP2pManager#addLocalService}
+ * {@see android.net.wifi.p2p.WifiP2pManager#removeLocalService}
+ * {@see WifiP2pServiceInfo}
+ * {@see WifiP2pUpnpServiceInfo}
  */
-public class WifiP2pBonjourServiceInfo extends WifiP2pServiceInfo {
+public class WifiP2pDnsSdServiceInfo extends WifiP2pServiceInfo {
 
     /**
      * Bonjour version 1.
@@ -67,25 +72,26 @@
      *
      * @param queryList
      */
-    private WifiP2pBonjourServiceInfo(List<String> queryList) {
+    private WifiP2pDnsSdServiceInfo(List<String> queryList) {
         super(queryList);
     }
 
     /**
-     * Create Bonjour service information object.
+     * Create a Bonjour service information object.
      *
      * @param instanceName instance name.<br>
      *  e.g) "MyPrinter"
-     * @param registrationType registration type.<br>
-     *  e.g) "_ipp._tcp.local."
-     * @param txtRecord text record.
+     * @param serviceType service type.<br>
+     *  e.g) "_ipp._tcp"
+     * @param txtRecord TXT record as defined at
+     * http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt
      * @return Bonjour service information object
      */
-    public static WifiP2pBonjourServiceInfo newInstance(String instanceName,
-            String registrationType, DnsSdTxtRecord txtRecord) {
-        if (TextUtils.isEmpty(instanceName) || TextUtils.isEmpty(registrationType)) {
+    public static WifiP2pDnsSdServiceInfo newInstance(String instanceName,
+            String serviceType, DnsSdTxtRecord txtRecord) {
+        if (TextUtils.isEmpty(instanceName) || TextUtils.isEmpty(serviceType)) {
             throw new IllegalArgumentException(
-                    "instance name or registration type cannot be empty");
+                    "instance name or service type cannot be empty");
         }
 
         if (txtRecord == null) {
@@ -93,10 +99,10 @@
         }
 
         ArrayList<String> queries = new ArrayList<String>();
-        queries.add(createPtrServiceQuery(instanceName, registrationType));
-        queries.add(createTxtServiceQuery(instanceName, registrationType, txtRecord));
+        queries.add(createPtrServiceQuery(instanceName, serviceType));
+        queries.add(createTxtServiceQuery(instanceName, serviceType, txtRecord));
 
-        return new WifiP2pBonjourServiceInfo(queries);
+        return new WifiP2pDnsSdServiceInfo(queries);
     }
 
     /**
@@ -104,16 +110,16 @@
      *
      * @param instanceName instance name.<br>
      *  e.g) "MyPrinter"
-     * @param registrationType registration type.<br>
-     *  e.g) "_ipp._tcp.local."
+     * @param serviceType service type.<br>
+     *  e.g) "_ipp._tcp"
      * @return wpa_supplicant service query.
      */
     private static String createPtrServiceQuery(String instanceName,
-            String registrationType) {
+            String serviceType) {
 
         StringBuffer sb = new StringBuffer();
         sb.append("bonjour ");
-        sb.append(createRequest(registrationType, DNS_TYPE_PTR, VERSION_1));
+        sb.append(createRequest(serviceType + ".local.", DNS_TYPE_PTR, VERSION_1));
         sb.append(" ");
 
         byte[] data = instanceName.getBytes();
@@ -130,20 +136,20 @@
      *
      * @param instanceName instance name.<br>
      *  e.g) "MyPrinter"
-     * @param registrationType registration type.<br>
-     *  e.g) "_ipp._tcp.local."
+     * @param serviceType service type.<br>
+     *  e.g) "_ipp._tcp"
      * @param txtRecord TXT record.<br>
      * @return wpa_supplicant service query.
      */
-    public static String createTxtServiceQuery(String instanceName,
-            String registrationType,
+    private static String createTxtServiceQuery(String instanceName,
+            String serviceType,
             DnsSdTxtRecord txtRecord) {
 
 
         StringBuffer sb = new StringBuffer();
         sb.append("bonjour ");
 
-        sb.append(createRequest((instanceName + "." + registrationType),
+        sb.append(createRequest((instanceName + "." + serviceType + ".local."),
                 DNS_TYPE_TXT, VERSION_1));
         sb.append(" ");
         byte[] rawData = txtRecord.getRawData();
@@ -173,7 +179,7 @@
          * ________________________________________________
          * |   Type (2)           | Version (1) |
          */
-        if (dnsType == WifiP2pBonjourServiceInfo.DNS_TYPE_TXT) {
+        if (dnsType == WifiP2pDnsSdServiceInfo.DNS_TYPE_TXT) {
             dnsName = dnsName.toLowerCase();
         }
         sb.append(compressDnsName(dnsName));
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceRequest.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceRequest.java
new file mode 100644
index 0000000..d5415e0
--- /dev/null
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceRequest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2012 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.p2p.nsd;
+
+import android.net.wifi.p2p.WifiP2pManager;
+
+/**
+ * A class for creating a Bonjour service discovery request for use with
+ * {@link WifiP2pManager#addServiceRequest} and {@link WifiP2pManager#removeServiceRequest}
+ *
+ * {@see WifiP2pManager}
+ * {@see WifiP2pServiceRequest}
+ * {@see WifiP2pUpnpServiceRequest}
+ */
+public class WifiP2pDnsSdServiceRequest extends WifiP2pServiceRequest {
+
+    /**
+     * This constructor is only used in newInstance().
+     *
+     * @param query The part of service specific query.
+     * @hide
+     */
+    private WifiP2pDnsSdServiceRequest(String query) {
+        super(WifiP2pServiceInfo.SERVICE_TYPE_BONJOUR, query);
+    }
+
+    /**
+     * This constructor is only used in newInstance().
+     * @hide
+     */
+    private WifiP2pDnsSdServiceRequest() {
+        super(WifiP2pServiceInfo.SERVICE_TYPE_BONJOUR, null);
+    }
+
+    private WifiP2pDnsSdServiceRequest(String dnsQuery, int dnsType, int version) {
+        super(WifiP2pServiceInfo.SERVICE_TYPE_BONJOUR, WifiP2pDnsSdServiceInfo.createRequest(
+                dnsQuery,
+                dnsType,
+                version));
+    }
+
+    /**
+     * Create a service discovery request to search all Bonjour services.
+     *
+     * @return service request for Bonjour.
+     */
+    public static WifiP2pDnsSdServiceRequest newInstance() {
+        return new WifiP2pDnsSdServiceRequest();
+    }
+
+    /**
+     * Create a service discovery to search for Bonjour services with the specified
+     * service type.
+     *
+     * @param serviceType service type. Cannot be null <br>
+     *  "_afpovertcp._tcp."(Apple File Sharing over TCP)<br>
+     *  "_ipp._tcp" (IP Printing over TCP)<br>
+     *  "_http._tcp" (http service)
+     * @return service request for DnsSd.
+     */
+    public static WifiP2pDnsSdServiceRequest newInstance(String serviceType) {
+        if (serviceType == null) {
+            throw new IllegalArgumentException("service type cannot be null");
+        }
+        return new WifiP2pDnsSdServiceRequest(serviceType + ".local.",
+                WifiP2pDnsSdServiceInfo.DNS_TYPE_PTR,
+                WifiP2pDnsSdServiceInfo.VERSION_1);
+    }
+
+    /**
+     * Create a service discovery request to get the TXT data from the specified
+     * Bonjour service.
+     *
+     * @param instanceName instance name. Cannot be null. <br>
+     *  "MyPrinter"
+     * @param serviceType service type. Cannot be null. <br>
+     * e.g) <br>
+     *  "_afpovertcp._tcp"(Apple File Sharing over TCP)<br>
+     *  "_ipp._tcp" (IP Printing over TCP)<br>
+     * @return service request for Bonjour.
+     */
+    public static WifiP2pDnsSdServiceRequest newInstance(String instanceName,
+            String serviceType) {
+        if (instanceName == null || serviceType == null) {
+            throw new IllegalArgumentException(
+                    "instance name or service type cannot be null");
+        }
+        String fullDomainName = instanceName + "." + serviceType + ".local.";
+        return new WifiP2pDnsSdServiceRequest(fullDomainName,
+                WifiP2pDnsSdServiceInfo.DNS_TYPE_TXT,
+                WifiP2pDnsSdServiceInfo.VERSION_1);
+    }
+}
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pBonjourServiceResponse.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceResponse.java
similarity index 88%
rename from wifi/java/android/net/wifi/p2p/nsd/WifiP2pBonjourServiceResponse.java
rename to wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceResponse.java
index c511569..c053c8a 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pBonjourServiceResponse.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceResponse.java
@@ -30,7 +30,7 @@
  *
  * @hide
  */
-public class WifiP2pBonjourServiceResponse extends WifiP2pServiceResponse {
+public class WifiP2pDnsSdServiceResponse extends WifiP2pServiceResponse {
 
     /**
      * DNS query name.
@@ -46,27 +46,27 @@
      * Service instance name.
      * e.g) "MyPrinter"
      * This field is only used when the dns type equals to
-     * {@link WifiP2pBonjourServiceInfo#DNS_TYPE_PTR}.
+     * {@link WifiP2pDnsSdServiceInfo#DNS_TYPE_PTR}.
      */
     private String mInstanceName;
 
     /**
      * DNS Type.
-     * Should be {@link WifiP2pBonjourServiceInfo#DNS_TYPE_PTR} or
-     * {@link WifiP2pBonjourServiceInfo#DNS_TYPE_TXT}.
+     * Should be {@link WifiP2pDnsSdServiceInfo#DNS_TYPE_PTR} or
+     * {@link WifiP2pDnsSdServiceInfo#DNS_TYPE_TXT}.
      */
     private int mDnsType;
 
     /**
-     * Bonjour version number.
-     * Should be {@link WifiP2pBonjourServiceInfo#VERSION_1}.
+     * DnsSd version number.
+     * Should be {@link WifiP2pDnsSdServiceInfo#VERSION_1}.
      */
     private int mVersion;
 
     /**
      * Txt record.
      * This field is only used when the dns type equals to
-     * {@link WifiP2pBonjourServiceInfo#DNS_TYPE_TXT}.
+     * {@link WifiP2pDnsSdServiceInfo#DNS_TYPE_TXT}.
      */
     private DnsSdTxtRecord mTxtRecord;
 
@@ -128,7 +128,7 @@
     @Override
     public String toString() {
         StringBuffer sbuf = new StringBuffer();
-        sbuf.append("serviceType:Bonjour(").append(mServiceType).append(")");
+        sbuf.append("serviceType:DnsSd(").append(mServiceType).append(")");
         sbuf.append(" status:").append(Status.toString(mStatus));
         sbuf.append(" srcAddr:").append(mDevice.deviceAddress);
         sbuf.append(" version:").append(String.format("%02x", mVersion));
@@ -149,7 +149,7 @@
      * @param data RDATA.
      * @hide
      */
-    protected WifiP2pBonjourServiceResponse(int status,
+    protected WifiP2pDnsSdServiceResponse(int status,
             int tranId, WifiP2pDevice dev, byte[] data) {
         super(WifiP2pServiceInfo.SERVICE_TYPE_BONJOUR,
                 status, tranId, dev, data);
@@ -159,7 +159,7 @@
     }
 
     /**
-     * Parse Bonjour service discovery response.
+     * Parse DnsSd service discovery response.
      *
      * @return {@code true} if the operation succeeded
      */
@@ -193,7 +193,7 @@
             return false;
         }
 
-        if (mDnsType == WifiP2pBonjourServiceInfo.DNS_TYPE_PTR) {
+        if (mDnsType == WifiP2pDnsSdServiceInfo.DNS_TYPE_PTR) {
             String rData = readDnsName(dis);
             if (rData == null) {
                 return false;
@@ -204,7 +204,7 @@
 
             mInstanceName = rData.substring(0,
                     rData.length() - mDnsQueryName.length() -1);
-        } else if (mDnsType == WifiP2pBonjourServiceInfo.DNS_TYPE_TXT) {
+        } else if (mDnsType == WifiP2pDnsSdServiceInfo.DNS_TYPE_TXT) {
             mTxtRecord = readTxtData(dis);
             if (mTxtRecord == null) {
                 return false;
@@ -287,23 +287,23 @@
     }
 
     /**
-     * Creates Bonjour service response.
+     * Creates DnsSd service response.
      *  This is only called from WifiP2pServiceResponse
      *
      * @param status status code.
      * @param dev source device.
-     * @param data Bonjour response data.
-     * @return Bonjour service response data.
+     * @param data DnsSd response data.
+     * @return DnsSd service response data.
      * @hide
      */
-    static WifiP2pBonjourServiceResponse newInstance(int status,
+    static WifiP2pDnsSdServiceResponse newInstance(int status,
             int transId, WifiP2pDevice dev, byte[] data) {
         if (status != WifiP2pServiceResponse.Status.SUCCESS) {
-            return new WifiP2pBonjourServiceResponse(status,
+            return new WifiP2pDnsSdServiceResponse(status,
                     transId, dev, null);
         }
         try {
-            return new WifiP2pBonjourServiceResponse(status,
+            return new WifiP2pDnsSdServiceResponse(status,
                     transId, dev, data);
         } catch (IllegalArgumentException e) {
             e.printStackTrace();
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java
index aed5616..b931475 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java
@@ -23,13 +23,11 @@
 import java.util.List;
 
 /**
- * The class for service information.
- *
- * <p>Currently UPnP and Bonjour are only supported.
+ * A class for storing service information that is advertised
+ * over a Wi-Fi peer-to-peer setup
  *
  * @see WifiP2pUpnpServiceInfo
- * @see WifiP2pBonjourServiceInfo
- * @hide
+ * @see WifiP2pDnsSdServiceInfo
  */
 public class WifiP2pServiceInfo implements Parcelable {
 
@@ -39,7 +37,7 @@
     public static final int SERVICE_TYPE_ALL             = 0;
 
     /**
-     * Bonjour protocol.
+     * DNS based service discovery protocol.
      */
     public static final int SERVICE_TYPE_BONJOUR         = 1;
 
@@ -50,6 +48,7 @@
 
     /**
      * WS-Discovery protocol
+     * @hide
      */
     public static final int SERVICE_TYPE_WS_DISCOVERY    = 3;
 
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java
index e41d9aa..c7f0e5f 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java
@@ -21,24 +21,26 @@
 import android.os.Parcelable;
 
 /**
- * A class for a request of service discovery.
+ * A class for creating a service discovery request for use with
+ * {@link WifiP2pManager#addServiceRequest} and {@link WifiP2pManager#removeServiceRequest}
  *
- * <p>This class is used when you create customized service discovery request.
- * e.g) vendor specific request/ws discovery etc.
+ * <p>This class is used to create service discovery request for custom
+ * vendor specific service discovery protocol {@link WifiP2pServiceInfo#SERVICE_TYPE_VENDOR_SPECIFIC}
+ * or to search all service protocols {@link WifiP2pServiceInfo#SERVICE_TYPE_ALL}.
  *
- * <p>If you want to create UPnP or Bonjour service request, then you had better
- * use {@link WifiP2pUpnpServiceRequest} or {@link WifiP2pBonjourServiceRequest}.
+ * <p>For the purpose of creating a UPnP or Bonjour service request, use
+ * {@link WifiP2pUpnpServiceRequest} or {@link WifiP2pDnsSdServiceRequest} respectively.
  *
- * @see WifiP2pUpnpServiceRequest
- * @see WifiP2pBonjourServiceRequest
- * @hide
+ * {@see WifiP2pManager}
+ * {@see WifiP2pUpnpServiceRequest}
+ * {@see WifiP2pDnsSdServiceRequest}
  */
 public class WifiP2pServiceRequest implements Parcelable {
 
     /**
-     * Service type. It's defined in table63 in Wi-Fi Direct specification.
+     * Service discovery protocol. It's defined in table63 in Wi-Fi Direct specification.
      */
-    private int mServiceType;
+    private int mProtocolType;
 
     /**
      * The length of the service request TLV.
@@ -56,7 +58,7 @@
     /**
      * The hex dump string of query data for the requested service information.
      *
-     * e.g) Bonjour apple file sharing over tcp (dns name=_afpovertcp._tcp.local.)
+     * e.g) DnsSd apple file sharing over tcp (dns name=_afpovertcp._tcp.local.)
      * 0b5f6166706f766572746370c00c000c01
      */
     private String mQuery;
@@ -64,14 +66,14 @@
     /**
      * This constructor is only used in newInstance().
      *
-     * @param serviceType service discovery type.
+     * @param protocolType service discovery protocol.
      * @param query The part of service specific query.
      * @hide
      */
-    protected WifiP2pServiceRequest(int serviceType, String query) {
+    protected WifiP2pServiceRequest(int protocolType, String query) {
         validateQuery(query);
 
-        mServiceType = serviceType;
+        mProtocolType = protocolType;
         mQuery = query;
         if (query != null) {
             mLength = query.length()/2 + 2;
@@ -90,7 +92,7 @@
      */
     private WifiP2pServiceRequest(int serviceType, int length,
             int transId, String query) {
-        mServiceType = serviceType;
+        mProtocolType = serviceType;
         mLength = length;
         mTransId = transId;
         mQuery = query;
@@ -134,7 +136,7 @@
         // length is retained as little endian format.
         sb.append(String.format("%02x", (mLength) & 0xff));
         sb.append(String.format("%02x", (mLength >> 8) & 0xff));
-        sb.append(String.format("%02x", mServiceType));
+        sb.append(String.format("%02x", mProtocolType));
         sb.append(String.format("%02x", mTransId));
         if (mQuery != null) {
             sb.append(mQuery);
@@ -177,42 +179,34 @@
     }
 
     /**
-     * Create service discovery request.
+     * Create a service discovery request.
      *
-     * <p>The created instance is set to framework by
-     * {@link WifiP2pManager#addLocalService}.
+     * @param protocolType can be {@link WifiP2pServiceInfo#SERVICE_TYPE_ALL}
+     * or {@link WifiP2pServiceInfo#SERVICE_TYPE_VENDOR_SPECIFIC}.
+     * In order to create a UPnP or Bonjour service request, use
+     * {@link WifiP2pUpnpServiceRequest} or {@link WifiP2pDnsSdServiceRequest}
+     * respectively
      *
-     * @param serviceType service type.<br>
-     * e.g) {@link WifiP2pServiceInfo#SERVICE_TYPE_ALL},
-     *  {@link WifiP2pServiceInfo#SERVICE_TYPE_WS_DISCOVERY},
-     * {@link WifiP2pServiceInfo#SERVICE_TYPE_VENDOR_SPECIFIC}.
-     * If you want to use UPnP or Bonjour, you create  the request by
-     * {@link WifiP2pUpnpServiceRequest} or {@link WifiP2pBonjourServiceRequest}
-     *
-     * @param query hex string. if null, all specified services are requested.
+     * @param queryData hex string that is vendor specific.  Can be null.
      * @return service discovery request.
      */
-    public static WifiP2pServiceRequest newInstance(int serviceType, String query) {
-        return new WifiP2pServiceRequest(serviceType, query);
+    public static WifiP2pServiceRequest newInstance(int protocolType, String queryData) {
+        return new WifiP2pServiceRequest(protocolType, queryData);
     }
 
     /**
-     * Create all service discovery request.
+     * Create a service discovery request.
      *
-     * <p>The created instance is set to framework by
-     * {@link WifiP2pManager#addLocalService}.
-     *
-     * @param serviceType service type.<br>
-     * e.g) {@link WifiP2pServiceInfo#SERVICE_TYPE_ALL},
-     *  {@link WifiP2pServiceInfo#SERVICE_TYPE_WS_DISCOVERY},
-     * {@link WifiP2pServiceInfo#SERVICE_TYPE_VENDOR_SPECIFIC}.
-     * If you want to use UPnP or Bonjour, you create  the request by
-     * {@link WifiP2pUpnpServiceRequest} or {@link WifiP2pBonjourServiceRequest}
+     * @param protocolType can be {@link WifiP2pServiceInfo#SERVICE_TYPE_ALL}
+     * or {@link WifiP2pServiceInfo#SERVICE_TYPE_VENDOR_SPECIFIC}.
+     * In order to create a UPnP or Bonjour service request, use
+     * {@link WifiP2pUpnpServiceRequest} or {@link WifiP2pDnsSdServiceRequest}
+     * respectively
      *
      * @return service discovery request.
      */
-    public static WifiP2pServiceRequest newInstance(int serviceType) {
-        return new WifiP2pServiceRequest(serviceType, null);
+    public static WifiP2pServiceRequest newInstance(int protocolType ) {
+        return new WifiP2pServiceRequest(protocolType, null);
     }
 
     @Override
@@ -230,7 +224,7 @@
          * Not compare transaction id.
          * Transaction id may be changed on each service discovery operation.
          */
-        if ((req.mServiceType != mServiceType) ||
+        if ((req.mProtocolType != mProtocolType) ||
                 (req.mLength != mLength)) {
             return false;
         }
@@ -246,7 +240,7 @@
     @Override
     public int hashCode() {
         int result = 17;
-        result = 31 * result + mServiceType;
+        result = 31 * result + mProtocolType;
         result = 31 * result + mLength;
         result = 31 * result + (mQuery == null ? 0 : mQuery.hashCode());
         return result;
@@ -259,7 +253,7 @@
 
     /** Implement the Parcelable interface {@hide} */
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mServiceType);
+        dest.writeInt(mProtocolType);
         dest.writeInt(mLength);
         dest.writeInt(mTransId);
         dest.writeString(mQuery);
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.java
index 0855eae..ac31663 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.java
@@ -246,7 +246,7 @@
 
                 WifiP2pServiceResponse resp;
                 if (type ==  WifiP2pServiceInfo.SERVICE_TYPE_BONJOUR) {
-                    resp = WifiP2pBonjourServiceResponse.newInstance(status,
+                    resp = WifiP2pDnsSdServiceResponse.newInstance(status,
                             transId, dev, data);
                 } else if (type == WifiP2pServiceInfo.SERVICE_TYPE_UPNP) {
                     resp = WifiP2pUpnpServiceResponse.newInstance(status,
@@ -373,7 +373,7 @@
                     in.readByteArray(data);
                 }
                 if (type ==  WifiP2pServiceInfo.SERVICE_TYPE_BONJOUR) {
-                    return WifiP2pBonjourServiceResponse.newInstance(status,
+                    return WifiP2pDnsSdServiceResponse.newInstance(status,
                             transId, dev, data);
                 } else if (type == WifiP2pServiceInfo.SERVICE_TYPE_UPNP) {
                     return WifiP2pUpnpServiceResponse.newInstance(status,
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pUpnpServiceInfo.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pUpnpServiceInfo.java
index 4d40e81..40a0d61 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pUpnpServiceInfo.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pUpnpServiceInfo.java
@@ -21,8 +21,13 @@
 import java.util.UUID;
 
 /**
- * The class for UPnP service information.
- * @hide
+ * A class for storing Upnp service information that is advertised
+ * over a Wi-Fi peer-to-peer setup.
+ *
+ * {@see android.net.wifi.p2p.WifiP2pManager#addLocalService}
+ * {@see android.net.wifi.p2p.WifiP2pManager#removeLocalService}
+ * {@see WifiP2pServiceInfo}
+ * {@see WifiP2pDnsSdServiceInfo}
  */
 public class WifiP2pUpnpServiceInfo extends WifiP2pServiceInfo {
 
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pUpnpServiceRequest.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pUpnpServiceRequest.java
index b97637a..b5cf144 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pUpnpServiceRequest.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pUpnpServiceRequest.java
@@ -16,9 +16,15 @@
 
 package android.net.wifi.p2p.nsd;
 
+import android.net.wifi.p2p.WifiP2pManager;
+
 /**
- * The class for a request of upnp service discovery.
- * @hide
+ * A class for creating a Upnp service discovery request for use with
+ * {@link WifiP2pManager#addServiceRequest} and {@link WifiP2pManager#removeServiceRequest}
+ *
+ * {@see WifiP2pManager}
+ * {@see WifiP2pServiceRequest}
+ * {@see WifiP2pDnsSdServiceRequest}
  */
 public class WifiP2pUpnpServiceRequest extends WifiP2pServiceRequest {