Merge "Fix some policy-base routing issues." into ics-mr1
diff --git a/Android.mk b/Android.mk
index 586eb4a..4cd85ec 100644
--- a/Android.mk
+++ b/Android.mk
@@ -329,20 +329,36 @@
../../external/apache-http/src/org/apache/http
# These are relative to frameworks/base
-dirs_to_document := \
- $(fwbase_dirs_to_document) \
+dirs_to_check_apis := \
+ $(fwbase_dirs_to_document) \
$(non_base_dirs)
+# These are relative to frameworks/base
+# FRAMEWORKS_BASE_SUBDIRS comes from build/core/pathmap.mk
+dirs_to_document := \
+ $(dirs_to_check_apis) \
+ $(addprefix ../../, $(FRAMEWORKS_SUPPORT_JAVA_SRC_DIRS))
+
+# These are relative to frameworks/base
html_dirs := \
$(FRAMEWORKS_BASE_SUBDIRS) \
$(non_base_dirs)
+# 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 ../../system/media/mca/, $(call libfilterfw_to_document, $(LOCAL_PATH)/../../system/media/mca)) \
+
# These are relative to frameworks/base
framework_docs_LOCAL_SRC_FILES := \
$(call find-other-java-files, $(dirs_to_document)) \
- $(call find-other-html-files, $(html_dirs)) \
- $(addprefix ../../libcore/, $(call libcore_to_document, $(LOCAL_PATH)/../../libcore)) \
- $(addprefix ../../system/media/mca/, $(call libfilterfw_to_document, $(LOCAL_PATH)/../../system/media/mca))
+ $(common_src_files)
+
+# These are relative to frameworks/base
+framework_docs_LOCAL_API_CHECK_SRC_FILES := \
+ $(call find-other-java-files, $(dirs_to_check_apis)) \
+ $(common_src_files)
# This is used by ide.mk as the list of source files that are
# always included.
@@ -412,6 +428,8 @@
resources/samples/BackupRestore "Backup and Restore" \
-samplecode $(sample_dir)/BluetoothChat \
resources/samples/BluetoothChat "Bluetooth Chat" \
+ -samplecode $(sample_dir)/BluetoothHDP \
+ resources/samples/BluetoothHDP "Bluetooth HDP Demo" \
-samplecode $(sample_dir)/BusinessCard \
resources/samples/BusinessCard "Business Card" \
-samplecode $(sample_dir)/ContactManager \
@@ -493,7 +511,7 @@
# ==== the api stubs and current.xml ===========================
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
+LOCAL_SRC_FILES:=$(framework_docs_LOCAL_API_CHECK_SRC_FILES)
LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
diff --git a/api/current.txt b/api/current.txt
index f33c6cb..23b441b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -83,6 +83,7 @@
field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
field public static final java.lang.String READ_PROFILE = "android.permission.READ_PROFILE";
field public static final java.lang.String READ_SMS = "android.permission.READ_SMS";
+ field public static final java.lang.String READ_SOCIAL_STREAM = "android.permission.READ_SOCIAL_STREAM";
field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
field public static final java.lang.String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
field public static final java.lang.String REBOOT = "android.permission.REBOOT";
@@ -127,6 +128,7 @@
field public static final java.lang.String WRITE_SECURE_SETTINGS = "android.permission.WRITE_SECURE_SETTINGS";
field public static final java.lang.String WRITE_SETTINGS = "android.permission.WRITE_SETTINGS";
field public static final java.lang.String WRITE_SMS = "android.permission.WRITE_SMS";
+ field public static final java.lang.String WRITE_SOCIAL_STREAM = "android.permission.WRITE_SOCIAL_STREAM";
field public static final java.lang.String WRITE_SYNC_SETTINGS = "android.permission.WRITE_SYNC_SETTINGS";
}
@@ -13631,16 +13633,19 @@
field public static final int GL_RENDERBUFFER_RED_SIZE_OES = 36176; // 0x8d50
field public static final int GL_RENDERBUFFER_STENCIL_SIZE_OES = 36181; // 0x8d55
field public static final int GL_RENDERBUFFER_WIDTH_OES = 36162; // 0x8d42
+ field public static final int GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES = 36200; // 0x8d68
field public static final int GL_RGB565_OES = 36194; // 0x8d62
field public static final int GL_RGB5_A1_OES = 32855; // 0x8057
field public static final int GL_RGB8_OES = 32849; // 0x8051
field public static final int GL_RGBA4_OES = 32854; // 0x8056
field public static final int GL_RGBA8_OES = 32856; // 0x8058
+ field public static final int GL_SAMPLER_EXTERNAL_OES = 36198; // 0x8d66
field public static final int GL_STENCIL_ATTACHMENT_OES = 36128; // 0x8d20
field public static final int GL_STENCIL_INDEX1_OES = 36166; // 0x8d46
field public static final int GL_STENCIL_INDEX4_OES = 36167; // 0x8d47
field public static final int GL_STENCIL_INDEX8_OES = 36168; // 0x8d48
field public static final int GL_TEXTURE_BINDING_CUBE_MAP_OES = 34068; // 0x8514
+ field public static final int GL_TEXTURE_BINDING_EXTERNAL_OES = 36199; // 0x8d67
field public static final int GL_TEXTURE_CROP_RECT_OES = 35741; // 0x8b9d
field public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES = 34070; // 0x8516
field public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES = 34072; // 0x8518
@@ -13649,6 +13654,7 @@
field public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES = 34069; // 0x8515
field public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES = 34071; // 0x8517
field public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES = 34073; // 0x8519
+ field public static final int GL_TEXTURE_EXTERNAL_OES = 36197; // 0x8d65
field public static final int GL_TEXTURE_GEN_MODE_OES = 9472; // 0x2500
field public static final int GL_TEXTURE_GEN_STR_OES = 36192; // 0x8d60
field public static final int GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES = 35215; // 0x898f
@@ -25145,7 +25151,7 @@
method public synchronized java.lang.String getFixedFontFamily();
method public synchronized boolean getJavaScriptCanOpenWindowsAutomatically();
method public synchronized boolean getJavaScriptEnabled();
- method public deprecated synchronized android.webkit.WebSettings.LayoutAlgorithm getLayoutAlgorithm();
+ method public synchronized android.webkit.WebSettings.LayoutAlgorithm getLayoutAlgorithm();
method public boolean getLightTouchEnabled();
method public boolean getLoadWithOverviewMode();
method public synchronized boolean getLoadsImagesAutomatically();
@@ -25192,7 +25198,7 @@
method public synchronized void setGeolocationEnabled(boolean);
method public synchronized void setJavaScriptCanOpenWindowsAutomatically(boolean);
method public synchronized void setJavaScriptEnabled(boolean);
- method public deprecated synchronized void setLayoutAlgorithm(android.webkit.WebSettings.LayoutAlgorithm);
+ method public synchronized void setLayoutAlgorithm(android.webkit.WebSettings.LayoutAlgorithm);
method public void setLightTouchEnabled(boolean);
method public void setLoadWithOverviewMode(boolean);
method public synchronized void setLoadsImagesAutomatically(boolean);
@@ -25227,12 +25233,12 @@
field public static final int LOAD_NO_CACHE = 2; // 0x2
}
- public static final deprecated class WebSettings.LayoutAlgorithm extends java.lang.Enum {
+ public static final class WebSettings.LayoutAlgorithm extends java.lang.Enum {
method public static android.webkit.WebSettings.LayoutAlgorithm valueOf(java.lang.String);
method public static final android.webkit.WebSettings.LayoutAlgorithm[] values();
enum_constant public static final android.webkit.WebSettings.LayoutAlgorithm NARROW_COLUMNS;
enum_constant public static final android.webkit.WebSettings.LayoutAlgorithm NORMAL;
- enum_constant public static final android.webkit.WebSettings.LayoutAlgorithm SINGLE_COLUMN;
+ enum_constant public static final deprecated android.webkit.WebSettings.LayoutAlgorithm SINGLE_COLUMN;
}
public static final class WebSettings.PluginState extends java.lang.Enum {
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 9eab2fc..395c28b 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -151,8 +151,7 @@
"su", "root", "wlutil", "counters", NULL);
#endif
-#ifdef BROKEN_VRIL_IS_FIXED_B_4442803
- char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
+ char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
if (0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1)) {
@@ -166,7 +165,6 @@
"su", "root", "vril-dump", NULL);
}
}
-#endif
print_properties();
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index ea5c3db..d971652 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -533,6 +533,7 @@
* @hide
*/
public ParcelUuid[] getUuids() {
+ if (getState() != STATE_ON) return null;
try {
return mService.getUuids();
} catch (RemoteException e) {Log.e(TAG, "", e);}
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index c2a757f..7ca6155 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -22,12 +22,9 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
-import android.media.AudioManager;
-import android.media.MediaPlayer;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.os.SystemProperties;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
@@ -157,7 +154,6 @@
private boolean mOneShot;
private boolean mWithBuffer;
private boolean mFaceDetectionRunning = false;
- private boolean mReleased = false;
/**
* Broadcast Action: A new picture is taken by the camera, and the entry of
@@ -322,15 +318,6 @@
public final void release() {
native_release();
mFaceDetectionRunning = false;
- if (mCameraSoundPlayers != null) {
- for (CameraSoundPlayer csp: mCameraSoundPlayers) {
- if (csp != null) {
- csp.release();
- }
- }
- mCameraSoundPlayers = null;
- }
- mReleased = true;
}
/**
@@ -2512,13 +2499,16 @@
/**
* Sets the white balance. Changing the setting will release the
- * auto-white balance lock.
+ * auto-white balance lock. It is recommended not to change white
+ * balance and AWB lock at the same time.
*
* @param value new white balance.
* @see #getWhiteBalance()
* @see #setAutoWhiteBalanceLock(boolean)
*/
public void setWhiteBalance(String value) {
+ String oldValue = get(KEY_WHITE_BALANCE);
+ if (same(value, oldValue)) return;
set(KEY_WHITE_BALANCE, value);
set(KEY_AUTO_WHITEBALANCE_LOCK, FALSE);
}
@@ -3493,195 +3483,11 @@
return result;
}
+
+ private boolean same(String s1, String s2) {
+ if (s1 == null && s2 == null) return true;
+ if (s1 != null && s1.equals(s2)) return true;
+ return false;
+ }
};
-
- /**
- * <p>The set of default system sounds for camera actions. Use this with
- * {@link #playSound} to play an appropriate sound when implementing a
- * custom still or video recording mechanism through the preview
- * callbacks.</p>
- *
- * <p>There is no need to play sounds when using {@link #takePicture} or
- * {@link android.media.MediaRecorder} for still images or video,
- * respectively, as these play their own sounds when needed.</p>
- *
- * @see #playSound
- * @hide
- */
- public static class Sound {
- /**
- * The sound used by {@link android.hardware.Camera#takePicture} to
- * indicate still image capture.
- */
- public static final int SHUTTER_CLICK = 0;
-
- /**
- * A sound to indicate that focusing has completed. Because deciding
- * when this occurs is application-dependent, this sound is not used by
- * any methods in the Camera class.
- */
- public static final int FOCUS_COMPLETE = 1;
-
- /**
- * The sound used by {@link android.media.MediaRecorder#start} to
- * indicate the start of video recording.
- */
- public static final int START_VIDEO_RECORDING = 2;
-
- /**
- * The sound used by {@link android.media.MediaRecorder#stop} to
- * indicate the end of video recording.
- */
- public static final int STOP_VIDEO_RECORDING = 3;
-
- private static final int NUM_SOUNDS = 4;
- };
-
- /**
- * <p>Play one of the predefined platform sounds for camera actions.</p>
- *
- * <p>Use this method to play a platform-specific sound for various camera
- * actions. The sound playing is done asynchronously, with the same behavior
- * and content as the sounds played by {@link #takePicture takePicture},
- * {@link android.media.MediaRecorder#start MediaRecorder.start}, and
- * {@link android.media.MediaRecorder#stop MediaRecorder.stop}.</p>
- *
- * <p>Using this method makes it easy to match the default device sounds
- * when recording or capturing data through the preview callbacks
- * ({@link #setPreviewCallback setPreviewCallback},
- * {@link #setPreviewTexture setPreviewTexture}).</p>
- *
- * @param soundId The type of sound to play, selected from the options in
- * {@link android.hardware.Camera.Sound}
- * @see android.hardware.Camera.Sound
- * @see #takePicture
- * @see android.media.MediaRecorder
- * @hide
- */
- public void playSound(int soundId) {
- if (mReleased) return;
- if (mCameraSoundPlayers == null) {
- mCameraSoundPlayers = new CameraSoundPlayer[Sound.NUM_SOUNDS];
- }
- if (mCameraSoundPlayers[soundId] == null) {
- mCameraSoundPlayers[soundId] = new CameraSoundPlayer(soundId);
- }
- mCameraSoundPlayers[soundId].play();
- }
-
- private CameraSoundPlayer[] mCameraSoundPlayers;
-
- private static class CameraSoundPlayer implements Runnable {
- private int mSoundId;
- private int mAudioStreamType;
- private MediaPlayer mPlayer;
- private Thread mThread;
- private boolean mExit;
- private int mPlayCount;
-
- private static final String mShutterSound =
- "/system/media/audio/ui/camera_click.ogg";
- private static final String mFocusSound =
- "/system/media/audio/ui/camera_focus.ogg";
- private static final String mVideoStartSound =
- "/system/media/audio/ui/VideoRecord.ogg";
- private static final String mVideoStopSound =
- "/system/media/audio/ui/VideoRecord.ogg";
-
- @Override
- public void run() {
- String soundFilePath;
- switch (mSoundId) {
- case Sound.SHUTTER_CLICK:
- soundFilePath = mShutterSound;
- break;
- case Sound.FOCUS_COMPLETE:
- soundFilePath = mFocusSound;
- break;
- case Sound.START_VIDEO_RECORDING:
- soundFilePath = mVideoStartSound;
- break;
- case Sound.STOP_VIDEO_RECORDING:
- soundFilePath = mVideoStopSound;
- break;
- default:
- Log.e(TAG, "Unknown sound " + mSoundId + " requested.");
- return;
- }
- mPlayer = new MediaPlayer();
- try {
- mPlayer.setAudioStreamType(mAudioStreamType);
- mPlayer.setDataSource(soundFilePath);
- mPlayer.setLooping(false);
- mPlayer.prepare();
- } catch(IOException e) {
- Log.e(TAG, "Error setting up sound " + mSoundId, e);
- return;
- }
-
- while(true) {
- try {
- synchronized (this) {
- while(true) {
- if (mExit) {
- return;
- } else if (mPlayCount <= 0) {
- wait();
- } else {
- mPlayCount--;
- break;
- }
- }
- }
- mPlayer.start();
- } catch (Exception e) {
- Log.e(TAG, "Error playing sound " + mSoundId, e);
- }
- }
- }
-
- public CameraSoundPlayer(int soundId) {
- mSoundId = soundId;
- if (SystemProperties.get("ro.camera.sound.forced", "0").equals("0")) {
- mAudioStreamType = AudioManager.STREAM_MUSIC;
- } else {
- mAudioStreamType = AudioManager.STREAM_SYSTEM_ENFORCED;
- }
- }
-
- public void play() {
- if (mThread == null) {
- mThread = new Thread(this);
- mThread.start();
- }
- synchronized (this) {
- mPlayCount++;
- notifyAll();
- }
- }
-
- public void release() {
- if (mThread != null) {
- synchronized (this) {
- mExit = true;
- notifyAll();
- }
- try {
- mThread.join();
- } catch (InterruptedException e) {
- }
- mThread = null;
- }
- if (mPlayer != null) {
- mPlayer.release();
- mPlayer = null;
- }
- }
-
- @Override
- protected void finalize() {
- release();
- }
- }
-
}
diff --git a/core/java/android/hardware/CameraSound.java b/core/java/android/hardware/CameraSound.java
new file mode 100644
index 0000000..32de0cd
--- /dev/null
+++ b/core/java/android/hardware/CameraSound.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2011 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.media.AudioManager;
+import android.media.MediaPlayer;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import java.io.IOException;
+
+/**
+ * <p>Use this class to play an appropriate sound when implementing a custom
+ * still or video recording mechanism through the preview callbacks.</p>
+ *
+ * <p>There is no need to play sounds when using {@link #android.hardware.Camera#takePicture}
+ * or {@link android.media.MediaRecorder} for still images or video,
+ * respectively, as these play their own sounds when needed.</p>
+ *
+ * @hide
+ */
+public class CameraSound {
+ private static final String TAG = "CameraSound";
+ /**
+ * The sound used by {@link android.hardware.Camera#takePicture} to
+ * indicate still image capture.
+ */
+ public static final int SHUTTER_CLICK = 0;
+
+ /**
+ * A sound to indicate that focusing has completed. Because deciding
+ * when this occurs is application-dependent, this sound is not used by
+ * any methods in the Camera class.
+ */
+ public static final int FOCUS_COMPLETE = 1;
+
+ /**
+ * The sound used by {@link android.media.MediaRecorder#start} to
+ * indicate the start of video recording.
+ */
+ public static final int START_VIDEO_RECORDING = 2;
+
+ /**
+ * The sound used by {@link android.media.MediaRecorder#stop} to
+ * indicate the end of video recording.
+ */
+ public static final int STOP_VIDEO_RECORDING = 3;
+
+ private static final int NUM_SOUNDS = 4;
+ private CameraSoundPlayer[] mCameraSoundPlayers;
+
+ public CameraSound() {
+ }
+
+ /**
+ * <p>Play one of the predefined platform sounds for camera actions.</p>
+ *
+ * <p>Use this method to play a platform-specific sound for various camera
+ * actions. The sound playing is done asynchronously, with the same behavior
+ * and content as the sounds played by {@link #takePicture takePicture},
+ * {@link android.media.MediaRecorder#start MediaRecorder.start}, and
+ * {@link android.media.MediaRecorder#stop MediaRecorder.stop}.</p>
+ *
+ * <p>Using this method makes it easy to match the default device sounds
+ * when recording or capturing data through the preview callbacks.</p>
+ *
+ * @param soundId The type of sound to play, selected from SHUTTER_CLICK,
+ * FOCUS_COMPLETE, START_VIDEO_RECORDING, or STOP_VIDEO_RECORDING.
+ * @see android.hardware#takePicture
+ * @see android.media.MediaRecorder
+ * @see #SHUTTER_CLICK
+ * @see #FOCUS_COMPLETE
+ * @see #START_VIDEO_RECORDING
+ * @see #STOP_VIDEO_RECORDING
+ */
+ public void playSound(int soundId) {
+ if (mCameraSoundPlayers == null) {
+ mCameraSoundPlayers = new CameraSoundPlayer[NUM_SOUNDS];
+ }
+ if (mCameraSoundPlayers[soundId] == null) {
+ mCameraSoundPlayers[soundId] = new CameraSoundPlayer(soundId);
+ }
+ mCameraSoundPlayers[soundId].play();
+ }
+
+ public void release() {
+ if (mCameraSoundPlayers != null) {
+ for (CameraSoundPlayer csp: mCameraSoundPlayers) {
+ if (csp != null) {
+ csp.release();
+ }
+ }
+ mCameraSoundPlayers = null;
+ }
+ }
+
+ private static class CameraSoundPlayer implements Runnable {
+ private int mSoundId;
+ private int mAudioStreamType;
+ private MediaPlayer mPlayer;
+ private Thread mThread;
+ private boolean mExit;
+ private int mPlayCount;
+
+ private static final String mShutterSound =
+ "/system/media/audio/ui/camera_click.ogg";
+ private static final String mFocusSound =
+ "/system/media/audio/ui/camera_focus.ogg";
+ private static final String mVideoStartSound =
+ "/system/media/audio/ui/VideoRecord.ogg";
+ private static final String mVideoStopSound =
+ "/system/media/audio/ui/VideoRecord.ogg";
+
+ @Override
+ public void run() {
+ String soundFilePath;
+ switch (mSoundId) {
+ case SHUTTER_CLICK:
+ soundFilePath = mShutterSound;
+ break;
+ case FOCUS_COMPLETE:
+ soundFilePath = mFocusSound;
+ break;
+ case START_VIDEO_RECORDING:
+ soundFilePath = mVideoStartSound;
+ break;
+ case STOP_VIDEO_RECORDING:
+ soundFilePath = mVideoStopSound;
+ break;
+ default:
+ Log.e(TAG, "Unknown sound " + mSoundId + " requested.");
+ return;
+ }
+ mPlayer = new MediaPlayer();
+ try {
+ mPlayer.setAudioStreamType(mAudioStreamType);
+ mPlayer.setDataSource(soundFilePath);
+ mPlayer.setLooping(false);
+ mPlayer.prepare();
+ } catch(IOException e) {
+ Log.e(TAG, "Error setting up sound " + mSoundId, e);
+ return;
+ }
+
+ while(true) {
+ try {
+ synchronized (this) {
+ while(true) {
+ if (mExit) {
+ return;
+ } else if (mPlayCount <= 0) {
+ wait();
+ } else {
+ mPlayCount--;
+ break;
+ }
+ }
+ }
+ mPlayer.start();
+ } catch (Exception e) {
+ Log.e(TAG, "Error playing sound " + mSoundId, e);
+ }
+ }
+ }
+
+ public CameraSoundPlayer(int soundId) {
+ mSoundId = soundId;
+ if (SystemProperties.get("ro.camera.sound.forced", "0").equals("0")) {
+ mAudioStreamType = AudioManager.STREAM_MUSIC;
+ } else {
+ mAudioStreamType = AudioManager.STREAM_SYSTEM_ENFORCED;
+ }
+ }
+
+ public void play() {
+ if (mThread == null) {
+ mThread = new Thread(this);
+ mThread.start();
+ }
+ synchronized (this) {
+ mPlayCount++;
+ notifyAll();
+ }
+ }
+
+ public void release() {
+ if (mThread != null) {
+ synchronized (this) {
+ mExit = true;
+ notifyAll();
+ }
+ try {
+ mThread.join();
+ } catch (InterruptedException e) {
+ }
+ mThread = null;
+ }
+ if (mPlayer != null) {
+ mPlayer.release();
+ mPlayer = null;
+ }
+ }
+
+ @Override
+ protected void finalize() {
+ release();
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index a9f1685..2857ac5 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -360,6 +360,10 @@
/* use getSystemService() instead of just instantiating to take
* advantage of the context's cached NfcManager & NfcAdapter */
NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);
+ if (manager == null) {
+ // NFC not available
+ return null;
+ }
return manager.getDefaultAdapter();
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 3362575..e1bc275 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -101,7 +101,7 @@
* Defines the UID/GID for the NFC service process.
* @hide
*/
- public static final int NFC_UID = 1025;
+ public static final int NFC_UID = 1027;
/**
* Defines the GID for the group that allows write access to the internal media storage.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b032169..ee3215c 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4020,21 +4020,26 @@
"setup_prepaid_detection_redir_host";
/**
- * The user's preferred "dream" (interactive screensaver) component.
- *
- * This component will be launched by the PhoneWindowManager after the user's chosen idle
- * timeout (specified by {@link #DREAM_TIMEOUT}).
+ * Whether the screensaver is enabled.
* @hide
*/
- public static final String DREAM_COMPONENT =
- "dream_component";
+ public static final String SCREENSAVER_ENABLED = "screensaver_enabled";
/**
- * The delay before a "dream" is started (set to 0 to disable).
+ * The user's chosen screensaver component.
+ *
+ * This component will be launched by the PhoneWindowManager after a timeout when not on
+ * battery, or upon dock insertion (if SCREENSAVER_ACTIVATE_ON_DOCK is set to 1).
* @hide
*/
- public static final String DREAM_TIMEOUT =
- "dream_timeout";
+ public static final String SCREENSAVER_COMPONENT = "screensaver_component";
+
+ /**
+ * Whether the screensaver should be automatically launched when the device is inserted
+ * into a (desk) dock.
+ * @hide
+ */
+ public static final String SCREENSAVER_ACTIVATE_ON_DOCK = "screensaver_activate_on_dock";
/** {@hide} */
public static final String NETSTATS_ENABLED = "netstats_enabled";
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index aa62cd7..a2038c9 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -784,12 +784,12 @@
// machine. We don't handle AVCTP signals currently. We only send
// intents for AVDTP state changes. We need to handle both of them in
// some cases. For now, just don't move to incoming state in this case.
- mBluetoothService.notifyIncomingA2dpConnection(address, true);
+ mBluetoothService.notifyIncomingA2dpConnection(address, false);
} else {
Log.i(TAG, "" + authorized +
"Incoming A2DP / AVRCP connection from " + address);
mA2dp.allowIncomingConnect(device, authorized);
- mBluetoothService.notifyIncomingA2dpConnection(address, false);
+ mBluetoothService.notifyIncomingA2dpConnection(address, true);
}
} else if (BluetoothUuid.isInputDevice(uuid)) {
// We can have more than 1 input device connected.
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index d604a01..28e231e 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -810,7 +810,7 @@
}
}
- /*package*/ synchronized String getProperty(String name, boolean checkState) {
+ /*package*/ String getProperty(String name, boolean checkState) {
// If checkState is false, check if the event loop is running.
// before making the call to Bluez
if (checkState) {
@@ -854,14 +854,14 @@
return getProperty("Name", false);
}
- public synchronized ParcelUuid[] getUuids() {
+ public ParcelUuid[] getUuids() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
String value = getProperty("UUIDs", true);
if (value == null) return null;
return convertStringToParcelUuid(value);
}
- private synchronized ParcelUuid[] convertStringToParcelUuid(String value) {
+ private ParcelUuid[] convertStringToParcelUuid(String value) {
String[] uuidStrings = null;
// The UUIDs are stored as a "," separated string.
uuidStrings = value.split(",");
@@ -934,7 +934,7 @@
* @return The discoverability window of the device, in seconds. A negative
* value indicates an error.
*/
- public synchronized int getDiscoverableTimeout() {
+ public int getDiscoverableTimeout() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
String timeout = getProperty("DiscoverableTimeout", true);
if (timeout != null)
@@ -943,7 +943,7 @@
return -1;
}
- public synchronized int getScanMode() {
+ public int getScanMode() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
if (!isEnabledInternal())
return BluetoothAdapter.SCAN_MODE_NONE;
@@ -969,7 +969,7 @@
return stopDiscoveryNative();
}
- public synchronized boolean isDiscovering() {
+ public boolean isDiscovering() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
String discoveringProperty = getProperty("Discovering", false);
@@ -2387,7 +2387,7 @@
mDeviceProfileState.remove(address);
}
- synchronized String[] getKnownDevices() {
+ String[] getKnownDevices() {
String[] bonds = null;
String val = getProperty("Devices", true);
if (val != null) {
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index 353b628..7f8af7a 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -1415,7 +1415,7 @@
}
}
- if (noMonthDay && startMonthNum == endMonthNum) {
+ if (noMonthDay && startMonthNum == endMonthNum && startYear == endYear) {
// Example: "January, 2008"
return formatter.format("%s", startDate.format(defaultDateFormat));
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index e0167d8..f77cf7e 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -22,6 +22,9 @@
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.opengl.GLUtils;
+import android.opengl.ManagedEGLContext;
+import android.os.Handler;
+import android.os.Looper;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.Log;
@@ -159,13 +162,21 @@
abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException;
/**
- * Destoys the layers used by the specified view hierarchy.
+ * Destroys the layers used by the specified view hierarchy.
*
* @param view The root of the view hierarchy
*/
abstract void destroyLayers(View view);
/**
+ * Destroys all hardware rendering resources associated with the specified
+ * view hierarchy.
+ *
+ * @param view The root of the view hierarchy
+ */
+ abstract void destroyHardwareResources(View view);
+
+ /**
* This method should be invoked whenever the current hardware renderer
* context should be reset.
*
@@ -345,15 +356,6 @@
}
/**
- * Invoke this method when the system needs to clean up all resources
- * associated with hardware rendering.
- */
- static void terminate() {
- Log.d(LOG_TAG, "Terminating hardware rendering");
- Gl20Renderer.terminate();
- }
-
- /**
* Indicates whether hardware acceleration is currently enabled.
*
* @return True if hardware acceleration is in use, false otherwise.
@@ -409,7 +411,8 @@
static final Object[] sEglLock = new Object[0];
int mWidth = -1, mHeight = -1;
- static final ThreadLocal<EGLContext> sEglContextStorage = new ThreadLocal<EGLContext>();
+ static final ThreadLocal<Gl20Renderer.Gl20RendererEglContext> sEglContextStorage
+ = new ThreadLocal<Gl20Renderer.Gl20RendererEglContext>();
EGLContext mEglContext;
Thread mEglThread;
@@ -561,12 +564,13 @@
}
}
- mEglContext = sEglContextStorage.get();
+ Gl20Renderer.Gl20RendererEglContext managedContext = sEglContextStorage.get();
+ mEglContext = managedContext != null ? managedContext.getContext() : null;
mEglThread = Thread.currentThread();
if (mEglContext == null) {
mEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
- sEglContextStorage.set(mEglContext);
+ sEglContextStorage.set(new Gl20Renderer.Gl20RendererEglContext(mEglContext));
}
}
@@ -904,6 +908,52 @@
private static EGLSurface sPbuffer;
private static final Object[] sPbufferLock = new Object[0];
+ static class Gl20RendererEglContext extends ManagedEGLContext {
+ final Handler mHandler = new Handler();
+
+ public Gl20RendererEglContext(EGLContext context) {
+ super(context);
+ }
+
+ @Override
+ public void onTerminate(final EGLContext eglContext) {
+ // Make sure we do this on the correct thread.
+ if (mHandler.getLooper() != Looper.myLooper()) {
+ mHandler.post(new Runnable() {
+ @Override public void run() {
+ onTerminate(eglContext);
+ }
+ });
+ return;
+ }
+
+ synchronized (sEglLock) {
+ if (sEgl == null) return;
+
+ if (EGLImpl.getInitCount(sEglDisplay) == 1) {
+ usePbufferSurface(eglContext);
+ GLES20Canvas.terminateCaches();
+
+ sEgl.eglDestroyContext(sEglDisplay, eglContext);
+ sEglContextStorage.remove();
+
+ sEgl.eglDestroySurface(sEglDisplay, sPbuffer);
+ sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
+ EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+ sEgl.eglReleaseThread();
+ sEgl.eglTerminate(sEglDisplay);
+
+ sEgl = null;
+ sEglDisplay = null;
+ sEglConfig = null;
+ sPbuffer = null;
+ sEglContextStorage.set(null);
+ }
+ }
+ }
+ }
+
Gl20Renderer(boolean translucent) {
super(2, translucent);
}
@@ -996,10 +1046,9 @@
}
}
- private void destroyHardwareLayer(View view) {
- if (view.destroyLayer()) {
- view.invalidate(true);
- }
+ private static void destroyHardwareLayer(View view) {
+ view.destroyLayer();
+
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
@@ -1009,6 +1058,36 @@
}
}
}
+
+ @Override
+ void destroyHardwareResources(View view) {
+ if (view != null) {
+ boolean needsContext = true;
+ if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false;
+
+ if (needsContext) {
+ Gl20RendererEglContext managedContext = sEglContextStorage.get();
+ if (managedContext == null) return;
+ usePbufferSurface(managedContext.getContext());
+ }
+
+ destroyResources(view);
+ GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
+ }
+ }
+
+ private static void destroyResources(View view) {
+ view.destroyHardwareResources();
+
+ if (view instanceof ViewGroup) {
+ ViewGroup group = (ViewGroup) view;
+
+ int count = group.getChildCount();
+ for (int i = 0; i < count; i++) {
+ destroyResources(group.getChildAt(i));
+ }
+ }
+ }
static HardwareRenderer create(boolean translucent) {
if (GLES20Canvas.isAvailable()) {
@@ -1020,12 +1099,12 @@
static void trimMemory(int level) {
if (sEgl == null || sEglConfig == null) return;
- EGLContext eglContext = sEglContextStorage.get();
+ Gl20RendererEglContext managedContext = sEglContextStorage.get();
// We do not have OpenGL objects
- if (eglContext == null) {
+ if (managedContext == null) {
return;
} else {
- usePbufferSurface(eglContext);
+ usePbufferSurface(managedContext.getContext());
}
switch (level) {
@@ -1052,33 +1131,5 @@
}
sEgl.eglMakeCurrent(sEglDisplay, sPbuffer, sPbuffer, eglContext);
}
-
- static void terminate() {
- synchronized (sEglLock) {
- if (sEgl == null) return;
-
- if (EGLImpl.getInitCount(sEglDisplay) == 1) {
- EGLContext eglContext = sEglContextStorage.get();
- if (eglContext == null) return;
-
- usePbufferSurface(eglContext);
- GLES20Canvas.terminateCaches();
-
- sEgl.eglDestroyContext(sEglDisplay, eglContext);
- sEglContextStorage.remove();
-
- sEgl.eglDestroySurface(sEglDisplay, sPbuffer);
- sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-
- sEgl.eglReleaseThread();
- sEgl.eglTerminate(sEglDisplay);
-
- sEgl = null;
- sEglDisplay = null;
- sEglConfig = null;
- sPbuffer = null;
- }
- }
- }
}
}
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 1697382..74916f0 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -203,7 +203,10 @@
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
+ destroySurface();
+ }
+ private void destroySurface() {
if (mLayer != null) {
boolean shouldRelease = true;
if (mListener != null) {
@@ -300,6 +303,17 @@
return false;
}
+ /**
+ * @hide
+ */
+ @Override
+ protected void destroyHardwareResources() {
+ super.destroyHardwareResources();
+ destroySurface();
+ invalidateParentCaches();
+ invalidate(true);
+ }
+
@Override
HardwareLayer getHardwareLayer() {
if (mLayer == null) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index dc46d42..6a9f1e6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1487,7 +1487,8 @@
| AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
| AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
| AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
- | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED;
+ | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
+ | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED;
/**
* Temporary Rect currently for use in setBackground(). This will probably
@@ -10072,7 +10073,7 @@
switch (mLayerType) {
case LAYER_TYPE_HARDWARE:
destroyLayer();
- // fall through - unaccelerated views may use software layer mechanism instead
+ // fall through - non-accelerated views may use software layer mechanism instead
case LAYER_TYPE_SOFTWARE:
destroyDrawingCache();
break;
@@ -10139,7 +10140,11 @@
switch (mLayerType) {
case LAYER_TYPE_HARDWARE:
- getHardwareLayer();
+ if (mAttachInfo.mHardwareRenderer != null &&
+ mAttachInfo.mHardwareRenderer.isEnabled() &&
+ mAttachInfo.mHardwareRenderer.validate()) {
+ getHardwareLayer();
+ }
break;
case LAYER_TYPE_SOFTWARE:
buildDrawingCache(true);
@@ -10234,12 +10239,31 @@
if (mHardwareLayer != null) {
mHardwareLayer.destroy();
mHardwareLayer = null;
+
+ invalidate(true);
+ invalidateParentCaches();
+
return true;
}
return false;
}
/**
+ * Destroys all hardware rendering resources. This method is invoked
+ * when the system needs to reclaim resources. Upon execution of this
+ * method, you should free any OpenGL resources created by the view.
+ *
+ * Note: you <strong>must</strong> call
+ * <code>super.destroyHardwareResources()</code> when overriding
+ * this method.
+ *
+ * @hide
+ */
+ protected void destroyHardwareResources() {
+ destroyLayer();
+ }
+
+ /**
* <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
* to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
* bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index b15b155..5f70a39 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -576,6 +576,13 @@
}
}
+ void terminateHardwareResources() {
+ if (mAttachInfo.mHardwareRenderer != null) {
+ mAttachInfo.mHardwareRenderer.destroyHardwareResources(mView);
+ mAttachInfo.mHardwareRenderer.destroy(false);
+ }
+ }
+
void destroyHardwareLayers() {
if (mThread != Thread.currentThread()) {
if (mAttachInfo.mHardwareRenderer != null &&
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index d89bc36..dfd1d55 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -21,6 +21,7 @@
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
+import android.opengl.ManagedEGLContext;
import android.os.IBinder;
import android.util.AndroidRuntimeException;
import android.util.Log;
@@ -424,11 +425,11 @@
if (mViews == null) return;
int count = mViews.length;
for (int i = 0; i < count; i++) {
- mRoots[i].destroyHardwareResources();
+ mRoots[i].terminateHardwareResources();
}
}
// Terminate the hardware renderer to free all resources
- HardwareRenderer.terminate();
+ ManagedEGLContext.doTerminate();
break;
}
// high end gfx devices fall through to next case
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 86dd9df..7bf0c83 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -220,15 +220,6 @@
* <li>{@link #isEnabled()} - Whether the source is enabled.</li>
* <li>{@link #getContentDescription()} - The content description of the source.</li>
* </ul>
- * <em>Note:</em> This event type is not dispatched to descendants though
- * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
- * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
- * source {@link android.view.View} and the sub-tree rooted at it will not receive
- * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
- * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
- * text content to such events is by setting the
- * {@link android.R.styleable#View_contentDescription contentDescription} of the source
- * view.</br>
* </p>
* <p>
* <b>View scrolled</b> - represents the event of scrolling a view. If
diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java
index 0eb6e27..489587e 100644
--- a/core/java/android/view/textservice/SpellCheckerSession.java
+++ b/core/java/android/view/textservice/SpellCheckerSession.java
@@ -201,7 +201,7 @@
private static final int TASK_CLOSE = 3;
private final Queue<SpellCheckerParams> mPendingTasks =
new LinkedList<SpellCheckerParams>();
- private final Handler mHandler;
+ private Handler mHandler;
private boolean mOpened;
private ISpellCheckerSession mISpellCheckerSession;
@@ -334,6 +334,7 @@
try {
mISpellCheckerSession.onClose();
mISpellCheckerSession = null;
+ mHandler = null;
} catch (RemoteException e) {
Log.e(TAG, "Failed to close " + e);
}
diff --git a/core/java/android/webkit/HTML5VideoFullScreen.java b/core/java/android/webkit/HTML5VideoFullScreen.java
index f29aff2..cb555ea 100644
--- a/core/java/android/webkit/HTML5VideoFullScreen.java
+++ b/core/java/android/webkit/HTML5VideoFullScreen.java
@@ -261,6 +261,8 @@
mLayout.addView(getSurfaceView(), layoutParams);
mLayout.setVisibility(View.VISIBLE);
+ mLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
+ | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
WebChromeClient client = webView.getWebChromeClient();
if (client != null) {
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index f240a2e..f947f95 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -42,12 +42,14 @@
* SINGLE_COLUMN moves all content into one column that is the width of the
* view.
* NARROW_COLUMNS makes all columns no wider than the screen if possible.
- * @deprecated This enum is now obsolete.
*/
// XXX: These must match LayoutAlgorithm in Settings.h in WebCore.
- @Deprecated
public enum LayoutAlgorithm {
NORMAL,
+ /**
+ * @deprecated This algorithm is now obsolete.
+ */
+ @Deprecated
SINGLE_COLUMN,
NARROW_COLUMNS
}
@@ -799,7 +801,7 @@
public void setDefaultZoom(ZoomDensity zoom) {
if (mDefaultZoom != zoom) {
mDefaultZoom = zoom;
- mWebView.updateDefaultZoomDensity(zoom.value);
+ mWebView.adjustDefaultZoomDensity(zoom.value);
}
}
@@ -936,9 +938,7 @@
* WebView.
* @param l A LayoutAlgorithm enum specifying the algorithm to use.
* @see WebSettings.LayoutAlgorithm
- * @deprecated This method is now obsolete.
*/
- @Deprecated
public synchronized void setLayoutAlgorithm(LayoutAlgorithm l) {
// XXX: This will only be affective if libwebcore was built with
// ANDROID_LAYOUT defined.
@@ -953,9 +953,7 @@
* @return LayoutAlgorithm enum value describing the layout algorithm
* being used.
* @see WebSettings.LayoutAlgorithm
- * @deprecated This method is now obsolete.
*/
- @Deprecated
public synchronized LayoutAlgorithm getLayoutAlgorithm() {
return mLayoutAlgorithm;
}
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 8aafc3d..f18a396 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -17,8 +17,10 @@
package android.webkit;
import android.content.Context;
+import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
+import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
@@ -49,6 +51,7 @@
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
+import android.widget.AbsoluteLayout;
import android.widget.AbsoluteLayout.LayoutParams;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
@@ -71,6 +74,9 @@
static final String LOGTAG = "webtextview";
+ private Paint mRingPaint;
+ private int mRingInset;
+
private WebView mWebView;
private boolean mSingle;
private int mWidthSpec;
@@ -201,7 +207,13 @@
}
}
};
+ float ringWidth = 4f * context.getResources().getDisplayMetrics().density;
mReceiver = new MyResultReceiver(mHandler);
+ mRingPaint = new Paint();
+ mRingPaint.setColor(0x6633b5e5);
+ mRingPaint.setStrokeWidth(ringWidth);
+ mRingPaint.setStyle(Style.FILL);
+ mRingInset = (int) ringWidth;
}
public void setAutoFillable(int queryId) {
@@ -211,6 +223,40 @@
}
@Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ if (isFocused()) {
+ final int ib = getHeight() - mRingInset;
+ canvas.drawRect(0, 0, getWidth(), mRingInset, mRingPaint);
+ canvas.drawRect(0, ib, getWidth(), getHeight(), mRingPaint);
+ canvas.drawRect(0, mRingInset, mRingInset, ib, mRingPaint);
+ canvas.drawRect(getWidth() - mRingInset, mRingInset, getWidth(), ib, mRingPaint);
+ }
+ }
+
+ private void growOrShrink(boolean grow) {
+ AbsoluteLayout.LayoutParams lp = (AbsoluteLayout.LayoutParams) getLayoutParams();
+ if (grow) {
+ Log.i("webtextview", "grow");
+ lp.x -= mRingInset;
+ lp.y -= mRingInset;
+ lp.width += 2 * mRingInset;
+ lp.height += 2 * mRingInset;
+ setPadding(getPaddingLeft() + mRingInset, getPaddingTop() + mRingInset,
+ getPaddingRight() + mRingInset, getPaddingBottom() + mRingInset);
+ } else {
+ Log.i("webtextview", "shrink");
+ lp.x += mRingInset;
+ lp.y += mRingInset;
+ lp.width -= 2 * mRingInset;
+ lp.height -= 2 * mRingInset;
+ setPadding(getPaddingLeft() - mRingInset, getPaddingTop() - mRingInset,
+ getPaddingRight() - mRingInset, getPaddingBottom() - mRingInset);
+ }
+ setLayoutParams(lp);
+ }
+
+ @Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.isSystem()) {
return super.dispatchKeyEvent(event);
@@ -511,6 +557,7 @@
} else if (!mInsideRemove) {
mWebView.setActive(false);
}
+ growOrShrink(focused);
mFromFocusChange = false;
}
@@ -567,7 +614,6 @@
mPreChange.substring(0, mMaxLength).equals(postChange))) {
return;
}
- mPreChange = postChange;
if (0 == count) {
if (before > 0) {
// For this and all changes to the text, update our cache
@@ -605,9 +651,9 @@
// Prefer sending javascript events, so when adding one character,
// don't replace the unchanged text.
if (count > 1 && before == count - 1) {
- String replaceButOne = s.subSequence(start,
+ String replaceButOne = mPreChange.subSequence(start,
start + before).toString();
- String replacedString = getText().subSequence(start,
+ String replacedString = s.subSequence(start,
start + before).toString();
if (replaceButOne.equals(replacedString)) {
// we're just adding one character
@@ -616,6 +662,7 @@
count = 1;
}
}
+ mPreChange = postChange;
// Find the last character being replaced. If it can be represented by
// events, we will pass them to native so we can see javascript events.
// Otherwise, replace the text being changed in the textfield.
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index ec2f55b..877c9ea 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -17,6 +17,7 @@
package android.webkit;
import android.annotation.Widget;
+import android.app.ActivityManager;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.ClipboardManager;
@@ -61,6 +62,7 @@
import android.util.AttributeSet;
import android.util.EventLog;
import android.util.Log;
+import android.view.Display;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.HardwareCanvas;
@@ -77,6 +79,7 @@
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
+import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -119,6 +122,11 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import static javax.microedition.khronos.egl.EGL10.*;
+
/**
* <p>A View that displays web pages. This class is the basis upon which you
* can roll your own web browser or simply display some online content within your Activity.
@@ -361,6 +369,7 @@
private final Rect mGLRectViewport = new Rect();
private final Rect mViewRectViewport = new Rect();
+ private final RectF mVisibleContentRect = new RectF();
private boolean mGLViewportEmpty = false;
/**
@@ -733,6 +742,7 @@
static final int SCREEN_ON = 136;
static final int ENTER_FULLSCREEN_VIDEO = 137;
static final int UPDATE_SELECTION = 138;
+ static final int UPDATE_ZOOM_DENSITY = 139;
private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID;
private static final int LAST_PACKAGE_MSG_ID = SET_TOUCH_HIGHLIGHT_RECTS;
@@ -788,7 +798,9 @@
"AUTOFILL_COMPLETE", // = 134;
"SELECT_AT", // = 135;
"SCREEN_ON", // = 136;
- "ENTER_FULLSCREEN_VIDEO" // = 137;
+ "ENTER_FULLSCREEN_VIDEO", // = 137;
+ "UPDATE_SELECTION", // = 138;
+ "UPDATE_ZOOM_DENSITY" // = 139;
};
// If the site doesn't use the viewport meta tag to specify the viewport,
@@ -909,6 +921,9 @@
private Rect mScrollingLayerBounds = new Rect();
private boolean mSentAutoScrollMessage = false;
+ // Temporary hack to work around the context removal upon memory pressure
+ private static boolean mIncrementEGLContextHack = false;
+
// used for serializing asynchronously handled touch events.
private final TouchEventQueue mTouchEventQueue = new TouchEventQueue();
@@ -927,7 +942,11 @@
* Notify the listener that the picture has changed.
* @param view The WebView that owns the picture.
* @param picture The new picture.
- * @deprecated This method is now obsolete.
+ * @deprecated Due to internal changes, the picture does not include
+ * composited layers such as fixed position elements or scrollable divs.
+ * While the PictureListener API can still be used to detect changes in
+ * the WebView content, you are advised against its usage until a replacement
+ * is provided in a future Android release
*/
@Deprecated
public void onNewPicture(WebView view, Picture picture);
@@ -1341,9 +1360,13 @@
}
}
- /* package */void updateDefaultZoomDensity(int zoomDensity) {
+ /* package */ void adjustDefaultZoomDensity(int zoomDensity) {
final float density = mContext.getResources().getDisplayMetrics().density
* 100 / zoomDensity;
+ updateDefaultZoomDensity(density);
+ }
+
+ /* package */ void updateDefaultZoomDensity(float density) {
mNavSlop = (int) (16 * density);
mZoomManager.updateDefaultZoomDensity(density);
}
@@ -2469,7 +2492,9 @@
* Set the initial scale for the WebView. 0 means default. If
* {@link WebSettings#getUseWideViewPort()} is true, it zooms out all the
* way. Otherwise it starts with 100%. If initial scale is greater than 0,
- * WebView starts will this value as initial scale.
+ * WebView starts with this value as initial scale.
+ * Please note that unlike the scale properties in the viewport meta tag,
+ * this method doesn't take the screen density into account.
*
* @param scaleInPercent The initial scale in percent.
*/
@@ -4219,6 +4244,13 @@
}
if (canvas.isHardwareAccelerated()) {
+ if (mIncrementEGLContextHack == false) {
+ mIncrementEGLContextHack = true;
+ EGL10 egl = (EGL10) EGLContext.getEGL();
+ EGLDisplay eglDisplay = egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ int[] version = new int[2];
+ egl.eglInitialize(eglDisplay, version);
+ }
mZoomManager.setHardwareAccelerated();
}
@@ -4586,11 +4618,14 @@
+ " extras=" + extras);
}
+ calcOurContentVisibleRectF(mVisibleContentRect);
if (canvas.isHardwareAccelerated()) {
- int functor = nativeGetDrawGLFunction(mNativeClass,
- mGLViewportEmpty ? null : mGLRectViewport, mGLViewportEmpty ? null : mViewRectViewport, getScale(), extras);
- ((HardwareCanvas) canvas).callDrawGLFunction(functor);
+ Rect glRectViewport = mGLViewportEmpty ? null : mGLRectViewport;
+ Rect viewRectViewport = mGLViewportEmpty ? null : mViewRectViewport;
+ int functor = nativeGetDrawGLFunction(mNativeClass, glRectViewport,
+ viewRectViewport, mVisibleContentRect, getScale(), extras);
+ ((HardwareCanvas) canvas).callDrawGLFunction(functor);
if (mHardwareAccelSkia != getSettings().getHardwareAccelSkiaEnabled()) {
mHardwareAccelSkia = getSettings().getHardwareAccelSkiaEnabled();
nativeUseHardwareAccelSkia(mHardwareAccelSkia);
@@ -4606,7 +4641,8 @@
canvas.setDrawFilter(df);
// XXX: Revisit splitting content. Right now it causes a
// synchronization problem with layers.
- int content = nativeDraw(canvas, color, extras, false);
+ int content = nativeDraw(canvas, mVisibleContentRect, color,
+ extras, false);
canvas.setDrawFilter(null);
if (!mBlockWebkitViewMessages && content != 0) {
mWebViewCore.sendMessage(EventHub.SPLIT_PICTURE_SET, content, 0);
@@ -5658,13 +5694,13 @@
if (hasFocus()) {
// If our window regained focus, and we have focus, then begin
// drawing the cursor ring
- mDrawCursorRing = true;
+ mDrawCursorRing = !inEditingMode();
setFocusControllerActive(true);
} else {
+ mDrawCursorRing = false;
if (!inEditingMode()) {
// If our window gained focus, but we do not have it, do not
// draw the cursor ring.
- mDrawCursorRing = false;
setFocusControllerActive(false);
}
// We do not call recordButtons here because we assume
@@ -5739,7 +5775,7 @@
// When we regain focus, if we have window focus, resume drawing
// the cursor ring
if (hasWindowFocus()) {
- mDrawCursorRing = true;
+ mDrawCursorRing = !inEditingMode();
setFocusControllerActive(true);
//} else {
// The WebView has gained focus while we do not have
@@ -5749,8 +5785,8 @@
} else {
// When we lost focus, unless focus went to the TextView (which is
// true if we are in editing mode), stop drawing the cursor ring.
+ mDrawCursorRing = false;
if (!inEditingMode()) {
- mDrawCursorRing = false;
setFocusControllerActive(false);
}
mKeysPressed.clear();
@@ -5776,8 +5812,9 @@
} else {
mGLViewportEmpty = true;
}
+ calcOurContentVisibleRectF(mVisibleContentRect);
nativeUpdateDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport,
- mGLViewportEmpty ? null : mViewRectViewport);
+ mGLViewportEmpty ? null : mViewRectViewport, mVisibleContentRect);
}
/**
@@ -8410,6 +8447,11 @@
mZoomManager.updateZoomRange(viewState, getViewWidth(), viewState.mScrollX);
break;
}
+ case UPDATE_ZOOM_DENSITY: {
+ final float density = (Float) msg.obj;
+ mZoomManager.updateDefaultZoomDensity(density);
+ break;
+ }
case REPLACE_BASE_CONTENT: {
nativeReplaceBaseContent(msg.arg1);
break;
@@ -8424,7 +8466,11 @@
// nativeCreate sets mNativeClass to a non-zero value
String drawableDir = BrowserFrame.getRawResFilename(
BrowserFrame.DRAWABLEDIR, mContext);
- nativeCreate(msg.arg1, drawableDir);
+ WindowManager windowManager =
+ (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ Display display = windowManager.getDefaultDisplay();
+ nativeCreate(msg.arg1, drawableDir,
+ ActivityManager.isHighEndGfx(display));
if (mDelaySetPicture != null) {
setNewPicture(mDelaySetPicture, true);
mDelaySetPicture = null;
@@ -8774,7 +8820,6 @@
mSendScrollEvent = false;
recordNewContentSize(draw.mContentSize.x,
draw.mContentSize.y, updateLayout);
-
if (isPictureAfterFirstLayout) {
// Reset the last sent data here since dealing with new page.
mLastWidthSent = 0;
@@ -9345,7 +9390,8 @@
* @hide only needs to be accessible to Browser and testing
*/
public void drawPage(Canvas canvas) {
- nativeDraw(canvas, 0, 0, false);
+ calcOurContentVisibleRectF(mVisibleContentRect);
+ nativeDraw(canvas, mVisibleContentRect, 0, 0, false);
}
/**
@@ -9453,7 +9499,7 @@
private native Rect nativeCacheHitNodeBounds();
private native int nativeCacheHitNodePointer();
/* package */ native void nativeClearCursor();
- private native void nativeCreate(int ptr, String drawableDir);
+ private native void nativeCreate(int ptr, String drawableDir, boolean isHighEndGfx);
private native int nativeCursorFramePointer();
private native Rect nativeCursorNodeBounds();
private native int nativeCursorNodePointer();
@@ -9476,13 +9522,14 @@
* MUST be passed to WebViewCore with SPLIT_PICTURE_SET message so that the
* native allocation can be freed.
*/
- private native int nativeDraw(Canvas canvas, int color, int extra,
- boolean splitIfNeeded);
+ private native int nativeDraw(Canvas canvas, RectF visibleRect,
+ int color, int extra, boolean splitIfNeeded);
private native void nativeDumpDisplayTree(String urlOrNull);
private native boolean nativeEvaluateLayersAnimations(int nativeInstance);
private native int nativeGetDrawGLFunction(int nativeInstance, Rect rect,
- Rect viewRect, float scale, int extras);
- private native void nativeUpdateDrawGLFunction(Rect rect, Rect viewRect);
+ Rect viewRect, RectF visibleRect, float scale, int extras);
+ private native void nativeUpdateDrawGLFunction(Rect rect, Rect viewRect,
+ RectF visibleRect);
private native void nativeExtendSelection(int x, int y);
private native int nativeFindAll(String findLower, String findUpper,
boolean sameAsLastSearch);
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index cd61481..2ad866b 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2336,6 +2336,10 @@
adjust = (float) mContext.getResources().getDisplayMetrics().densityDpi
/ mViewportDensityDpi;
}
+ if (adjust != mWebView.getDefaultZoomScale()) {
+ Message.obtain(mWebView.mPrivateHandler,
+ WebView.UPDATE_ZOOM_DENSITY, adjust).sendToTarget();
+ }
int defaultScale = (int) (adjust * 100);
if (mViewportInitialScale > 0) {
@@ -2546,7 +2550,7 @@
// called by JNI
private void restoreScale(float scale, float textWrapScale) {
if (mBrowserFrame.firstLayoutDone() == false) {
- mIsRestored = scale > 0;
+ mIsRestored = true;
mRestoredScale = scale;
if (mSettings.getUseWideViewPort()) {
mRestoredTextWrapScale = textWrapScale;
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index e1392ae..695c154 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -42,7 +42,7 @@
// log tag
protected static final String LOGTAG = "webviewdatabase";
- private static final int DATABASE_VERSION = 10;
+ private static final int DATABASE_VERSION = 11;
// 2 -> 3 Modified Cache table to allow cache of redirects
// 3 -> 4 Added Oma-Downloads table
// 4 -> 5 Modified Cache table to support persistent contentLength
@@ -52,6 +52,9 @@
// 7 -> 8 Move cache to its own db
// 8 -> 9 Store both scheme and host when storing passwords
// 9 -> 10 Update httpauth table UNIQUE
+ // 10 -> 11 Drop cookies and cache now managed by the chromium stack,
+ // and update the form data table to use the new format
+ // implemented for b/5265606.
private static final int CACHE_DATABASE_VERSION = 4;
// 1 -> 2 Add expires String
// 2 -> 3 Add content-disposition
@@ -204,7 +207,9 @@
}
initDatabase(context);
- if (!JniUtil.useChromiumHttpStack()) {
+ if (JniUtil.useChromiumHttpStack()) {
+ context.deleteDatabase(CACHE_DATABASE_FILE);
+ } else {
initCacheDatabase(context);
}
@@ -327,15 +332,59 @@
}
private static void upgradeDatabase() {
+ upgradeDatabaseToV10();
+ upgradeDatabaseFromV10ToV11();
+ // Add future database upgrade functions here, one version at a
+ // time.
+ mDatabase.setVersion(DATABASE_VERSION);
+ }
+
+ private static void upgradeDatabaseFromV10ToV11() {
int oldVersion = mDatabase.getVersion();
+
+ if (oldVersion >= 11) {
+ // Nothing to do.
+ return;
+ }
+
+ if (JniUtil.useChromiumHttpStack()) {
+ // Clear out old java stack cookies - this data is now stored in
+ // a separate database managed by the Chrome stack.
+ mDatabase.execSQL("DROP TABLE IF EXISTS " + mTableNames[TABLE_COOKIES_ID]);
+
+ // Likewise for the old cache table.
+ mDatabase.execSQL("DROP TABLE IF EXISTS cache");
+ }
+
+ // Update form autocomplete URLs to match new ICS formatting.
+ Cursor c = mDatabase.query(mTableNames[TABLE_FORMURL_ID], null, null,
+ null, null, null, null);
+ while (c.moveToNext()) {
+ String urlId = Long.toString(c.getLong(c.getColumnIndex(ID_COL)));
+ String url = c.getString(c.getColumnIndex(FORMURL_URL_COL));
+ ContentValues cv = new ContentValues(1);
+ cv.put(FORMURL_URL_COL, WebTextView.urlForAutoCompleteData(url));
+ mDatabase.update(mTableNames[TABLE_FORMURL_ID], cv, ID_COL + "=?",
+ new String[] { urlId });
+ }
+ c.close();
+ }
+
+ private static void upgradeDatabaseToV10() {
+ int oldVersion = mDatabase.getVersion();
+
+ if (oldVersion >= 10) {
+ // Nothing to do.
+ return;
+ }
+
if (oldVersion != 0) {
Log.i(LOGTAG, "Upgrading database from version "
+ oldVersion + " to "
+ DATABASE_VERSION + ", which will destroy old data");
}
- boolean justPasswords = 8 == oldVersion && 9 == DATABASE_VERSION;
- boolean justAuth = 9 == oldVersion && 10 == DATABASE_VERSION;
- if (justAuth) {
+
+ if (9 == oldVersion) {
mDatabase.execSQL("DROP TABLE IF EXISTS "
+ mTableNames[TABLE_HTTPAUTH_ID]);
mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
@@ -348,55 +397,49 @@
return;
}
- if (!justPasswords) {
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_COOKIES_ID]);
- mDatabase.execSQL("DROP TABLE IF EXISTS cache");
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_FORMURL_ID]);
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_FORMDATA_ID]);
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_HTTPAUTH_ID]);
- }
+ mDatabase.execSQL("DROP TABLE IF EXISTS "
+ + mTableNames[TABLE_COOKIES_ID]);
+ mDatabase.execSQL("DROP TABLE IF EXISTS cache");
+ mDatabase.execSQL("DROP TABLE IF EXISTS "
+ + mTableNames[TABLE_FORMURL_ID]);
+ mDatabase.execSQL("DROP TABLE IF EXISTS "
+ + mTableNames[TABLE_FORMDATA_ID]);
+ mDatabase.execSQL("DROP TABLE IF EXISTS "
+ + mTableNames[TABLE_HTTPAUTH_ID]);
mDatabase.execSQL("DROP TABLE IF EXISTS "
+ mTableNames[TABLE_PASSWORD_ID]);
- mDatabase.setVersion(DATABASE_VERSION);
+ // cookies
+ mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_COOKIES_ID]
+ + " (" + ID_COL + " INTEGER PRIMARY KEY, "
+ + COOKIES_NAME_COL + " TEXT, " + COOKIES_VALUE_COL
+ + " TEXT, " + COOKIES_DOMAIN_COL + " TEXT, "
+ + COOKIES_PATH_COL + " TEXT, " + COOKIES_EXPIRES_COL
+ + " INTEGER, " + COOKIES_SECURE_COL + " INTEGER" + ");");
+ mDatabase.execSQL("CREATE INDEX cookiesIndex ON "
+ + mTableNames[TABLE_COOKIES_ID] + " (path)");
- if (!justPasswords) {
- // cookies
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_COOKIES_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, "
- + COOKIES_NAME_COL + " TEXT, " + COOKIES_VALUE_COL
- + " TEXT, " + COOKIES_DOMAIN_COL + " TEXT, "
- + COOKIES_PATH_COL + " TEXT, " + COOKIES_EXPIRES_COL
- + " INTEGER, " + COOKIES_SECURE_COL + " INTEGER" + ");");
- mDatabase.execSQL("CREATE INDEX cookiesIndex ON "
- + mTableNames[TABLE_COOKIES_ID] + " (path)");
+ // formurl
+ mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMURL_ID]
+ + " (" + ID_COL + " INTEGER PRIMARY KEY, " + FORMURL_URL_COL
+ + " TEXT" + ");");
- // formurl
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMURL_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, " + FORMURL_URL_COL
- + " TEXT" + ");");
+ // formdata
+ mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMDATA_ID]
+ + " (" + ID_COL + " INTEGER PRIMARY KEY, "
+ + FORMDATA_URLID_COL + " INTEGER, " + FORMDATA_NAME_COL
+ + " TEXT, " + FORMDATA_VALUE_COL + " TEXT," + " UNIQUE ("
+ + FORMDATA_URLID_COL + ", " + FORMDATA_NAME_COL + ", "
+ + FORMDATA_VALUE_COL + ") ON CONFLICT IGNORE);");
- // formdata
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMDATA_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, "
- + FORMDATA_URLID_COL + " INTEGER, " + FORMDATA_NAME_COL
- + " TEXT, " + FORMDATA_VALUE_COL + " TEXT," + " UNIQUE ("
- + FORMDATA_URLID_COL + ", " + FORMDATA_NAME_COL + ", "
- + FORMDATA_VALUE_COL + ") ON CONFLICT IGNORE);");
-
- // httpauth
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, "
- + HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
- + " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
- + HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
- + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL
- + ") ON CONFLICT REPLACE);");
- }
+ // httpauth
+ mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
+ + " (" + ID_COL + " INTEGER PRIMARY KEY, "
+ + HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
+ + " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
+ + HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
+ + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL
+ + ") ON CONFLICT REPLACE);");
// passwords
mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_PASSWORD_ID]
+ " (" + ID_COL + " INTEGER PRIMARY KEY, "
@@ -411,7 +454,7 @@
if (oldVersion != 0) {
Log.i(LOGTAG, "Upgrading cache database from version "
+ oldVersion + " to "
- + DATABASE_VERSION + ", which will destroy all old data");
+ + CACHE_DATABASE_VERSION + ", which will destroy all old data");
}
mCacheDatabase.execSQL("DROP TABLE IF EXISTS cache");
mCacheDatabase.setVersion(CACHE_DATABASE_VERSION);
@@ -1150,7 +1193,7 @@
cursor = mDatabase.query(mTableNames[TABLE_FORMURL_ID],
ID_PROJECTION, urlSelection, new String[] { url }, null,
null, null);
- if (cursor.moveToFirst()) {
+ while (cursor.moveToNext()) {
long urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
Cursor dataCursor = null;
try {
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index f599dba..84d00c9 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -349,7 +349,7 @@
}
public final void setInitialScaleInPercent(int scaleInPercent) {
- mInitialScale = scaleInPercent * mDisplayDensity * 0.01f;
+ mInitialScale = scaleInPercent * 0.01f;
}
public final float computeScaleWithLimits(float scale) {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 3e96c81..fec4cbc 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -1275,7 +1275,7 @@
// record changes to the battery level.
if (mHistoryLastWritten.batteryLevel == mHistoryCur.batteryLevel &&
(dataSize >= MAX_MAX_HISTORY_BUFFER
- || ((mHistoryEnd.states^mHistoryCur.states)
+ || ((mHistoryLastWritten.states^mHistoryCur.states)
& HistoryItem.MOST_INTERESTING_STATES) == 0)) {
return;
}
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index b7bc366..25b0065 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -29,6 +29,7 @@
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewParent;
import android.view.animation.DecelerateInterpolator;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
@@ -392,7 +393,11 @@
final ActionBar.Tab tab = mTab;
final View custom = tab.getCustomView();
if (custom != null) {
- addView(custom);
+ final ViewParent customParent = custom.getParent();
+ if (customParent != this) {
+ if (customParent != null) ((ViewGroup) customParent).removeView(custom);
+ addView(custom);
+ }
mCustomView = custom;
if (mTextView != null) mTextView.setVisibility(GONE);
if (mIconView != null) {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 230df39..97658a1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -263,8 +263,7 @@
android:label="@string/permlab_writeProfile"
android:description="@string/permdesc_writeProfile" />
- <!-- Allows an application to read from the user's social stream.
- @hide -->
+ <!-- Allows an application to read from the user's social stream. -->
<permission android:name="android.permission.READ_SOCIAL_STREAM"
android:permissionGroup="android.permission-group.PERSONAL_INFO"
android:protectionLevel="dangerous"
@@ -272,8 +271,7 @@
android:description="@string/permdesc_readSocialStream" />
<!-- Allows an application to write (but not read) the user's
- social stream data.
- @hide -->
+ social stream data. -->
<permission android:name="android.permission.WRITE_SOCIAL_STREAM"
android:permissionGroup="android.permission-group.PERSONAL_INFO"
android:protectionLevel="dangerous"
diff --git a/core/res/res/layout/media_controller.xml b/core/res/res/layout/media_controller.xml
index 582101a..313806cd 100644
--- a/core/res/res/layout/media_controller.xml
+++ b/core/res/res/layout/media_controller.xml
@@ -17,13 +17,9 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="#CC666666"
+ android:background="#CC000000"
android:orientation="vertical">
- <ImageView android:layout_width="match_parent"
- android:layout_height="1px"
- android:background="@android:drawable/divider_horizontal_dark" />
-
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 168030c..42f3d8c 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1219,6 +1219,6 @@
<string name="status_bar_device_locked" msgid="3092703448690669768">"Toestel gesluit."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
<string name="sending" msgid="8715108995741758718">"Stuur tans..."</string>
- <string name="launchBrowserDefault" msgid="2057951947297614725">"Begin Browser?"</string>
- <string name="SetupCallDefault" msgid="6870275517518479651">"Aanvaar Bel?"</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Begin webblaaier?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Aanvaar oproep?"</string>
</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 97996ab..9fb9946 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Апублікаваць праз..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Прылада заблакаваная."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Адпраўка..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Запусцiць браўзер?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Адказаць?"</string>
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 66b5cae..f86b74f 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Споделяне със..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Устройството е заключено."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Изпраща се..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Да се стартира ли браузърът?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Да се приеме ли обаждането?"</string>
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 74ee156..617c0b3 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Sdílet s..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Zařízení je uzamčeno."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Odesílání..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Spustit prohlížeč?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Přijmout hovor?"</string>
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 465ec4e..c1f4c9b 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Del med:"</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Enhed låst."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Sender..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Vil du starte browseren?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Vil du besvare opkaldet?"</string>
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index f77187c..53c4f30 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1096,7 +1096,7 @@
<string name="throttled_notification_title" msgid="6269541897729781332">"Mobildatenlimit überschritten"</string>
<string name="throttled_notification_message" msgid="4712369856601275146">"Durch Berühren weitere Informationen zur Mobildatennutzung aufrufen"</string>
<string name="no_matches" msgid="8129421908915840737">"Keine Treffer"</string>
- <string name="find_on_page" msgid="1946799233822820384">"Auf Seite suchen"</string>
+ <string name="find_on_page" msgid="1946799233822820384">"Suchen"</string>
<plurals name="matches_found">
<item quantity="one" msgid="8167147081136579439">"1 Treffer"</item>
<item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> von <xliff:g id="TOTAL">%d</xliff:g>"</item>
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Teilen mit..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Gerät gesperrt"</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Wird gesendet..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Browser starten?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Anruf annehmen?"</string>
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 54980a5..f52d25d 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Κοινή χρήση με..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Η συσκευή κλειδώθηκε."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Αποστολή..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Εκκίνηση προγράμματος περιήγησης;"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Αποδοχή κλήσης;"</string>
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index ba79143..f93aee3 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Compartir con..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Dispositivo bloqueado"</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Envío en curso..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"¿Deseas iniciar el navegador?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"¿Deseas aceptar la llamada?"</string>
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index a7aeb01..db9dab0 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Compartir con..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Dispositivo bloqueado"</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Enviando..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"¿Iniciar el navegador?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"¿Aceptar la llamada?"</string>
</resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 4801b32..3b4d993 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Jaga kasutaja(te)ga ..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Seade lukustatud."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Saatmine ..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Kas käivitada brauser?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Kas vastata kõnele?"</string>
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 49cae50..9c06aa6 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Jaa seuraavien kautta:"</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Laite lukittu."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Lähetetään..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Käynnistetäänkö selain?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Vastataanko puheluun?"</string>
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 4b33998..f2726d8b 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Partager avec..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Appareil verrouillé"</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Envoi en cours…"</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Lancer l\'application Navigateur ?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Prendre l\'appel ?"</string>
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 7f140f1..925724e 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"इससे साझा करें..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"उपकरण लॉक कर दिया गया."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"भेज रहा है..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"ब्राउज़र लॉन्च करें?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"कॉल स्वीकार करें?"</string>
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 0599a6b..ae592f1 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Dijeli sa..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Uređaj zaključan."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Slanje u tijeku..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Pokrenuti preglednik?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Prihvatiti poziv?"</string>
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 6e395f3..d303aa1 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Megosztás..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Az eszköz le van zárva."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Küldés..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Böngésző indítása?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Hívás fogadása?"</string>
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 930c89e..2699953 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Berbagi dengan..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Perangkat tergembok."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Mengirim..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Luncurkan Peramban?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Terima Panggilan?"</string>
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index bd7350d..0706a24 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Condividi con..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Dispositivo bloccato."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Invio..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Avviare l\'applicazione Browser?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Accettare la chiamata?"</string>
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 7b315c2..b74d7fd 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -901,7 +901,7 @@
<string name="chooseUsbActivity" msgid="7892597146032121735">"בחר יישום עבור מכשיר ה-USB"</string>
<string name="noApplications" msgid="1691104391758345586">"אין יישומים שיכולים לבצע פעולה זו."</string>
<string name="aerr_title" msgid="1905800560317137752"></string>
- <string name="aerr_application" msgid="932628488013092776">"לצערנו ה<xliff:g id="APPLICATION">%1$s</xliff:g> הפסיק לפעול."</string>
+ <string name="aerr_application" msgid="932628488013092776">"לצערנו, פעולת ה<xliff:g id="APPLICATION">%1$s</xliff:g> הופסקה."</string>
<string name="aerr_process" msgid="4507058997035697579">"לצערנו, התהליך <xliff:g id="PROCESS">%1$s</xliff:g> הופסק."</string>
<string name="anr_title" msgid="4351948481459135709"></string>
<string name="anr_activity_application" msgid="8339738283149696827">"<xliff:g id="APPLICATION">%2$s</xliff:g> אינו מגיב."\n\n" האם ברצונך לסגור אותו?"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index d0e94c8..15dc2fe 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"共有相手..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"端末がロックされています。"</string>
<string name="list_delimeter" msgid="3975117572185494152">"、 "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"送信しています..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"ブラウザを起動しますか?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"通話を受けますか?"</string>
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index fe048be..924198e 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"공유 대상..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"기기가 잠겼습니다."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"보내는 중..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"브라우저를 실행하시겠습니까?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"통화를 수락하시겠습니까?"</string>
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index bb3b044..ae92e56 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Bendrinti su..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Įrenginys užrakintas."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Siunčiama..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Paleisti naršyklę?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Priimti skambutį?"</string>
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index dc60a35..b4e4488 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Koplietot ar..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Ierīce ir bloķēta."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Notiek sūtīšana..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Vai palaist pārlūkprogrammu?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Vai pieņemt zvanu?"</string>
</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index b268575..a2b253b 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Kongsi dengan..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Peranti dikunci."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Menghantar..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Lancarkan Penyemak Imbas?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Terima Panggilan?"</string>
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index e9c0965..0cab24a 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -302,7 +302,7 @@
<string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Lar appen lese fra diverse loggfiler på systemet. Disse inneholder generell informasjon om hva som gjøres med nettbrettet, og kan inneholde personlig eller privat informasjon."</string>
<string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Lar appen lese fra diverse loggfiler på systemet. Disse inneholder generell informasjon om hva som gjøres med telefonen, og kan inneholde personlig eller privat informasjon."</string>
<string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"bruke en hvilken som helst mediedekoder for avspilling"</string>
- <string name="permdesc_anyCodecForPlayback" msgid="2101444559995480174">"Gir en app tillatelse til å bruke en hvilken som helst installert mediedekoder for å dekode for avspilling."</string>
+ <string name="permdesc_anyCodecForPlayback" msgid="2101444559995480174">"Lar apper bruke en hvilken som helst installert mediedekoder for å dekode for avspilling."</string>
<string name="permlab_diagnostic" msgid="8076743953908000342">"lese/skrive ressurser eid av diag"</string>
<string name="permdesc_diagnostic" msgid="3121238373951637049">"Lar applikasjonen lese og skrive enhver ressurs eid av gruppen diag; for eksempel, filer i /dev. Dette kan potensielt påvirke systemets sikkerhet og stabilitet. Dette bør KUN brukes for maskinvarespesifikke diagnoseverktøy laget av operatøren eller produsenten."</string>
<string name="permlab_changeComponentState" msgid="79425198834329406">"aktivere eller deaktigere applikasjonskomponenter"</string>
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Del med"</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Enheten er låst."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Sender …"</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Vil du starte nettleseren?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Vil du besvare anropet?"</string>
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index cc04e9c..14d3d0c 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -36,7 +36,7 @@
<string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
<string name="mmiError" msgid="5154499457739052907">"Problem z połączeniem lub błędny kod MMI."</string>
<string name="mmiFdnError" msgid="5224398216385316471">"Operacja jest ograniczona wyłącznie do numerów ustalonych."</string>
- <string name="serviceEnabled" msgid="8147278346414714315">"Usługa była włączona."</string>
+ <string name="serviceEnabled" msgid="8147278346414714315">"Usługa została włączona."</string>
<string name="serviceEnabledFor" msgid="6856228140453471041">"Usługa została włączona dla:"</string>
<string name="serviceDisabled" msgid="1937553226592516411">"Usługa została wyłączona."</string>
<string name="serviceRegistered" msgid="6275019082598102493">"Rejestracja powiodła się."</string>
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Udostępnij..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Urządzenie zablokowane."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Wysyłanie..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Uruchomić przeglądarkę?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Odebrać połączenie?"</string>
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 16e1282..679d73d 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1020,7 +1020,7 @@
<string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatar"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB ligada"</string>
<string name="adb_active_notification_message" msgid="8470296818270110396">"Seleccione para desactivar depuração USB."</string>
- <string name="select_input_method" msgid="6865512749462072765">"Selecionar método de entrada"</string>
+ <string name="select_input_method" msgid="6865512749462072765"></string>
<string name="configure_input_methods" msgid="6324843080254191535">"Configurar métodos de entrada"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Partilhar com..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Aparelho bloqueado."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"A enviar..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Iniciar Navegador?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Aceitar Chamada?"</string>
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 86492fa..040ad38 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Distribuiţi cu..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Dispozitiv blocat."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Se trimite..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Lansaţi browserul?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Acceptaţi apelul?"</string>
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index d0a40954..58b027c 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Настройка доступа"</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Устройство заблокировано."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Отправка..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Запустить браузер?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Принять вызов?"</string>
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index f075d27..5476a84 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Zdieľať s..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Zariadenie je zamknuté."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Prebieha odosielanie..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Spustiť prehliadač?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Prijať hovor?"</string>
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index e298819..1221b99 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Skupna raba z ..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Naprava zaklenjena."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Pošiljanje ..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Ali želite odpreti brskalnik?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Ali želite sprejeti klic?"</string>
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index f083a6d..5402394 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Дељење са..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Уређај је закључан."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Слање..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Желите ли да покренете прегледач?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Желите ли да прихватите позив?"</string>
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 2e04d8f..f1dbe47 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Dela med..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Enheten är låst."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Skickas ..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Vill du öppna webbläsaren?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Vill du ta emot samtal?"</string>
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index d1287d8..5334bfc 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -266,11 +266,11 @@
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"funganisha kwa mbinu ya uingizaji"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Huruhusu kishikiliaji kufunga kiolesura cha kiwango cha juu cha mbinu ya uingizaji. Haipaswi kuhitajika kwa programu za kawaida za kompyuta."</string>
<string name="permlab_bindTextService" msgid="7358378401915287938">"Imefungwa kwa huduma ya maandishi"</string>
- <string name="permdesc_bindTextService" msgid="172508880651909350">"Huruhusu kishikiliaji kufunga kiolesura cha kiwango cha juu cha pazia cha huduma ya maandishi (k.m.SpellCheckerService). Haipaswi kuhitajika kwa programu za kawaida."</string>
+ <string name="permdesc_bindTextService" msgid="172508880651909350">"Huruhusu kishikiliaji kufunga kiolesura cha kiwango cha juu cha mandhari cha huduma ya maandishi (k.m.SpellCheckerService). Haipaswi kuhitajika kwa programu za kawaida."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"funga kwa huduma ya VPN"</string>
<string name="permdesc_bindVpnService" msgid="6011554199384584151">"Huruhusu kishikiliaji kufunga kusano cha kiwango cha juu cha huduma ya Vpn. Haipaswi kamwe kuhitajika kwa programu za kawaida."</string>
- <string name="permlab_bindWallpaper" msgid="8716400279937856462">"funga kwa pazia"</string>
- <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Huruhusu kishikiliaji kufunga kiolesura cha kiwango cha juu cha pazia. Haipaswi kuhitajika kwa programu za kawaida za kompyuta."</string>
+ <string name="permlab_bindWallpaper" msgid="8716400279937856462">"funga kwa mandhari"</string>
+ <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Huruhusu kishikiliaji kufunga kiolesura cha kiwango cha juu cha mandhari. Haipaswi kuhitajika kwa programu za kawaida za kompyuta."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"funga kwenye huduma ya widget"</string>
<string name="permdesc_bindRemoteViews" msgid="2930855984822926963">"Huruhusu kishikiliaji kufunga kiolesura cha kiwango cha juu cha huduma ya wiji. Haipaswi kuhitajika kwa programu za kawaida."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"jiunge na msimamizi wa kifaa"</string>
@@ -333,9 +333,9 @@
<string name="permlab_writeProfile" msgid="4679878325177177400">"andika kwenye data ya maelezo yako mafupi"</string>
<string name="permdesc_writeProfile" product="default" msgid="6431297330378229453">"Inaruhusu programu kubadilisha au kuongeza maelezo binafsi ya maelezo yako mafupi yaliyohifadhiwa kwenye kifaa chako, kama vile jina lako na maelezo ya anwani. Hii ina maanisha programu nyingine ziweze kukutambua na kutuma maelezo ya maelezo yako mafupi kwa wengine."</string>
<string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"soma mkondo wako wa kijamii"</string>
- <string name="permdesc_readSocialStream" product="default" msgid="6619997662735851111">"Inaruhusu programu kufikia na kulandanisha usasisho kutoka kwako na marafiki wako. Prog hasidi zinaweza kutumia hizi kusoma mawasiliano ya kibinafsi kati yako na marafiki wako kwenye mitandao ya kijamii."</string>
+ <string name="permdesc_readSocialStream" product="default" msgid="6619997662735851111">"Inaruhusu programuramu kufikia na kulandanisha usasisho kutoka kwako na marafiki wako. Prog hasidi zinaweza kutumia hizi kusoma mawasiliano ya kibinafsi kati yako na marafiki wako kwenye mitandao ya kijamii."</string>
<string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"andika kwa mkondo wako wa kijamii"</string>
- <string name="permdesc_writeSocialStream" product="default" msgid="2689083745826002521">"Inaruhusu programu kuonyesha usasisho ya kijamii kutoka kwa marafiki wako. Prog hasidi zinaweza kutumia hizi zikijifanya kuwa rafiki na kukuhadaa kuonyesha nenosiri au taarifa zingine za siri."</string>
+ <string name="permdesc_writeSocialStream" product="default" msgid="2689083745826002521">"Inaruhusu programuramu kuonyesha usasisho ya kijamii kutoka kwa marafiki wako. Prog hasidi zinaweza kutumia hizi zikijifanya kuwa rafiki na kukuhadaa kuonyesha nenosiri au taarifa zingine za siri."</string>
<string name="permlab_readCalendar" msgid="5972727560257612398">"soma matukio ya kalenda pamoja na maelezo ya siri"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5665520896961671949">"Huruhusu programu kusoma matukio yote ya kalenda yaliyohifadhiwa kwenye kompyuta yako ndogo, pamoja na za marafiki au wafanyakazi wenza. Programu hasidi yenye kibali hiki kinaweza kuchukua maelezo ya kibinagsi kutoka kwa kalenda hizi bila ufahamu wa mmiliki."</string>
<string name="permdesc_readCalendar" product="default" msgid="2915879965326930312">"Huruhusu programu kusoma matukio yote ya kalenda yaliyohifadhiwa kwenye simu yako, pamoja na za marafiki au marafiki wenza. Programu hasidi yenye kibali hiki inaweza kuchukua maelezo ya kibinafsi kutoka kwa kalenda hizi bila ufahamu wa mmiliki."</string>
@@ -423,10 +423,10 @@
<string name="permlab_factoryTest" msgid="3715225492696416187">"endesha katika hali ya jaribio ya kiwanda"</string>
<string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Endesha kama jaribio la mtengenezaji la kiwango cha chini, kwa hivyo kuruhusu ufikiaji kamili wa maunzi ya kompyuta ndogo. Inapatikana tu wakati kompyuta ndogo inaendeshwa katika hali ya jaribio la mtengenezaji."</string>
<string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Endesha kama jaribio la kiwango cha chini cha mtengenezaji, kwa hivyo kuruhusu ufikiaji kamili wa maunzi ya simu. Inapatikana tu wakati simu inaendeshwa katika gumzo ya jaribio ya mtengenezaji."</string>
- <string name="permlab_setWallpaper" msgid="6627192333373465143">"weka pazia"</string>
- <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Huruhusu programu kuweka pazia ya mfumo."</string>
- <string name="permlab_setWallpaperHints" msgid="3600721069353106851">"weka vidokezo vya ukubwa wa pazia"</string>
- <string name="permdesc_setWallpaperHints" msgid="6019479164008079626">"Huruhusu programu kuweka vidokezo vya ukubwa wa pazia ya mfumo."</string>
+ <string name="permlab_setWallpaper" msgid="6627192333373465143">"weka mandhari"</string>
+ <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Huruhusu programu kuweka mandhari ya mfumo."</string>
+ <string name="permlab_setWallpaperHints" msgid="3600721069353106851">"weka vidokezo vya ukubwa wa mandhari"</string>
+ <string name="permdesc_setWallpaperHints" msgid="6019479164008079626">"Huruhusu programu kuweka vidokezo vya ukubwa wa mandhari ya mfumo."</string>
<string name="permlab_masterClear" msgid="2315750423139697397">"weka upya mfumo kwa chaguo-msingi za kiwanda"</string>
<string name="permdesc_masterClear" msgid="5033465107545174514">"Huruhusu programu kuweka upya kabisa mfumo kwa mipangilio yake ya kiwanda, kwa hivyo kufuta data zote, usanidi, na programu za kompyuta zilizosanidiwa."</string>
<string name="permlab_setTime" msgid="2021614829591775646">"weka muda"</string>
@@ -844,7 +844,7 @@
<item quantity="one" msgid="2178576254385739855">"kesho"</item>
<item quantity="other" msgid="2973062968038355991">"kati ya siku <xliff:g id="COUNT">%d</xliff:g>"</item>
</plurals>
- <string name="preposition_for_date" msgid="9093949757757445117">"mnamo <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="preposition_for_date" msgid="9093949757757445117">"tarehe <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"Saa <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"ndani ya <xliff:g id="YEAR">%s</xliff:g>"</string>
<string name="day" msgid="8144195776058119424">"siku"</string>
@@ -1074,8 +1074,8 @@
<string name="input_method_binding_label" msgid="1283557179944992649">"Mbinu ya uingizaji"</string>
<string name="sync_binding_label" msgid="3687969138375092423">"Sawazisha"</string>
<string name="accessibility_binding_label" msgid="4148120742096474641">"Ufikiaji"</string>
- <string name="wallpaper_binding_label" msgid="1240087844304687662">"Pazia"</string>
- <string name="chooser_wallpaper" msgid="7873476199295190279">"Badilisha pazia"</string>
+ <string name="wallpaper_binding_label" msgid="1240087844304687662">"Mandhari"</string>
+ <string name="chooser_wallpaper" msgid="7873476199295190279">"Badilisha mandhari"</string>
<string name="vpn_title" msgid="8219003246858087489">"VPN imeamilishwa."</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN imeamilishwa na <xliff:g id="APP">%s</xliff:g>"</string>
<string name="vpn_text" msgid="1610714069627824309">"Gonga ili kudhibiti mtandao."</string>
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Shiriki na..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Kifaa kimefungwa."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Inatuma..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Zindua Kivinjari?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Kubali Simu?"</string>
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index abd1208..c224d54 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"แบ่งปันกับ..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"ล็อกอุปกรณ์อยู่"</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"กำลังส่ง..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"เปิดเบราว์เซอร์หรือไม่"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"รับสายหรือไม่"</string>
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index bc47b0a..4ff92d2 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Ibahagi kay..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Naka-lock ang device."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Ipinapadala..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Ilunsad ang Browser?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Tanggapin ang Tawag?"</string>
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index d27d95b..7eaeedc 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Şununla paylaş..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Cihaz kilitli."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Gönderiliyor..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Tarayıcı Başlatılsın mı?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Çağrı Kabul Edilsin mi?"</string>
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 72b91fc..8213008 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -38,9 +38,9 @@
<string name="mmiFdnError" msgid="5224398216385316471">"Chỉ hạn chế thao tác đối với số quay số định sẵn."</string>
<string name="serviceEnabled" msgid="8147278346414714315">"Dịch vụ đã được bật."</string>
<string name="serviceEnabledFor" msgid="6856228140453471041">"Dịch vụ đã được bật cho:"</string>
- <string name="serviceDisabled" msgid="1937553226592516411">"Dịch vụ đã bị vô hiệu hoá."</string>
+ <string name="serviceDisabled" msgid="1937553226592516411">"Dịch vụ đã bị vô hiệu hóa."</string>
<string name="serviceRegistered" msgid="6275019082598102493">"Đăng ký thành công."</string>
- <string name="serviceErased" msgid="1288584695297200972">"Xoá thành công."</string>
+ <string name="serviceErased" msgid="1288584695297200972">"Xóa thành công."</string>
<string name="passwordIncorrect" msgid="7612208839450128715">"Mật khẩu không chính xác."</string>
<string name="mmiComplete" msgid="8232527495411698359">"MMI hoàn tất."</string>
<string name="badPin" msgid="5085454289896032547">"Mã PIN cũ bạn đã nhập không chính xác."</string>
@@ -48,7 +48,7 @@
<string name="mismatchPin" msgid="3695902225843339274">"Mã PIN bạn đã nhập không khớp."</string>
<string name="invalidPin" msgid="3850018445187475377">"Nhập mã PIN có từ 4 đến 8 số."</string>
<string name="invalidPuk" msgid="8761456210898036513">"Nhập PUK có từ 8 số trở lên."</string>
- <string name="needPuk" msgid="919668385956251611">"Thẻ SIM của bạn đã bị khoá PUK. Nhập mã PUK để mở khoá thẻ SIM đó."</string>
+ <string name="needPuk" msgid="919668385956251611">"Thẻ SIM của bạn đã bị khóa PUK. Nhập mã PUK để mở khóa thẻ SIM đó."</string>
<string name="needPuk2" msgid="4526033371987193070">"Nhập mã PUK2 để bỏ chặn thẻ SIM."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Số gọi đến"</string>
<string name="ClirMmi" msgid="7784673673446833091">"Số gọi đi"</string>
@@ -83,7 +83,7 @@
<string name="serviceClassFAX" msgid="5566624998840486475">"FAX"</string>
<string name="serviceClassSMS" msgid="2015460373701527489">"SMS"</string>
<string name="serviceClassDataAsync" msgid="4523454783498551468">"Không đồng bộ"</string>
- <string name="serviceClassDataSync" msgid="7530000519646054776">"Đồng bộ hoá"</string>
+ <string name="serviceClassDataSync" msgid="7530000519646054776">"Đồng bộ hóa"</string>
<string name="serviceClassPacket" msgid="6991006557993423453">"Gói"</string>
<string name="serviceClassPAD" msgid="3235259085648271037">"PAD"</string>
<string name="roamingText0" msgid="7170335472198694945">"Chỉ báo Chuyển vùng Bật"</string>
@@ -124,11 +124,11 @@
<string name="httpErrorFileNotFound" msgid="5588380756326017105">"Không tìm thấy tệp được yêu cầu."</string>
<string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Quá nhiều yêu cầu đang được xử lý. Hãy thử lại sau."</string>
<string name="notification_title" msgid="1259940370369187045">"Lỗi đăng nhập đối với <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
- <string name="contentServiceSync" msgid="8353523060269335667">"Đồng bộ hoá"</string>
- <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Đồng bộ hoá"</string>
- <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Quá nhiều lần xoá <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
+ <string name="contentServiceSync" msgid="8353523060269335667">"Đồng bộ hóa"</string>
+ <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Đồng bộ hóa"</string>
+ <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Quá nhiều lần xóa <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="2292820184396262278">"Bộ nhớ máy tính bảng đã đầy! Hãy xóa một số tệp để giải phóng dung lượng."</string>
- <string name="low_memory" product="default" msgid="6632412458436461203">"Bộ nhớ điện thoại đã đầy! Hãy xoá một số tệp để tạo thêm dung lượng."</string>
+ <string name="low_memory" product="default" msgid="6632412458436461203">"Bộ nhớ điện thoại đã đầy! Hãy xóa một số tệp để tạo thêm dung lượng."</string>
<string name="me" msgid="6545696007631404292">"Tôi"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tùy chọn máy tính bảng"</string>
<string name="power_dialog" product="default" msgid="1319919075463988638">"Tùy chọn điện thoại"</string>
@@ -180,8 +180,8 @@
<string name="permgrouplab_storage" msgid="1971118770546336966">"Dung lượng"</string>
<string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Truy cập bộ nhớ USB."</string>
<string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Truy cập thẻ SD."</string>
- <string name="permlab_statusBar" msgid="7417192629601890791">"vô hiệu hoá hoặc sửa đổi thanh trạng thái"</string>
- <string name="permdesc_statusBar" msgid="1365473595331989732">"Cho phép ứng dụng vô hiệu hoá thanh trạng thái hoặc thêm và xoá biểu tượng hệ thống."</string>
+ <string name="permlab_statusBar" msgid="7417192629601890791">"vô hiệu hóa hoặc sửa đổi thanh trạng thái"</string>
+ <string name="permdesc_statusBar" msgid="1365473595331989732">"Cho phép ứng dụng vô hiệu hóa thanh trạng thái hoặc thêm và xóa biểu tượng hệ thống."</string>
<string name="permlab_statusBarService" msgid="7247281911387931485">"thanh trạng thái"</string>
<string name="permdesc_statusBarService" msgid="4097605867643520920">"Cho phép ứng dụng là thanh trạng thái."</string>
<string name="permlab_expandStatusBar" msgid="1148198785937489264">"mở rộng/thu gọn thanh trạng thái"</string>
@@ -189,9 +189,9 @@
<string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"chặn các cuộc gọi đi"</string>
<string name="permdesc_processOutgoingCalls" msgid="2228988201852654461">"Cho phép ứng dụng xử lý cuộc gọi đi và thay đổi số đã được quay số. Các ứng dụng độc hại có thể giám sát, chuyển hướng hoặc chặn các cuộc gọi đi."</string>
<string name="permlab_receiveSms" msgid="2697628268086208535">"nhận SMS"</string>
- <string name="permdesc_receiveSms" msgid="6298292335965966117">"Cho phép ứng dụng nhận và xử lý tin nhắn SMS. Các ứng dụng độc hại có thể giám sát tin nhắn của bạn hoặc xoá chúng mà không cần hiển thị tin nhắn đó cho bạn."</string>
+ <string name="permdesc_receiveSms" msgid="6298292335965966117">"Cho phép ứng dụng nhận và xử lý tin nhắn SMS. Các ứng dụng độc hại có thể giám sát tin nhắn của bạn hoặc xóa chúng mà không cần hiển thị tin nhắn đó cho bạn."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"nhận MMS"</string>
- <string name="permdesc_receiveMms" msgid="4563346832000174373">"Cho phép ứng dụng nhận và xử lý tin nhắn MMS. Các ứng dụng độc hại có thể giám sát tin nhắn của bạn hoặc xoá chúng mà không cần hiển thị tin nhắn đó cho bạn."</string>
+ <string name="permdesc_receiveMms" msgid="4563346832000174373">"Cho phép ứng dụng nhận và xử lý tin nhắn MMS. Các ứng dụng độc hại có thể giám sát tin nhắn của bạn hoặc xóa chúng mà không cần hiển thị tin nhắn đó cho bạn."</string>
<string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"nhận các truyền phát khẩn cấp"</string>
<string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Cho phép ứng dụng truy xuất và xử lý các thư phát khẩn cấp. Quyền này chỉ khả dụng đối với các ứng dụng hệ thống."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"gửi tin nhắn SMS"</string>
@@ -203,9 +203,9 @@
<string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Cho phép ứng dụng đọc tin nhắn SMS được lưu trữ trên điện thoại hoặc thẻ SIM của bạn. Các ứng dụng độc hại có thể đọc tin nhắn bí mật của bạn."</string>
<string name="permlab_writeSms" msgid="6881122575154940744">"chỉnh sửa SMS hoặc MMS"</string>
<string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Cho phép ứng dụng ghi vào tin nhắn SMS được lưu trữ trên máy tính bảng hoặc thẻ SIM của bạn. Các ứng dụng độc hại có thể xóa tin nhắn của bạn."</string>
- <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Cho phép ứng dụng ghi vào tin nhắn SMS được lưu trữ trên điện thoại hoặc thẻ SIM của bạn. Các ứng dụng độc hại có thể xoá tin nhắn của bạn."</string>
+ <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Cho phép ứng dụng ghi vào tin nhắn SMS được lưu trữ trên điện thoại hoặc thẻ SIM của bạn. Các ứng dụng độc hại có thể xóa tin nhắn của bạn."</string>
<string name="permlab_receiveWapPush" msgid="8258226427716551388">"nhận WAP"</string>
- <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Cho phép ứng dụng nhận và xử lý tin nhắn WAP. Các ứng dụng độc hại có thể giám sát tin nhắn của bạn hoặc xoá chúng mà không cần hiển thị tin nhắn đó cho bạn."</string>
+ <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Cho phép ứng dụng nhận và xử lý tin nhắn WAP. Các ứng dụng độc hại có thể giám sát tin nhắn của bạn hoặc xóa chúng mà không cần hiển thị tin nhắn đó cho bạn."</string>
<string name="permlab_getTasks" msgid="5005277531132573353">"truy xuất các ứng dụng đang chạy"</string>
<string name="permdesc_getTasks" msgid="7048711358713443341">"Cho phép ứng dụng truy xuất thông tin về các công việc hiện đang chạy. Có thể cho phép các ứng dụng độc hại phát hiện thông tin riêng tư về các ứng dụng khác."</string>
<string name="permlab_reorderTasks" msgid="5669588525059921549">"sắp xếp lại các ứng dụng đang chạy"</string>
@@ -234,8 +234,8 @@
<string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Ngăn người dùng chuyển sang ứng dụng khác."</string>
<string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"giám sát và kiểm soát tất cả khởi chạy ứng dụng"</string>
<string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Cho phép ứng dụng giám sát và kiểm soát cách hệ thống khởi chạy các hoạt động. Các ứng dụng độc hại có thể làm tổn hại hoàn toàn hệ thống. Quyền này chỉ cần cho việc phát triển, không bao giờ dùng cho việc sử dụng thông thường."</string>
- <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"gửi truyền phát đã xoá của gói"</string>
- <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Cho phép ứng dụng truyền phát thông báo rằng gói ứng dụng đã bị xoá. Các ứng dụng độc hại có thể sử dụng quyền này để loại bỏ mọi ứng dụng đang chạy khác."</string>
+ <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"gửi truyền phát đã xóa của gói"</string>
+ <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Cho phép ứng dụng truyền phát thông báo rằng gói ứng dụng đã bị xóa. Các ứng dụng độc hại có thể sử dụng quyền này để loại bỏ mọi ứng dụng đang chạy khác."</string>
<string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"gửi truyền phát SMS nhận được"</string>
<string name="permdesc_broadcastSmsReceived" msgid="9122419277306740155">"Cho phép ứng dụng truyền phát thông báo rằng đã nhận được tin nhắn SMS. Các ứng dụng độc hại có thẻ sử dụng quyền này để giả mạo tin nhắn SMS đến."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"gửi truyền phát WAP-PUSH nhận được"</string>
@@ -283,19 +283,19 @@
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"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="8659652042401085862">"đặt ứng dụng luôn chạy"</string>
<string name="permdesc_persistentActivity" msgid="5037199778265006008">"Cho phép ứng dụng tạo sự đồng nhất cho các phần của mình để hệ thống không thể sử dụng ứng dụng đó cho các ứng dụng khác."</string>
- <string name="permlab_deletePackages" msgid="3343439331576348805">"xoá ứng dụng"</string>
- <string name="permdesc_deletePackages" msgid="3634943677518723314">"Cho phép ứng dụng xoá các gói Android. Các ứng dụng độc hại có thể sử dụng quyền này để xoá các ứng dụng quan trọng."</string>
- <string name="permlab_clearAppUserData" msgid="2192134353540277878">"xoá dữ liệu của ứng dụng khác"</string>
- <string name="permdesc_clearAppUserData" msgid="7546345080434325456">"Cho phép ứng dụng xoá dữ liệu của người dùng."</string>
- <string name="permlab_deleteCacheFiles" msgid="1518556602634276725">"xoá bộ nhớ cache của các ứng dụng khác"</string>
- <string name="permdesc_deleteCacheFiles" msgid="2283074077168165971">"Cho phép ứng dụng xoá các tệp bộ nhớ cache."</string>
+ <string name="permlab_deletePackages" msgid="3343439331576348805">"xóa ứng dụng"</string>
+ <string name="permdesc_deletePackages" msgid="3634943677518723314">"Cho phép ứng dụng xóa các gói Android. Các ứng dụng độc hại có thể sử dụng quyền này để xóa các ứng dụng quan trọng."</string>
+ <string name="permlab_clearAppUserData" msgid="2192134353540277878">"xóa dữ liệu của ứng dụng khác"</string>
+ <string name="permdesc_clearAppUserData" msgid="7546345080434325456">"Cho phép ứng dụng xóa dữ liệu của người dùng."</string>
+ <string name="permlab_deleteCacheFiles" msgid="1518556602634276725">"xóa bộ nhớ cache của các ứng dụng khác"</string>
+ <string name="permdesc_deleteCacheFiles" msgid="2283074077168165971">"Cho phép ứng dụng xóa các tệp bộ nhớ cache."</string>
<string name="permlab_getPackageSize" msgid="4799785352306641460">"đo dung lượng lưu trữ ứng dụng"</string>
<string name="permdesc_getPackageSize" msgid="5557253039670753437">"Cho phép ứng dụng truy xuất mã, dữ liệu và kích thước bộ nhớ cache của nó"</string>
<string name="permlab_installPackages" msgid="335800214119051089">"cài đặt trực tiếp ứng dụng"</string>
<string name="permdesc_installPackages" msgid="526669220850066132">"Cho phép ứng dụng cài đặt các gói Android mới hoặc đã được cập nhật. Các ứng dụng độc hại có thể sử dụng quyền này để thêm ứng dụng mới có quyền mạnh mẽ tùy ý."</string>
- <string name="permlab_clearAppCache" msgid="4747698311163766540">"xoá tất cả dữ liệu bộ nhớ cache của ứng dụng"</string>
+ <string name="permlab_clearAppCache" msgid="4747698311163766540">"xóa tất cả dữ liệu bộ nhớ cache của ứng dụng"</string>
<string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Cho phép ứng dụng giải phóng bộ nhớ máy tính bảng bằng cách xóa các tệp trong thư mục bộ nhớ cache ứng dụng. Quyền truy cập thường rất hạn chế đối với quy trình hệ thống."</string>
- <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Cho phép ứng dụng tạo thêm dung lượng điện thoại bằng cách xoá các tệp trong thư mục bộ nhớ cache ứng dụng. Quyền truy cập thường rất hạn chế đối với quy trình hệ thống."</string>
+ <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Cho phép ứng dụng tạo thêm dung lượng điện thoại bằng cách xóa các tệp trong thư mục bộ nhớ cache ứng dụng. Quyền truy cập thường rất hạn chế đối với quy trình hệ thống."</string>
<string name="permlab_movePackage" msgid="728454979946503926">"Chuyển tài nguyên của ứng dụng"</string>
<string name="permdesc_movePackage" msgid="6323049291923925277">"Cho phép ứng dụng di chuyển các tài nguyên của ứng dụng từ phương tiện truyền thông bên trong ra phương tiện bên ngoài và ngược lại."</string>
<string name="permlab_readLogs" msgid="6615778543198967614">"đọc dữ liệu nhật ký nhạy cảm"</string>
@@ -305,7 +305,7 @@
<string name="permdesc_anyCodecForPlayback" msgid="2101444559995480174">"Cho phép ứng dụng sử dụng bất kỳ bộ giải mã phương tiện đã cài đặt nào để giải mã phát lại."</string>
<string name="permlab_diagnostic" msgid="8076743953908000342">"đọc/ghi vào tài nguyên do chẩn đoán sở hữu"</string>
<string name="permdesc_diagnostic" msgid="3121238373951637049">"Cho phép ứng dụng đọc và ghi vào bất kỳ tài nguyên nào do nhóm chẩn đoán sở hữu; ví dụ: các tệp trong /dev. Quyền này có thể ảnh hưởng đến sự ổn định và bảo mật của hệ thống. CHỈ nên sử dụng quyền này cho các chẩn đoán phần cứng cụ thể bởi nhà sản xuất hoặc nhà cung cấp dịch vụ."</string>
- <string name="permlab_changeComponentState" msgid="79425198834329406">"bật hoặc vô hiệu hoá các thành phần ứng dụng"</string>
+ <string name="permlab_changeComponentState" msgid="79425198834329406">"bật hoặc vô hiệu hóa các thành phần ứng dụng"</string>
<string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Cho phép ứng dụng thay đổi việc có nên bật thành phần của ứng dụng khác hay không. Các ứng dụng độc hại có thể sử dụng quyền này để vô hiệu hóa các tính năng quan trọng của máy tính bảng. Phải cẩn thận khi sử dụng quyền này vì nó có thể khiến các thành phần rơi vào trạng thái không sử dụng được, không đồng nhất hoặc không ổn định."</string>
<string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Cho phép ứng dụng thay đổi việc có nên bật thành phần của ứng dụng khác hay không. Các ứng dụng độc hại có thể sử dụng quyền này để vô hiệu hóa các tính năng quan trọng của điện thoại. Phải cẩn thận khi sử dụng quyền này vì quyền này có thể khiến các thành phần ứng dụng rơi vào trạng thái không sử dụng được, không đồng nhất hoặc không ổn định."</string>
<string name="permlab_setPreferredApplications" msgid="3393305202145172005">"đặt ứng dụng ưa thích"</string>
@@ -327,7 +327,7 @@
<string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Cho phép ứng dụng đọc tất cả dữ liệu liên hệ (địa chỉ) được lưu trữ trên điện thoại của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để gửi dữ liệu của bạn cho những người khác."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"ghi dữ liệu liên hệ"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Cho phép ứng dụng sửa đổi dữ liệu (địa chỉ) liên hệ được lưu trữ trên máy tính bảng của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xóa hoặc sửa đổi dữ liệu liên hệ của bạn."</string>
- <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Cho phép ứng dụng sửa đổi dữ liệu liên hệ (địa chỉ) được lưu trữ trên điện thoại của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xoá hoặc sửa đổi dữ liệu liên hệ của bạn."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Cho phép ứng dụng sửa đổi dữ liệu liên hệ (địa chỉ) được lưu trữ trên điện thoại của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xóa hoặc sửa đổi dữ liệu liên hệ của bạn."</string>
<string name="permlab_readProfile" msgid="6824681438529842282">"đọc d.liệu t.sử của bạn"</string>
<string name="permdesc_readProfile" product="default" msgid="6335739730324727203">"Cho phép ứng dụng đọc thông tin tiểu sử cá nhân được lưu trên thiết bị của bạn, ví dụ như tên và thông tin liên hệ của bạn. Điều này nghĩa là ứng dụng có thể nhận dạng bạn và gửi thông tin tiểu sử của bạn cho những người khác."</string>
<string name="permlab_writeProfile" msgid="4679878325177177400">"ghi dữ liệu t.sử của bạn"</string>
@@ -364,9 +364,9 @@
<string name="permlab_camera" msgid="3616391919559751192">"chụp ảnh và quay video"</string>
<string name="permdesc_camera" msgid="6004878235852154239">"Cho phép ứng dụng chụp ảnh và quay video bằng máy ảnh. Quyền này cho phép ứng dụng thu thập ảnh mà máy ảnh chụp vào bất kỳ thời điểm nào."</string>
<string name="permlab_brick" product="tablet" msgid="2961292205764488304">"vô hiệu hóa vĩnh viễn máy tính bảng"</string>
- <string name="permlab_brick" product="default" msgid="8337817093326370537">"vĩnh viễn vô hiệu hoá điện thoại"</string>
+ <string name="permlab_brick" product="default" msgid="8337817093326370537">"vĩnh viễn vô hiệu hóa điện thoại"</string>
<string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Cho phép ứng dụng vô hiệu hóa vĩnh viễn toàn bộ máy tính bảng. Việc này rất nguy hiểm."</string>
- <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Cho phép ứng dụng vô hiệu hoá vĩnh viễn toàn bộ điện thoại. Việc này rất nguy hiểm."</string>
+ <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Cho phép ứng dụng vô hiệu hóa vĩnh viễn toàn bộ điện thoại. Việc này rất nguy hiểm."</string>
<string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"buộc máy tính bảng khởi động lại"</string>
<string name="permlab_reboot" product="default" msgid="2898560872462638242">"buộc khởi động lại điện thoại"</string>
<string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Cho phép ứng dụng buộc máy tính bảng khởi động lại."</string>
@@ -396,7 +396,7 @@
<string name="permlab_hardware_test" msgid="4148290860400659146">"kiểm tra phần cứng"</string>
<string name="permdesc_hardware_test" msgid="3668894686500081699">"Cho phép ứng dụng kiểm soát các thiết bị ngoại vi khác nhau nhằm mục đích kiểm tra phần cứng."</string>
<string name="permlab_callPhone" msgid="3925836347681847954">"gọi trực tiếp số điện thoại"</string>
- <string name="permdesc_callPhone" msgid="3369867353692722456">"Cho phép ứng dụng gọi các số điện thoại mà không cần sự can thiệp của bạn. Các ứng dụng độc hại có thể dẫn đến các cuộc gọi không mong muốn trên hoá đơn điện thoại của bạn. Lưu ý rằng quyền này không cho phép ứng dụng gọi các số khẩn cấp."</string>
+ <string name="permdesc_callPhone" msgid="3369867353692722456">"Cho phép ứng dụng gọi các số điện thoại mà không cần sự can thiệp của bạn. Các ứng dụng độc hại có thể dẫn đến các cuộc gọi không mong muốn trên hóa đơn điện thoại của bạn. Lưu ý rằng quyền này không cho phép ứng dụng gọi các số khẩn cấp."</string>
<string name="permlab_callPrivileged" msgid="4198349211108497879">"gọi trực tiếp số điện thoại bất kỳ"</string>
<string name="permdesc_callPrivileged" msgid="244405067160028452">"Cho phép ứng dụng gọi bất kỳ số điện thoại nào, kể cả số khẩn cấp mà không cần sự can thiệp của bạn. Các ứng dụng độc hại có thể thực hiện các cuộc gọi không cần thiết và bất hợp pháp vào dịch vụ khẩn cấp."</string>
<string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"trực tiếp bắt đầu thiết lập máy tính bảng CDMA"</string>
@@ -428,7 +428,7 @@
<string name="permlab_setWallpaperHints" msgid="3600721069353106851">"Đặt gợi ý kích thước hình nền"</string>
<string name="permdesc_setWallpaperHints" msgid="6019479164008079626">"Cho phép ứng dụng đặt gợi ý kích thước hình nền của hệ thống."</string>
<string name="permlab_masterClear" msgid="2315750423139697397">"đặt lại hệ thống về mặc định ban đầu"</string>
- <string name="permdesc_masterClear" msgid="5033465107545174514">"Cho phép ứng dụng đặt lại toàn bộ hệ thống về cài đặt ban đầu, xoá tất cả dữ liệu, cấu hình và ứng dụng đã cài đặt."</string>
+ <string name="permdesc_masterClear" msgid="5033465107545174514">"Cho phép ứng dụng đặt lại toàn bộ hệ thống về cài đặt ban đầu, xóa tất cả dữ liệu, cấu hình và ứng dụng đã cài đặt."</string>
<string name="permlab_setTime" msgid="2021614829591775646">"đặt giờ"</string>
<string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Cho phép ứng dụng thay đổi giờ trên đồng hồ của máy tính bảng."</string>
<string name="permdesc_setTime" product="default" msgid="667294309287080045">"Cho phép ứng dụng thay đổi giờ trên đồng hồ của điện thoại."</string>
@@ -443,7 +443,7 @@
<string name="permlab_authenticateAccounts" msgid="3940505577982882450">"hoạt động như trình xác thực tài khoản"</string>
<string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Cho phép ứng dụng sử dụng các tính năng của trình xác thực tài khoản của AccountManager, bao gồm tạo tài khoản, nhận và đặt mật khẩu của các tài khoản đó."</string>
<string name="permlab_manageAccounts" msgid="4440380488312204365">"quản lý danh sách tài khoản"</string>
- <string name="permdesc_manageAccounts" msgid="8804114016661104517">"Cho phép ứng dụng thực hiện các thao tác như thêm và xoá tài khoản cũng như xoá mật khẩu của các tài khoản đó."</string>
+ <string name="permdesc_manageAccounts" msgid="8804114016661104517">"Cho phép ứng dụng thực hiện các thao tác như thêm và xóa tài khoản cũng như xóa mật khẩu của các tài khoản đó."</string>
<string name="permlab_useCredentials" msgid="6401886092818819856">"sử dụng thông tin xác thực tài khoản"</string>
<string name="permdesc_useCredentials" msgid="7416570544619546974">"Cho phép ứng dụng yêu cầu mã thông báo xác thực."</string>
<string name="permlab_accessNetworkState" msgid="6865575199464405769">"xem trạng thái mạng"</string>
@@ -476,24 +476,24 @@
<string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Cho phép ứng dụng xem cấu hình của điện thoại Bluetooth nội hạt cũng như tạo và chấp nhận các kết nối với các thiết bị được ghép nối."</string>
<string name="permlab_nfc" msgid="4423351274757876953">"kiểm soát Liên lạc trường gần"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Cho phép ứng dụng liên lạc với thẻ Liên lạc trường gần (NFC), thẻ và trình đọc."</string>
- <string name="permlab_disableKeyguard" msgid="4977406164311535092">"vô hiệu hoá khoá phím"</string>
- <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Cho phép ứng dụng vô hiệu hoá khoá phím và bất kỳ bảo mật mật khẩu được liên kết nào. Ví dụ thích hợp của việc này là điện thoại vô hiệu hoá khoá phím khi nhận được cuộc gọi đến sau đó bật lại khoá phím khi cuộc gọi kết thúc."</string>
- <string name="permlab_readSyncSettings" msgid="6201810008230503052">"đọc cài đặt đồng bộ hoá"</string>
- <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Cho phép ứng dụng đọc cài đặt đồng bộ hoá, chẳng hạn như liệu đồng bộ hoá đã được bật cho Danh bạ hay chưa."</string>
- <string name="permlab_writeSyncSettings" msgid="6297138566442486462">"ghi cài đặt đồng bộ hoá"</string>
- <string name="permdesc_writeSyncSettings" msgid="2498201614431360044">"Cho phép ứng dụng sửa đổi cài đặt đồng bộ hoá, chẳng hạn như liệu đồng bộ hoá đã được bật cho Danh bạ chưa."</string>
- <string name="permlab_readSyncStats" msgid="7396577451360202448">"đọc thống kê đồng bộ hoá"</string>
- <string name="permdesc_readSyncStats" msgid="7511448343374465000">"Cho phép ứng dụng đọc thống kê đồng bộ hoá, ví dụ: lịch sử đồng bộ hoá đã diễn ra."</string>
+ <string name="permlab_disableKeyguard" msgid="4977406164311535092">"vô hiệu hóa khóa phím"</string>
+ <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Cho phép ứng dụng vô hiệu hóa khóa phím và bất kỳ bảo mật mật khẩu được liên kết nào. Ví dụ thích hợp của việc này là điện thoại vô hiệu hóa khóa phím khi nhận được cuộc gọi đến sau đó bật lại khóa phím khi cuộc gọi kết thúc."</string>
+ <string name="permlab_readSyncSettings" msgid="6201810008230503052">"đọc cài đặt đồng bộ hóa"</string>
+ <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Cho phép ứng dụng đọc cài đặt đồng bộ hóa, chẳng hạn như liệu đồng bộ hóa đã được bật cho Danh bạ hay chưa."</string>
+ <string name="permlab_writeSyncSettings" msgid="6297138566442486462">"ghi cài đặt đồng bộ hóa"</string>
+ <string name="permdesc_writeSyncSettings" msgid="2498201614431360044">"Cho phép ứng dụng sửa đổi cài đặt đồng bộ hóa, chẳng hạn như liệu đồng bộ hóa đã được bật cho Danh bạ chưa."</string>
+ <string name="permlab_readSyncStats" msgid="7396577451360202448">"đọc thống kê đồng bộ hóa"</string>
+ <string name="permdesc_readSyncStats" msgid="7511448343374465000">"Cho phép ứng dụng đọc thống kê đồng bộ hóa, ví dụ: lịch sử đồng bộ hóa đã diễn ra."</string>
<string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"đọc nguồn cấp dữ liệu đã đăng ký"</string>
- <string name="permdesc_subscribedFeedsRead" msgid="3622200625634207660">"Cho phép ứng dụng nhận các chi tiết về nguồn cấp dữ liệu hiện đã được đồng bộ hoá."</string>
+ <string name="permdesc_subscribedFeedsRead" msgid="3622200625634207660">"Cho phép ứng dụng nhận các chi tiết về nguồn cấp dữ liệu hiện đã được đồng bộ hóa."</string>
<string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"ghi nguồn cấp dữ liệu đã đăng ký"</string>
- <string name="permdesc_subscribedFeedsWrite" msgid="8121607099326533878">"Cho phép ứng dụng sửa đổi nguồn cấp dữ liệu hiện đã được đồng bộ hoá. Quyền này có thể cho phép ứng dụng độc hại thay đổi nguồn cấp dữ liệu đã đồng bộ hoá của bạn."</string>
+ <string name="permdesc_subscribedFeedsWrite" msgid="8121607099326533878">"Cho phép ứng dụng sửa đổi nguồn cấp dữ liệu hiện đã được đồng bộ hóa. Quyền này có thể cho phép ứng dụng độc hại thay đổi nguồn cấp dữ liệu đã đồng bộ hóa của bạn."</string>
<string name="permlab_readDictionary" msgid="432535716804748781">"đọc từ điển do người dùng xác định"</string>
<string name="permdesc_readDictionary" msgid="1082972603576360690">"Cho phép ứng dụng đọc bất kỳ từ, tên và cụm từ riêng nào mà người dùng có thể đã lưu trữ trong từ điển của người dùng."</string>
<string name="permlab_writeDictionary" msgid="6703109511836343341">"ghi vào từ điển do người dùng xác định"</string>
<string name="permdesc_writeDictionary" msgid="2241256206524082880">"Cho phép ứng dụng ghi từ mới vào từ điển của người dùng."</string>
<string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"sửa đổi/xóa nội dung bộ nhớ USB"</string>
- <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"sửa đổi/xoá nội dung thẻ SD"</string>
+ <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"sửa đổi/xóa nội dung thẻ SD"</string>
<string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"C.phép ứ.dụng ghi vào b.nhớ USB."</string>
<string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Cho phép ứng dụng ghi vào thẻ SD."</string>
<string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"sửa đổi/xóa nội dung trên bộ nhớ phương tiện cục bộ"</string>
@@ -517,7 +517,7 @@
<string name="policydesc_resetPassword" msgid="5391240616981297361">"Thay đổi mật khẩu mở khóa màn hình"</string>
<string name="policylab_forceLock" msgid="2274085384704248431">"Khóa màn hình"</string>
<string name="policydesc_forceLock" msgid="5696964126226028442">"Kiểm tra cách và thời điểm khóa màn hình"</string>
- <string name="policylab_wipeData" msgid="3910545446758639713">"Xoá tất cả dữ liệu"</string>
+ <string name="policylab_wipeData" msgid="3910545446758639713">"Xóa tất cả dữ liệu"</string>
<string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Xóa dữ liệu trên máy tính bảng mà không cần cảnh báo, bằng cách thực hiện đặt lại về dữ liệu gốc"</string>
<string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Xóa dữ liệu trên điện thoại mà không cần cảnh báo, bằng cách thực hiện đặt lại về dữ liệu gốc"</string>
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Đặt proxy chung của điện thoại"</string>
@@ -646,16 +646,16 @@
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Mã PUK"</string>
<string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Mã Pin mới"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Chạm để nhập mật khẩu"</font></string>
- <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Nhập mật khẩu để mở khoá"</string>
+ <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Nhập mật khẩu để mở khóa"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Nhập PIN để mở khóa"</string>
<string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Mã PIN không chính xác!"</string>
- <string name="keyguard_label_text" msgid="861796461028298424">"Để mở khoá, hãy nhấn vào Trình đơn sau đó nhấn 0."</string>
+ <string name="keyguard_label_text" msgid="861796461028298424">"Để mở khóa, hãy nhấn vào Trình đơn sau đó nhấn 0."</string>
<string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Số khẩn cấp"</string>
<string name="lockscreen_carrier_default" msgid="8963839242565653192">"Không có dịch vụ nào."</string>
- <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Màn hình đã khoá."</string>
- <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Nhấn vào Trình đơn để mở khoá hoặc thực hiện cuộc gọi khẩn cấp."</string>
- <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Nhấn vào Trình đơn để mở khoá."</string>
- <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Vẽ hình để mở khoá"</string>
+ <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Màn hình đã khóa."</string>
+ <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Nhấn vào Trình đơn để mở khóa hoặc thực hiện cuộc gọi khẩn cấp."</string>
+ <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Nhấn vào Trình đơn để mở khóa."</string>
+ <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Vẽ hình để mở khóa"</string>
<string name="lockscreen_emergency_call" msgid="5347633784401285225">"Cuộc gọi khẩn cấp"</string>
<string name="lockscreen_return_to_call" msgid="5244259785500040021">"Quay lại cuộc gọi"</string>
<string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Chính xác!"</string>
@@ -677,32 +677,32 @@
<string name="lockscreen_transport_play_description" msgid="5888422938351019426">"Nút phát"</string>
<string name="lockscreen_transport_stop_description" msgid="4562318378766987601">"Nút dừng"</string>
<string name="emergency_calls_only" msgid="6733978304386365407">"Chỉ cuộc gọi khẩn cấp"</string>
- <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Mạng đã khoá"</string>
- <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Thẻ SIM đã bị khoá PUK."</string>
+ <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Mạng đã khóa"</string>
+ <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Thẻ SIM đã bị khóa PUK."</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="635967534992394321">"Vui lòng xem Hướng dẫn Người dùng hoặc liên hệ với Trung tâm Chăm sóc Khách hàng."</string>
- <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Thẻ SIM đã bị khoá."</string>
- <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Đang mở khoá thẻ SIM…"</string>
- <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Bạn đã vẽ không chính xác hình mở khoá của mình <xliff:g id="NUMBER_0">%d</xliff:g> lần. "\n\n"Vui lòng thử lại sau <xliff:g id="NUMBER_1">%d</xliff:g> giây."</string>
+ <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Thẻ SIM đã bị khóa."</string>
+ <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Đang mở khóa thẻ SIM…"</string>
+ <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Bạn đã vẽ không chính xác hình mở khóa của mình <xliff:g id="NUMBER_0">%d</xliff:g> lần. "\n\n"Vui lòng thử lại sau <xliff:g id="NUMBER_1">%d</xliff:g> giây."</string>
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Bạn đã nhập sai mật khẩu <xliff:g id="NUMBER_0">%d</xliff:g> lần. "\n\n"Vui lòng thử lại trong <xliff:g id="NUMBER_1">%d</xliff:g> giấy."</string>
<string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Bạn đã nhập sai PIN <xliff:g id="NUMBER_0">%d</xliff:g> lần. "\n\n"Vui lòng thử lại trong <xliff:g id="NUMBER_1">%d</xliff:g> giây."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Bạn đã vẽ không chính xác hình mở khóa của mình <xliff:g id="NUMBER_0">%d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần thử không thành công khác, bạn sẽ được yêu cầu mở khóa máy tính bảng bằng thông tin đăng nhập Google của mình."\n\n" Vui lòng thử lại trong <xliff:g id="NUMBER_2">%d</xliff:g> giây."</string>
- <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Bạn đã vẽ không chính xác hình mở khoá của mình <xliff:g id="NUMBER_0">%d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần thử không thành công khác, bạn sẽ được yêu cầu mở khoá điện thoại bằng thông tin đăng nhập Google của mình."\n\n" Vui lòng thử lại trong <xliff:g id="NUMBER_2">%d</xliff:g> giây."</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Bạn đã vẽ không chính xác hình mở khóa của mình <xliff:g id="NUMBER_0">%d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần thử không thành công khác, bạn sẽ được yêu cầu mở khóa điện thoại bằng thông tin đăng nhập Google của mình."\n\n" Vui lòng thử lại trong <xliff:g id="NUMBER_2">%d</xliff:g> giây."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Bạn đã mở khóa máy tính bảng không đúng cách <xliff:g id="NUMBER_0">%d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần mở khóa không thành công nữa, máy tính bảng sẽ được đặt lại về mặc định ban đầu và tất cả dữ liệu người dùng sẽ bị mất."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Bạn đã mở khóa điện thoại không đúng cách <xliff:g id="NUMBER_0">%d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần mở khóa không thành công nữa, điện thoại sẽ được đặt lại về mặc định ban đầu và tất cả dữ liệu người dùng sẽ bị mất."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"Bạn đã mở khóa máy tính bảng không đúng cách <xliff:g id="NUMBER">%d</xliff:g> lần. Bây giờ, máy tính bảng sẽ được đặt lại về mặc định ban đầu."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Bạn đã mở khóa điện thoại không đúng cách <xliff:g id="NUMBER">%d</xliff:g> lần. Bây giờ, điện thoại sẽ được đặt lại về mặc định ban đầu."</string>
<string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Hãy thử lại sau <xliff:g id="NUMBER">%d</xliff:g> giây."</string>
<string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Đã quên hình?"</string>
- <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Mở khoá tài khoản"</string>
+ <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Mở khóa tài khoản"</string>
<string name="lockscreen_glogin_too_many_attempts" msgid="2446246026221678244">"Quá nhiều lần nhập hình!"</string>
- <string name="lockscreen_glogin_instructions" msgid="1816635201812207709">"Để mở khoá, hãy đăng nhập bằng tài khoản Google của bạn"</string>
+ <string name="lockscreen_glogin_instructions" msgid="1816635201812207709">"Để mở khóa, hãy đăng nhập bằng tài khoản Google của bạn"</string>
<string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Tên người dùng (email)"</string>
<string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"Mật khẩu"</string>
<string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Đăng nhập"</string>
<string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Tên người dùng hoặc mật khẩu không hợp lệ."</string>
<string name="lockscreen_glogin_account_recovery_hint" msgid="8253152905532900548">"Bạn quên tên người dùng hoặc mật khẩu?"\n"Hãy truy cập "<b>"google.com/accounts/recovery"</b></string>
<string name="lockscreen_glogin_checking_password" msgid="6758890536332363322">"Đang kiểm tra..."</string>
- <string name="lockscreen_unlock_label" msgid="737440483220667054">"Mở khoá"</string>
+ <string name="lockscreen_unlock_label" msgid="737440483220667054">"Mở khóa"</string>
<string name="lockscreen_sound_on_label" msgid="9068877576513425970">"Bật âm thanh"</string>
<string name="lockscreen_sound_off_label" msgid="996822825154319026">"Tắt âm thanh"</string>
<string name="lockscreen_access_pattern_start" msgid="3941045502933142847">"Đã bắt đầu vẽ hình"</string>
@@ -745,7 +745,7 @@
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Cho phép ứng dụng đọc tất cả các URL mà Trình duyệt đã truy cập và tất cả các dấu trang của Trình duyệt."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"xem lịch sử và dấu trang của Trình duyệt"</string>
<string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Cho phép ứng dụng sửa đổi lịch sử hoặc dấu trang của Trình duyệt được lưu trữ trên máy tính bảng của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xóa hoặc sửa đổi dữ liệu Trình duyệt của bạn."</string>
- <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Cho phép ứng dụng sửa đổi lịch sử hoặc dấu trang của Trình duyệt được lưu trữ trên điện thoại của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xoá hoặc sửa đổi dữ liệu Trình duyệt của bạn."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Cho phép ứng dụng sửa đổi lịch sử hoặc dấu trang của Trình duyệt được lưu trữ trên điện thoại của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xóa hoặc sửa đổi dữ liệu Trình duyệt của bạn."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"đặt báo thức trong đồng hồ báo thức"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Cho phép ứng dụng đặt báo thức trong ứng dụng đồng hồ báo thức được cài đặt. Một số ứng dụng đồng hồ báo thức có thể không sử dụng tính năng này."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"thêm thư thoại"</string>
@@ -766,7 +766,7 @@
<string name="prepend_shortcut_label" msgid="2572214461676015642">"Trình đơn+"</string>
<string name="menu_space_shortcut_label" msgid="2410328639272162537">"dấu cách"</string>
<string name="menu_enter_shortcut_label" msgid="2743362785111309668">"nhập"</string>
- <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"xoá"</string>
+ <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"xóa"</string>
<string name="search_go" msgid="8298016669822141719">"Tìm kiếm"</string>
<string name="searchview_description_search" msgid="6749826639098512120">"Tìm kiếm"</string>
<string name="searchview_description_query" msgid="5911778593125355124">"Truy vấn tìm kiếm"</string>
@@ -896,7 +896,7 @@
<string name="capital_off" msgid="6815870386972805832">"TẮT"</string>
<string name="whichApplication" msgid="4533185947064773386">"Hoàn tất tác vụ đang sử dụng"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Sử dụng theo mặc định đối với tác vụ này."</string>
- <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Xoá mặc định trong Cài đặt Màn hình trang chủ > Ứng dụng> Quản lý ứng dụng."</string>
+ <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Xóa mặc định trong Cài đặt Màn hình trang chủ > Ứng dụng> Quản lý ứng dụng."</string>
<string name="chooseActivity" msgid="1009246475582238425">"Chọn tác vụ"</string>
<string name="chooseUsbActivity" msgid="7892597146032121735">"Chọn ứng dụng cho thiết bị USB"</string>
<string name="noApplications" msgid="1691104391758345586">"Không ứng dụng nào có thể thực hiện tác vụ này."</string>
@@ -1019,7 +1019,7 @@
<string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Bạn có chắc chắn muốn định dạng thẻ SD không? Tất cả dữ liệu trên thẻ của bạn sẽ bị mất."</string>
<string name="extmedia_format_button_format" msgid="4131064560127478695">"Định dạng"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Gỡ lỗi USB đã được kết nối"</string>
- <string name="adb_active_notification_message" msgid="8470296818270110396">"Chọn để vô hiệu hoá gỡ lỗi USB."</string>
+ <string name="adb_active_notification_message" msgid="8470296818270110396">"Chọn để vô hiệu hóa gỡ lỗi USB."</string>
<string name="select_input_method" msgid="6865512749462072765">"Chọn phương thức nhập"</string>
<string name="configure_input_methods" msgid="6324843080254191535">"Định cấu hình phương thức nhập liệu"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1072,7 +1072,7 @@
<string name="permission_request_notification_title" msgid="5390555465778213840">"Yêu cầu Quyền"</string>
<string name="permission_request_notification_with_subtitle" msgid="4325409589686688000">"Yêu cầu Quyền"\n"cho tài khoản <xliff:g id="ACCOUNT">%s</xliff:g>"</string>
<string name="input_method_binding_label" msgid="1283557179944992649">"Phương thức nhập"</string>
- <string name="sync_binding_label" msgid="3687969138375092423">"Đồng bộ hoá"</string>
+ <string name="sync_binding_label" msgid="3687969138375092423">"Đồng bộ hóa"</string>
<string name="accessibility_binding_label" msgid="4148120742096474641">"Khả năng truy cập"</string>
<string name="wallpaper_binding_label" msgid="1240087844304687662">"Hình nền"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"Thay đổi hình nền"</string>
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"Chia sẻ với..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Thiết bị đã bị khóa."</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"Đang gửi..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Khởi chạy trình duyệt?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"Chấp nhận cuộc gọi?"</string>
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index b92008f..12b1784 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"分享方式..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"设备已锁定。"</string>
<string name="list_delimeter" msgid="3975117572185494152">"、 "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"正在发送..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"要启动浏览器吗?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"要接听电话吗?"</string>
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 80c3ee5..1252ba1 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1218,10 +1218,7 @@
<string name="share_action_provider_share_with" msgid="1791316789651185229">"分享活動..."</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"裝置已鎖定。"</string>
<string name="list_delimeter" msgid="3975117572185494152">"、 "</string>
- <!-- no translation found for sending (8715108995741758718) -->
- <skip />
- <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
- <skip />
- <!-- no translation found for SetupCallDefault (6870275517518479651) -->
- <skip />
+ <string name="sending" msgid="8715108995741758718">"傳送中..."</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"要啟動「瀏覽器」嗎?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"要接受通話嗎?"</string>
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index eadb0ea..eb9e660 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -73,11 +73,11 @@
<string name="RestrictedOnData" msgid="8653794784690065540">"Insizakalo yedatha ivaliwe."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Insizakalo ephuthumayo ivimbelwe."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Insizakalo yezwi ivimbelwe."</string>
- <string name="RestrictedOnAllVoice" msgid="1459318899842232234">"Zonke izinsizakalo Zezwi zivimbelwe."</string>
+ <string name="RestrictedOnAllVoice" msgid="1459318899842232234">"Wonke amasevisi Wezwi avimbelwe."</string>
<string name="RestrictedOnSms" msgid="8314352327461638897">"Insizakalo ye-SMS ivaliwe."</string>
- <string name="RestrictedOnVoiceData" msgid="8244438624660371717">"Izinsizakalo Zezwi/Idatha zivimbelwe."</string>
- <string name="RestrictedOnVoiceSms" msgid="1888588152792023873">"Izinsizakalo Zezwi/SMS zivimbelwe."</string>
- <string name="RestrictedOnAll" msgid="2714924667937117304">"Zonke izinsizakalo Zezwi/Idatha/SMS zivimbelwe."</string>
+ <string name="RestrictedOnVoiceData" msgid="8244438624660371717">"Amasevisi Wezwi/Idatha avimbelwe."</string>
+ <string name="RestrictedOnVoiceSms" msgid="1888588152792023873">"Amasevisi Wezwi/SMS avimbelwe."</string>
+ <string name="RestrictedOnAll" msgid="2714924667937117304">"Wonke amasevisi Wezwi/Idatha/SMS avimbelwe."</string>
<string name="serviceClassVoice" msgid="1258393812335258019">"Izwi"</string>
<string name="serviceClassData" msgid="872456782077937893">"Idatha"</string>
<string name="serviceClassFAX" msgid="5566624998840486475">"Ifeksi"</string>
@@ -99,7 +99,7 @@
<string name="roamingText10" msgid="3992906999815316417">"Iyazulazula - Isici Sensizakalo Eyingxenye"</string>
<string name="roamingText11" msgid="4154476854426920970">"Ibhena Yokuzulazula Ivuliwe"</string>
<string name="roamingText12" msgid="1189071119992726320">"Ibhena yokuzulazula ivaliwe"</string>
- <string name="roamingTextSearching" msgid="8360141885972279963">"Iseshela Izinsizakalo"</string>
+ <string name="roamingTextSearching" msgid="8360141885972279963">"Iseshela Isevisi"</string>
<string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Akudlulisiwe"</string>
<string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> emuva kwamasekhondi angu-<xliff:g id="TIME_DELAY">{2}</xliff:g>"</string>
@@ -463,7 +463,7 @@
<string name="permlab_changeWifiState" msgid="7280632711057112137">"shintsha isimo se-WiFi"</string>
<string name="permdesc_changeWifiState" msgid="2950383153656873267">"Ivumela uhlelo lokusebena ukuxhuma futhi ingaxhumeki kumaphoyinti e-Wi-Fi, nokwenza izinguquko kumanethiwekhi e-Wi-Fi amisiwe."</string>
<string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"ivumela isamukeli se-Wi-Fi Multicast"</string>
- <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Ivumela uhlelo lokusebenza ukuthola amaphakhethe ngokungaqondile angeyona awedivaysi yakho. Lokhu kungaba usizo lapho uthola izinsizakalo ezinikezwa eduze. Kusebenzisa amandla amaninigi kunemodi yokungajikijeli okuningi."</string>
+ <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Ivumela uhlelo lokusebenza ukuthola amaphakhethe ngokungaqondile angeyona awedivaysi yakho. Lokhu kungaba usizo lapho uthola amasevisi anikezwa eduze. Kusebenzisa amandla amaninigi kunemodi yokungajikijeli okuningi."</string>
<string name="permlab_accessWimaxState" msgid="2800410363171809280">"Buka isimo se-WiMAX"</string>
<string name="permdesc_accessWimaxState" msgid="8298035866227524023">"Ivumela uhlelo lokusebenza ukubuka ulwazi mayelana nesimo se-WiMAX."</string>
<string name="permlab_changeWimaxState" msgid="340465839241528618">"shintsha isimo se-WiMAX"</string>
@@ -852,7 +852,7 @@
<string name="hour" msgid="2126771916426189481">"ihora"</string>
<string name="hours" msgid="894424005266852993">"amahora"</string>
<string name="minute" msgid="9148878657703769868">"Okuncane"</string>
- <string name="minutes" msgid="5646001005827034509">"imizuzu"</string>
+ <string name="minutes" msgid="5646001005827034509">"amaminithi"</string>
<string name="second" msgid="3184235808021478">"isekhondi"</string>
<string name="seconds" msgid="3161515347216589235">"amasekhondi"</string>
<string name="week" msgid="5617961537173061583">"iviki"</string>
@@ -968,7 +968,7 @@
<string name="wifi_p2p_pin_go_negotiation_request_message" msgid="5177412094633377308">"Isethaphu yoheloxhumano oluqondile lwe-WiFi lwesicelo kusuka ku <xliff:g id="P2P_DEVICE_ADDRESS">%1$s</xliff:g>. Faka i-pin ukuze uqhubeke"</string>
<string name="wifi_p2p_pin_display_message" msgid="2834049169114922902">"i-pin ye-WPS <xliff:g id="P2P_WPS_PIN">%1$s</xliff:g> idinga ukufakiwa kudivayisi ye-peer <xliff:g id="P2P_CLIENT_ADDRESS">%2$s</xliff:g> ukuze isethaphu yohleloxhumano iqhubeke"</string>
<string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"I-Wi-Fi Direct ivulekile"</string>
- <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Thinta ze uthole izisetho"</string>
+ <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Thinta ukuze uthole izilungiselelo"</string>
<string name="select_character" msgid="3365550120617701745">"Faka uhlamvu"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Uhlelo lokusebenza olungaziwa"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Ithumela imiyalezo ye-SMS"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 767cafe..25f7d25 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -741,4 +741,7 @@
<string name="config_wimaxServiceClassname"></string>
<!-- Name of the wimax state tracker clas -->
<string name="config_wimaxStateTrackerClassname"></string>
+
+ <!-- Name of screensaver components to look for if none has been chosen by the user -->
+ <string name="config_defaultDreamComponent">com.google.android.deskclock/com.android.deskclock.Screensaver</string>
</resources>
diff --git a/docs/html/guide/appendix/market-filters.jd b/docs/html/guide/appendix/market-filters.jd
index dc79d95..6610f5f 100644
--- a/docs/html/guide/appendix/market-filters.jd
+++ b/docs/html/guide/appendix/market-filters.jd
@@ -25,7 +25,7 @@
</ol>
<h2>See also</h2>
- <ol>
+ <ol>
<li><a
href="{@docRoot}guide/practices/compatibility.html">Android Compatibility</a></li>
<li><code><a
@@ -48,7 +48,7 @@
<img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png">
<div id="qv-sub-rule">
<img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0 5px;">
- <h2 style="color:#669999;">Interested in publishing your app on Android Market?</h2>
+ <h2 style="color:#669999;">Interested in publishing your app on Android Market?</h2>
<p><a id="publish-link"
href="http://market.android.com/publish">Go to Android Market</a> to create a publisher
account and upload your app.</p></div>
@@ -83,7 +83,7 @@
manifest file and publishing details. If the application is
compatible with the device according to the filter rules, Market displays the
application to the user. Otherwise, Market hides your application from search
-results and category browsing, even if a user specifically requests
+results and category browsing, even if a user specifically requests
the app by clicking a deep link that points directly to the app's ID within Market..</p>
<p class="note"><strong>Note:</strong> When users browse the <a
@@ -108,7 +108,7 @@
<p>Most Market filters are triggered by elements within an application's
manifest file, <a
-href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a>
+href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a>
(although not everything in the manifest file can trigger filtering).
Table 1 lists the manifest elements that you should use to trigger Android
Market filtering, and explains how the filtering for each element works.</p>
@@ -173,7 +173,7 @@
</strong>The manifest declares <code><uses-sdk android:minSdkVersion="3"
android:targetSdkVersion="4"></code> and does not include a
<code><supports-screens></code> element.
- <strong>Result</strong>: Android Market will show the app to users on all
+ <strong>Result</strong>: Android Market will show the app to users on all
devices, unless other filters apply. </p>
<p><strong>Example 3<br />
</strong>The manifest declares <code><uses-sdk android:minSdkVersion="4"></code>
@@ -402,9 +402,9 @@
visible on devices that support that platform. For details about the NDK and using
native libraries, see <a href="{@docRoot}sdk/ndk/index.html#overview">What is the
Android NDK?</a></p> </tr> <tr>
- <td valign="top">Forward-Locked Applications</td> <td valign="top"><p>To
- forward lock an application, set copy protection to "On" when you upload the
- application to Market. Market will not show copy-protected applications on
+ <td valign="top">Copy-Protected Applications</td> <td valign="top"><p>To
+ copy protect an application, set copy protection to "On" when you configure publishing
+options for your application. Market will not show copy-protected applications on
developer devices or unreleased devices.</p></td> </tr> </table>
@@ -431,7 +431,7 @@
<p>By using the <a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
<supports-screens>}</a> or <a
href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
-<compatible-screens>}</a> element.</p>
+<compatible-screens>}</a> element.</p>
</li>
<li>API level
<p>By using the <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index af379de..3eb7286 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -119,7 +119,7 @@
</a></li>
<li><a href="<?cs var:toroot ?>guide/topics/ui/actionbar.html">
<span class="en">Action Bar</span>
- </a></li>
+ </a> <span class="new">updated</span></li>
<li><a href="<?cs var:toroot ?>guide/topics/ui/dialogs.html">
<span class="en">Dialogs</span>
</a></li>
@@ -739,21 +739,21 @@
<ul>
<li class="toggle-list">
<div><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/icon_design.html">
- <span class="en">Icon Design <span class="new">updated</span></span>
- </a></div>
+ <span class="en">Icon Design</span>
+ </a> <span class="new">updated</span></div>
<ul>
<li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/icon_design_launcher.html">
- <span class="en">Launcher Icons <span class="new">updated</span></span>
- </a></li>
+ <span class="en">Launcher Icons</span>
+ </a> <span class="new">updated</span></li>
<li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/icon_design_menu.html">
<span class="en">Menu Icons</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/icon_design_action_bar.html">
- <span class="en">Action Bar Icons <span class="new">new!</span></span>
- </a></li>
+ <span class="en">Action Bar Icons</span>
+ </a> <span class="new">new!</span></li>
<li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/icon_design_status_bar.html">
- <span class="en">Status Bar Icons <span class="new">updated</span></span>
- </a></li>
+ <span class="en">Status Bar Icons</span>
+ </a> <span class="new">updated</span></li>
<li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/icon_design_tab.html">
<span class="en">Tab Icons</span>
</a></li>
@@ -766,8 +766,8 @@
</ul>
</li>
<li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/widget_design.html">
- <span class="en">App Widget Design <span class="new">updated</span></span>
- </a></li>
+ <span class="en">App Widget Design</span>
+ </a> <span class="new">updated</span></li>
<li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/activity_task_design.html">
<span class="en">Activity and Task Design</span>
</a></li>
@@ -844,8 +844,8 @@
<span class="en">App Install Location</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/appendix/media-formats.html">
- <span class="en">Supported Media Formats <span class="new">updated</span></span>
- </a></li>
+ <span class="en">Supported Media Formats</span>
+ </a> <span class="new">updated</span></li>
<li><a href="<?cs var:toroot ?>guide/appendix/g-app-intents.html">
<span class="en">Intents List: Google Apps</span>
</a></li>
diff --git a/docs/html/guide/practices/tablets-and-handsets.jd b/docs/html/guide/practices/tablets-and-handsets.jd
index 7bc1ad7..dc35801 100644
--- a/docs/html/guide/practices/tablets-and-handsets.jd
+++ b/docs/html/guide/practices/tablets-and-handsets.jd
@@ -372,9 +372,8 @@
value</strong>. In your <a
href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a>, use {@code "ifRoom"}
for the {@code android:showAsAction} attribute if you'd like the menu item to appear in the action
-bar. However, you might need {@code "always"} when an action view does not provide an alternative
-action for the overflow menu (that is, it must appear as an action view) or when a menu item added
-by a fragment is low in the menu order and it must jump into the action bar at all times. However,
+bar. However, you might need {@code "always"} when an action view does not provide a default
+action for the overflow menu (that is, it must appear as an action view). However,
you should not use {@code "always"} more than once or twice. In almost all other cases, use {@code
"ifRoom"} as the value for {@code "android:showAsAction"} when you want the item to appear as an
action item. Forcing too many action items into the action bar can create a cluttered UI and
diff --git a/docs/html/guide/publishing/licensing.jd b/docs/html/guide/publishing/licensing.jd
index fc0de9d..609241b 100644
--- a/docs/html/guide/publishing/licensing.jd
+++ b/docs/html/guide/publishing/licensing.jd
@@ -100,9 +100,14 @@
<h4>Application, Android Market client, and server</h4>
<p>The licensing service is based on the capability of the Android Market server
-to determine whether a given user is licensed to use a given application. The
-server considers a user licensed if the user is recorded to have purchased the
-application, or if the application is available for free. To properly identify
+to determine whether a given user is licensed to use a given application. The licensing server
+considers a user to be licensed if the user is a recorded purchaser of an application. If a paid
+application has been uploaded to Android Market but saved only as a draft application (in
+other words, the app is unpublished), the licensing server considers all users to be licensed users
+of the application. Keep in mind, you cannot implement Android Market Licensing in a free
+application.</p>
+
+<p>To properly identify
the user and determine the license status, the server requires information about
the application and user — the application and the Android Market client
work together to assemble the information and pass it to the server. </p>
@@ -243,7 +248,7 @@
<ul>
<li>Only paid applications published through Market can use the
-service. </li>
+service.</li>
<li>An application can use the service only if the Android Market client is
installed on its host device and the device is running Android 1.5 (API level 3)
or higher.</li>
@@ -258,8 +263,8 @@
secure.</li>
<li>Adding licensing to an application does not affect the way the application
functions when run on a device that does not offer Android Market.</li>
-<li>Licensing is currently for paid apps only, since free apps are considered
-licensed for all users. If your application is already published as free,
+<li>Licensing is currently for paid apps only, since draft apps are
+licensed for all users. If your application is already published as a free app,
you won't be able to upload a new version that uses licensing.</li>
</ul>
@@ -698,7 +703,7 @@
<p>Next, open the application's project properties window, as shown below.
Select the "Android" properties group and click <strong>Add</strong>, then
choose the LVL library project (com_android_vending_licensing) and click
-<strong>OK</strong>. For more information, see
+<strong>OK</strong>. For more information, see
<a href="{@docRoot}guide/developing/projects/projects-eclipse.html#SettingUpLibraryProject">
Managing Projects from Eclipse with ADT</a></p>.
@@ -727,7 +732,7 @@
--library <em>path/to/my/library_project</em>
</pre>
-<p>For more information about working with library projects,
+<p>For more information about working with library projects,
see <a href="{@docRoot}guide/developing/projects/projects-cmdline.html#SettingUpLibraryProject">
Managing Projects from the Command Line</a></p>.
@@ -1226,6 +1231,8 @@
<li>Otherwise, the LicenseChecker initiates a license check request that is sent
to the licensing server.</li>
</ul>
+<p class="note"><strong>Note:</strong> The licensing server always returns
+<code>LICENSED</code> when you perform a license check of a draft application.</p>
</li>
<li>When a response is received, LicenseChecker creates a LicenseValidator that
verifies the signed license data and extracts the fields of the response, then
@@ -1384,7 +1391,7 @@
</ol>
<p>If you want your LicenseCheckerCallback methods to update the UI thread,
-instantiate a {@link android.os.Handler} in the main Activity's
+instantiate a {@link android.os.Handler} in the main Activity's
{@link android.app.Activity#onCreate(android.os.Bundle) onCreate()} method,
as shown below. In this example, the LVL sample application's
LicenseCheckerCallback methods (see above) call <code>displayResult()</code> to
@@ -2338,7 +2345,7 @@
</p>
<p>In general, the RETRY response code is a signal to the application that an
-error has occurred that has prevented a license check from completing.
+error has occurred that has prevented a license check from completing.
<p>The Android Market server helps an application to manage licensing under
error conditions by setting a retry "grace period" and a recommended maximum
diff --git a/docs/html/guide/topics/media/camera.jd b/docs/html/guide/topics/media/camera.jd
index 877bded..b962f96 100644
--- a/docs/html/guide/topics/media/camera.jd
+++ b/docs/html/guide/topics/media/camera.jd
@@ -29,6 +29,15 @@
</ol>
</li>
<li><a href="#saving-media">Saving Media Files</a></li>
+ <li><a href="#camera-features">Camera Features</a>
+ <ol>
+ <li><a href="#check-feature">Checking feature availability</a></li>
+ <li><a href="#using-features">Using camera features</a></li>
+ <li><a href="#metering-focus-areas">Metering and focus areas</a></li>
+ <li><a href="#face-detection">Face detection</a></li>
+ <li><a href="#time-lapse-video">Time lapse video</a></li>
+ </ol>
+ </li>
</ol>
<h2>Key Classes</h2>
<ol>
@@ -39,8 +48,7 @@
</ol>
<h2>See also</h2>
<ol>
- <li><a href="{@docRoot}reference/android/hardware/Camera.html">Camera</a></li>
- <li><a href="{@docRoot}reference/android/media/MediaRecorder.html">MediaRecorder</a></li>
+ <li><a href="{@docRoot}guide/topics/media/mediaplayer.html">Media Playback</a></li>
<li><a href="{@docRoot}guide/topics/data/data-storage.html">Data Storage</a></li>
</ol>
</div>
@@ -64,7 +72,7 @@
<li><strong>Quick Picture or Customized Camera</strong> - How will your application use the
camera? Are you just interested in snapping a quick picture or video clip, or will your application
-provide a new way to use cameras? For a getting a quick snap or clip, consider
+provide a new way to use cameras? For a getting a quick snap or clip, consider
<a href="#intents">Using Existing Camera Apps</a>. For developing a customized camera feature, check
out the <a href="#custom-camera">Building a Camera App</a> section.</li>
@@ -85,7 +93,7 @@
<dl>
<dt>{@link android.hardware.Camera}</dt>
<dd>This class is the primary API for controlling device cameras. This class is used to take
-pictures or videos when you are building a camera application.</a>.</dd>
+pictures or videos when you are building a camera application.</dd>
<dt>{@link android.view.SurfaceView}</dt>
<dd>This class is used to present a live camera preview to the user.</dd>
@@ -120,8 +128,8 @@
<pre>
<uses-feature android:name="android.hardware.camera" />
</pre>
- <p>For a list of camera features, see the manifest <a
-href="{@docRoot}guide/topics/manifest/uses-feature-element.html#features-reference">Features
+ <p>For a list of camera features, see the manifest
+<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#hw-features">Features
Reference</a>.</p>
<p>Adding camera features to your manifest causes Android Market to prevent your application from
being installed to devices that do not include a camera or do not support the camera features you
@@ -148,6 +156,15 @@
<uses-permission android:name="android.permission.RECORD_AUDIO" />
</pre>
</li>
+ <li><strong>Location Permission</strong> - If your application tags images with GPS location
+information, you must request location permission:
+<pre>
+<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+</pre>
+<p>For more information about getting user location, see
+<a href="{@docRoot}guide/topics/location/obtaining-user-location.html">Obtaining User
+Location</a>.</p>
+ </li>
</ul>
@@ -224,8 +241,8 @@
your application, and you must intercept the {@link
android.app.Activity#onActivityResult(int, int, android.content.Intent) onActivityResult()}
method to receive the result of the intent and continue your application execution. For information
-on how to receive the completed intent, see <a href="#intent-receive">Receiving Camera Intent
-Result</a>.</p>
+on how to receive the completed intent, see <a href="#intent-receive">Receiving camera intent
+result</a>.</p>
<h3 id="intent-video">Video capture intent</h3>
@@ -360,8 +377,8 @@
<p>Camera hardware is a shared resource that must be carefully managed so your application does
not collide with other applications that may also want to use it. The following sections discusses
-how to detect camera hardware, how to request access to a camera and how to release it when your
-application is done using it.</p>
+how to detect camera hardware, how to request access to a camera, how to capture pictures or video
+and how to release the camera when your application is done using it.</p>
<p class="caution"><strong>Caution:</strong> Remember to release the {@link android.hardware.Camera}
object by calling the {@link android.hardware.Camera#release() Camera.release()} when your
@@ -492,7 +509,8 @@
// ignore: tried to stop a non-existent preview
}
- // make any resize, rotate or reformatting changes here
+ // set preview size and make any resize, rotate or
+ // reformatting changes here
// start preview with new settings
try {
@@ -506,6 +524,12 @@
}
</pre>
+<p>If you want to set a specific size for your camera preview, set this in the {@code
+surfaceChanged()} method as noted in the comments above. When setting preview size, you
+<em>must use</em> values from {@link android.hardware.Camera.Parameters#getSupportedPreviewSizes}.
+<em>Do not</em> set arbitrary values in the {@link
+android.hardware.Camera.Parameters#setPreviewSize setPreviewSize()} method.</p>
+
<h3 id="preview-layout">Placing preview in a layout</h3>
<p>A camera preview class, such as the example shown in the previous section, must be placed in the
@@ -780,6 +804,10 @@
since users typically prefer to see a preview before starting a recording, that process is not
discussed here.</p>
+<p class="note"><strong>Tip:</strong> If your application is typically used for recording video, set
+{@link android.hardware.Camera.Parameters#setRecordingHint} to {@code true} prior to starting your
+preview. This setting can help reduce the time it takes to start recording.</p>
+
<h4 id="configuring-mediarecorder">Configuring MediaRecorder</h4>
<p>When using the {@link android.media.MediaRecorder} class to record video, you must perform
configuration steps in a <em>specific order</em> and then call the {@link
@@ -851,7 +879,7 @@
<li>{@link android.media.MediaRecorder#setAudioSamplingRate(int) setAudioSamplingRate()}</li>
</ul>
-<h4 id="start-stop-mediarecorder">Starting and Stopping MediaRecorder</h4>
+<h4 id="start-stop-mediarecorder">Starting and stopping MediaRecorder</h4>
<p>When starting and stopping video recording using the {@link android.media.MediaRecorder} class,
you must follow a specific order, as listed below.</p>
@@ -938,7 +966,7 @@
private MediaRecorder mMediaRecorder;
...
-
+
@Override
protected void onPause() {
super.onPause();
@@ -1052,4 +1080,425 @@
href="{@docRoot}guide/topics/data/data-storage.html#SavingSharedFiles">Saving Shared Files</a>.</p>
<p>For more information about saving files on an Android device, see <a
-href="{@docRoot}guide/topics/data/data-storage.html">Data Storage</a>.</p>
\ No newline at end of file
+href="{@docRoot}guide/topics/data/data-storage.html">Data Storage</a>.</p>
+
+
+<h2 id="camera-features">Camera Features</h2>
+<p>Android supports a wide array of camera features you can control with your camera application,
+such as picture format, flash mode, focus settings, and many more. This section lists the common
+camera features, and briefly discusses how to use them. Most camera features can be accessed and set
+using the through {@link android.hardware.Camera.Parameters} object. However, there are several
+important features that require more than simple settings in {@link
+android.hardware.Camera.Parameters}. These features are covered in the following sections:<p>
+
+<ul>
+ <li><a href="#metering-focus-areas">Metering and focus areas</a></li>
+ <li><a href="#face-detection">Face detection</a></li>
+ <li><a href="#time-lapse-video">Time lapse video</a></li>
+</ul>
+
+<p>For general information about how to use features that are controlled through {@link
+android.hardware.Camera.Parameters}, review the <a href="#using-features">Using camera
+features</a> section. For more detailed information about how to use features controlled through the
+camera parameters object, follow the links in the feature list below to the API reference
+documentation.</p>
+
+<p class="table-caption" id="table1">
+ <strong>Table 1.</strong> Common camera features sorted by the Android API Level in which they
+were introduced.</p>
+<table>
+ <tr>
+ <th>Feature</th> <th>API Level</th> <th>Description</th>
+ </tr>
+ <tr>
+ <td><a href="#face-detection">Face Detection</a></td>
+ <td>14</td>
+ <td>Identify human faces within a picture and use them for focus, metering and white
+balance</td>
+ </tr>
+ <tr>
+ <td><a href="#metering-focus-areas">Metering Areas</a></td>
+ <td>14</td>
+ <td>Specify one or more areas within an image for calculating white balance</td>
+ </tr>
+ <tr>
+ <td><a href="#metering-focus-areas">Focus Areas</a></td>
+ <td>14</td>
+ <td>Set one or more areas within an image to use for focus</td>
+ </tr>
+ <tr>
+ <td>{@link android.hardware.Camera.Parameters#setAutoWhiteBalanceLock White Balance Lock}</td>
+ <td>14</td>
+ <td>Stop or start automatic white balance adjustments</td>
+ </tr>
+ <tr>
+ <td>{@link android.hardware.Camera.Parameters#setAutoExposureLock Exposure Lock}</td>
+ <td>14</td>
+ <td>Stop or start automatic exposure adjustments</td>
+ </tr>
+ <tr>
+ <td>{@link android.hardware.Camera#takePicture Video Snapshot}</td>
+ <td>14</td>
+ <td>Take a picture while shooting video (frame grab)</td>
+ </tr>
+ <tr>
+ <td><a href="#time-lapse-video">Time Lapse Video</a></td>
+ <td>11</td>
+ <td>Record frames with set delays to record a time lapse video</td>
+ </tr>
+ <tr>
+ <td>{@link android.hardware.Camera#open(int) Multiple Cameras}</td>
+ <td>9</td>
+ <td>Support for more than one camera on a device, including front-facing and back-facing
+cameras</td>
+ </tr>
+ <tr>
+ <td>{@link android.hardware.Camera.Parameters#getFocusDistances Focus Distance}</td>
+ <td>9</td>
+ <td>Reports distances between the camera and objects that appear to be in focus</td>
+ </tr>
+ <tr>
+ <td>{@link android.hardware.Camera.Parameters#setZoom Zoom}</td>
+ <td>8</td>
+ <td>Set image magnification</td>
+ </tr>
+ <tr>
+ <td>{@link android.hardware.Camera.Parameters#setExposureCompensation Exposure
+Compensation}</td>
+ <td>8</td>
+ <td>Increase or decrease the light exposure level</td>
+ </tr>
+ <tr>
+ <td>{@link android.hardware.Camera.Parameters#setGpsLatitude GPS Data}</td>
+ <td>5</td>
+ <td>Include or omit geographic location data with the image</td>
+ </tr>
+ <tr>
+ <td>{@link android.hardware.Camera.Parameters#setWhiteBalance White Balance}</td>
+ <td>5</td>
+ <td>Set the white balance mode, which affects color values in the captured image</td>
+ </tr>
+ <tr>
+ <td>{@link android.hardware.Camera.Parameters#setFocusMode Focus Mode}</td>
+ <td>5</td>
+ <td>Set how the camera focuses on a subject such as automatic, fixed, macro or infinity</td>
+ </tr>
+ <tr>
+ <td>{@link android.hardware.Camera.Parameters#setSceneMode Scene Mode}</td>
+ <td>5</td>
+ <td>Apply a preset mode for specific types of photography situations such as night, beach, snow
+or candlelight scenes</td>
+ </tr>
+ <tr>
+ <td>{@link android.hardware.Camera.Parameters#setJpegQuality JPEG Quality}</td>
+ <td>5</td>
+ <td>Set the compression level for a JPEG image, which increases or decreases image output file
+quality and size</td>
+ </tr>
+ <tr>
+ <td>{@link android.hardware.Camera.Parameters#setFlashMode Flash Mode}</td>
+ <td>5</td>
+ <td>Turn flash on, off, or use automatic setting</td>
+ </tr>
+ <tr>
+ <td>{@link android.hardware.Camera.Parameters#setColorEffect Color Effects}</td>
+ <td>5</td>
+ <td>Apply a color effect to the captured image such as black and white, sepia tone or negative.
+</td>
+ </tr>
+ <tr>
+ <td>{@link android.hardware.Camera.Parameters#setAntibanding Anti-Banding}</td>
+ <td>5</td>
+ <td>Reduces the effect of banding in color gradients due to JPEG compression</td>
+ </tr>
+ <tr>
+ <td>{@link android.hardware.Camera.Parameters#setPictureFormat Picture Format}</td>
+ <td>1</td>
+ <td>Specify the file format for the picture</td>
+ </tr>
+ <tr>
+ <td>{@link android.hardware.Camera.Parameters#setPictureSize Picture Size}</td>
+ <td>1</td>
+ <td>Specify the pixel dimensions of the saved picture</td>
+ </tr>
+</table>
+
+<p class="note"><strong>Note:</strong> These features are not supported on all devices due to
+hardware differences and software implementation. For information on checking the availability
+of features on the device where your application is running, see <a href="#check-feature">Checking
+feature availability</a>.</p>
+
+
+<h3 id="check-feature">Checking feature availability</h3>
+<p>The first thing to understand when setting out to use camera features on Android devices is that
+not all camera features are supported on all devices. In addition, devices that support a particular
+feature may support them to different levels or with different options. Therefore, part of your
+decision process as you develop a camera application is to decide what camera features you want to
+support and to what level. After making that decision, you should plan on including code in your
+camera application that checks to see if device hardware supports those features and fails
+gracefully if a feature is not available.</p>
+
+<p>You can check the availabilty of camera features by getting an instance of a camera’s parameters
+object, and checking the relevant methods. The following code sample shows you how to obtain a
+{@link android.hardware.Camera.Parameters} object and check if the camera supports the autofocus
+feature:</p>
+
+<pre>
+// get Camera parameters
+Camera.Parameters params = mCamera.getParameters();
+
+List<String> focusModes = params.getSupportedFocusModes();
+if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
+ // Autofocus mode is supported
+}
+</pre>
+
+<p>You can use the technique shown above for most camera features. The
+{@link android.hardware.Camera.Parameters} object provides a {@code getSupported...()}, {@code
+is...Supported()} or {@code getMax...()} method to determine if (and to what extent) a feature is
+supported.</p>
+
+<p>If your application requires certain camera features in order to function properly, you can
+require them through additions to your application manifest. When you declare the use of specific
+camera features, such as flash and auto-focus, the Android Market restricts your application from
+being installed on devices which do not support these features. For a list of camera features that
+can be declared in your app manifest, see the manifest
+<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#hw-features"> Features
+Reference</a>.</p>
+
+<h3 id="using-features">Using camera features</h3>
+<p>Most camera features are activated and controlled using a {@link
+android.hardware.Camera.Parameters} object. You obtain this object by first getting an instance of
+the {@link android.hardware.Camera} object, calling the {@link
+android.hardware.Camera#getParameters getParameters()} method, changing the returned parameter
+object and then setting it back into the camera object, as demonstrated in the following example
+code:</p>
+
+<pre>
+// get Camera parameters
+Camera.Parameters params = mCamera.getParameters();
+// set the focus mode
+params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
+// set Camera parameters
+mCamera.setParameters(params);
+</pre>
+
+<p>This technique works for nearly all camera features, and most parameters can be changed at any
+time after you have obtained an instance of the {@link android.hardware.Camera} object. Changes to
+parameters are typically visible to the user immediately in the application’s camera preview.
+On the software side, parameter changes may take several frames to actually take effect as the
+camera hardware processes the new instructions and then sends updated image data.</p>
+
+<p class="caution"><strong>Important:</strong> Some camera features cannot be changed at will. In
+particular, changing the size or orientation of the camera preview requires that you first stop the
+preview, change the preview size, and then restart the preview. Starting with Android 4.0 (API
+Level 14) preview orientation can be changed without restarting the preview.</p>
+
+<p>Other camera features require more code in order to implement, including:</p>
+<ul>
+ <li>Metering and focus areas</li>
+ <li>Face detection</li>
+ <li>Time lapse video</li>
+</ul>
+<p>A quick outline of how to implement these features is provided in the following sections.</p>
+
+
+<h3 id="metering-focus-areas">Metering and focus areas</h3>
+<p>In some photographic scenarios, automatic focusing and light metering may not produce the
+desired results. Starting with Android 4.0 (API Level 14), your camera application can provide
+additional controls to allow your app or users to specify areas in an image to use for determining
+focus or light level settings and pass these values to the camera hardware for use in capturing
+images or video.</p>
+
+<p>Areas for metering and focus work very similarly to other camera features, in that you control
+them through methods in the {@link android.hardware.Camera.Parameters} object. The following code
+demonstrates setting two light metering areas for an instance of
+{@link android.hardware.Camera}:</p>
+
+<pre>
+// Create an instance of Camera
+mCamera = getCameraInstance();
+
+// set Camera parameters
+Camera.Parameters params = mCamera.getParameters();
+
+if (params.getMaxNumMeteringAreas() > 0){ // check that metering areas are supported
+ List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();
+
+ Rect areaRect1 = new Rect(-100, -100, 100, 100); // specify an area in center of image
+ meteringAreas.add(new Camera.Area(areaRect1, 600)); // set weight to 60%
+ Rect areaRect2 = new Rect(800, -1000, 1000, -800); // specify an area in upper right of image
+ meteringAreas.add(new Camera.Area(areaRect2, 400)); // set weight to 40%
+ params.setMeteringAreas(meteringAreas);
+}
+
+mCamera.setParameters(params);
+</pre>
+
+<p>The {@link android.hardware.Camera.Area} object contains two data parameters: A {@link
+android.graphics.Rect} object for specifying an area within the camera’s field of view and a weight
+value, which tells the camera what level of importance this area should be given in light metering
+or focus calculations.</p>
+
+<p>The {@link android.graphics.Rect} field in a {@link android.hardware.Camera.Area} object
+describes a rectangular shape mapped on a 2000 x 2000 unit grid. The coordinates -1000, -1000
+represent the top, left corner of the camera image, and coordinates 1000, 1000 represent the
+bottom, right corner of the camera image, as shown in the illustration below.</p>
+
+<img src='images/camera-area-coordinates.png' />
+<p class="img-caption">
+ <strong>Figure 1.</strong> The red lines illustrate the coordinate system for specifying a
+{@link android.hardware.Camera.Area} within a camera preview. The blue box shows the location and
+shape of an camera area with the {@link android.graphics.Rect} values 333,333,667,667.
+</p>
+
+<p>The bounds of this coordinate system always correspond to the outer edge of the image visible in
+the camera preview and do not shrink or expand with the zoom level. Similarly, rotation of the image
+preview using {@link android.hardware.Camera#setDisplayOrientation Camera.setDisplayOrientation()}
+does not remap the coordinate system.</p>
+
+
+<h3 id="face-detection">Face detection</h3>
+<p>For pictures that include people, faces are usually the most important part of the picture, and
+should be used for determining both focus and white balance when capturing an image. The Android 4.0
+(API Level 14) framework provides APIs for identifying faces and calculating picture settings using
+face recognition technology.</p>
+
+<p class="note"><strong>Note:</strong> While the face detection feature is running,
+{@link android.hardware.Camera.Parameters#setWhiteBalance},
+{@link android.hardware.Camera.Parameters#setFocusAreas} and
+{@link android.hardware.Camera.Parameters#setMeteringAreas} have no effect.</p>
+
+<p>Using the face detection feature in your camera application requires a few general steps:</p>
+<ul>
+ <li>Check that face detection is supported on the device</li>
+ <li>Create a face detection listener</li>
+ <li>Add the face detection listener to your camera object</li>
+ <li>Start face detection after preview (and after <em>every</em> preview restart)</li>
+</ul>
+
+<p>The face detection feature is not supported on all devices. You can check that this feature is
+supported by calling {@link android.hardware.Camera.Parameters#getMaxNumDetectedFaces}. An
+example of this check is shown in the {@code startFaceDetection()} sample method below.</p>
+
+<p>In order to be notified and respond to the detection of a face, your camera application must set
+a listener for face detection events. In order to do this, you must create a listener class that
+implements the {@link android.hardware.Camera.FaceDetectionListener} interface as shown in the
+example code below.</p>
+
+<pre>
+class MyFaceDetectionListener implements Camera.FaceDetectionListener {
+
+ @Override
+ public void onFaceDetection(Face[] faces, Camera camera) {
+ if (faces.length > 0){
+ Log.d("FaceDetection", "face detected: "+ faces.length +
+ " Face 1 Location X: " + faces[0].rect.centerX() +
+ "Y: " + faces[0].rect.centerY() );
+ }
+ }
+}
+</pre>
+
+<p>After creating this class, you then set it into your application’s
+{@link android.hardware.Camera} object, as shown in the example code below:</p>
+
+<pre>
+mCamera.setFaceDetectionListener(new MyFaceDetectionListener());
+</pre>
+
+<p>Your application must start the face detection function each time you start (or restart) the
+camera preview. Create a method for starting face detection so you can call it as needed, as shown
+in the example code below.</p>
+
+<pre>
+public void startFaceDetection(){
+ // Try starting Face Detection
+ Camera.Parameters params = mCamera.getParameters();
+
+ // start face detection only *after* preview has started
+ if (params.getMaxNumDetectedFaces() > 0){
+ // camera supports face detection, so can start it:
+ mCamera.startFaceDetection();
+ }
+}
+</pre>
+
+<p>You must start face detection <em>each time</em> you start (or restart) the camera preview. If
+you use the preview class shown in <a href="#camera-preview">Creating a preview class</a>, add your
+{@link android.hardware.Camera#startFaceDetection startFaceDetection()} method to both the
+{@link android.view.SurfaceHolder.Callback#surfaceCreated surfaceCreated()} and {@link
+android.view.SurfaceHolder.Callback#surfaceChanged surfaceChanged()} methods in your preview class,
+as shown in the sample code below.</p>
+
+<pre>
+public void surfaceCreated(SurfaceHolder holder) {
+ try {
+ mCamera.setPreviewDisplay(holder);
+ mCamera.startPreview();
+
+ startFaceDetection(); // start face detection feature
+
+ } catch (IOException e) {
+ Log.d(TAG, "Error setting camera preview: " + e.getMessage());
+ }
+}
+
+public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+
+ if (mHolder.getSurface() == null){
+ // preview surface does not exist
+ Log.d(TAG, "mHolder.getSurface() == null");
+ return;
+ }
+
+ try {
+ mCamera.stopPreview();
+
+ } catch (Exception e){
+ // ignore: tried to stop a non-existent preview
+ Log.d(TAG, "Error stopping camera preview: " + e.getMessage());
+ }
+
+ try {
+ mCamera.setPreviewDisplay(mHolder);
+ mCamera.startPreview();
+
+ startFaceDetection(); // re-start face detection feature
+
+ } catch (Exception e){
+ // ignore: tried to stop a non-existent preview
+ Log.d(TAG, "Error starting camera preview: " + e.getMessage());
+ }
+}
+</pre>
+
+<p class="note"><strong>Note:</strong> Remember to call this method <em>after</em> calling
+{@link android.hardware.Camera#startPreview startPreview()}. Do not attempt to start face detection
+in the {@link android.app.Activity#onCreate onCreate()} method of your camera app’s main activity,
+as the preview is not available by this point in your application's the execution.</p>
+
+
+<h3 id="time-lapse-video">Time lapse video</h3>
+<p>Time lapse video allows users to create video clips that combine pictures taken a few seconds or
+minutes apart. This feature uses {@link android.media.MediaRecorder} to record the images for a time
+lapse sequence. </p>
+
+<p>To record a time lapse video with {@link android.media.MediaRecorder}, you must configure the
+recorder object as if you are recording a normal video, setting the captured frames per second to a
+low number and using one of the time lapse quality settings, as shown in the code example below.</p>
+
+<pre>
+// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
+mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH));
+...
+// Step 5.5: Set the video capture rate to a low number
+mMediaRecorder.setCaptureRate(0.1); // capture a frame every 10 seconds
+</pre>
+
+<p>These settings must be done as part of a larger configuration procedure for {@link
+android.media.MediaRecorder}. For a full configuration code example, see <a
+href="#configuring-mediarecorder">Configuring MediaRecorder</a>. Once the configuration is complete,
+you start the video recording as if you were recording a normal video clip. For more information
+about configuring and running {@link android.media.MediaRecorder}, see <a
+href="#capture-video">Capturing videos</a>.</p>
diff --git a/docs/html/guide/topics/media/images/camera-area-coordinates.png b/docs/html/guide/topics/media/images/camera-area-coordinates.png
new file mode 100644
index 0000000..9876453
--- /dev/null
+++ b/docs/html/guide/topics/media/images/camera-area-coordinates.png
Binary files differ
diff --git a/docs/html/guide/topics/media/index.jd b/docs/html/guide/topics/media/index.jd
index 7c1754fe..0e0412a 100644
--- a/docs/html/guide/topics/media/index.jd
+++ b/docs/html/guide/topics/media/index.jd
@@ -6,7 +6,7 @@
<h2>Topics</h2>
<ol>
-<li><a href="{@docRoot}guide/topics/media/mediaplayer.html">MediaPlayer</a></li>
+<li><a href="{@docRoot}guide/topics/media/mediaplayer.html">Media Playback</a></li>
<li><a href="{@docRoot}guide/topics/media/jetplayer.html">JetPlayer</a></li>
<li><a href="{@docRoot}guide/topics/media/camera.html">Camera</a></li>
<li><a href="{@docRoot}guide/topics/media/audio-capture.html">Audio Capture</a></li>
@@ -46,7 +46,8 @@
and playback.</p>
<dl>
- <dt><strong><a href="{@docRoot}guide/topics/media/mediaplayer.html">MediaPlayer</a></strong></dt>
+ <dt><strong><a href="{@docRoot}guide/topics/media/mediaplayer.html">Media Playback</a></strong>
+ </dt>
<dd>How to play audio and video in your application.</dd>
<dt><strong><a href="{@docRoot}guide/topics/media/jetplayer.html">JetPlayer</a></strong></dt>
diff --git a/docs/html/guide/topics/ui/actionbar.jd b/docs/html/guide/topics/ui/actionbar.jd
index 4742923..3c0ef26 100644
--- a/docs/html/guide/topics/ui/actionbar.jd
+++ b/docs/html/guide/topics/ui/actionbar.jd
@@ -8,179 +8,249 @@
<h2>Quickview</h2>
<ul>
- <li>A replacement for the title bar that includes the application icon and activity title</li>
- <li>Provides action items from the Options Menu and modes of navigating around the
-application</li>
- <li>Supports custom views, including an embedded search box</li>
- <li>Requires API Level 11</li>
+ <li>A title bar that includes the application icon and activity title</li>
+ <li>Provides access to menu items and navigation modes such as tabs</li>
+ <li>Requires API level 11 or greater</li>
</ul>
<h2>In this document</h2>
- <ol>
- <li><a href="#Adding">Adding the Action Bar</a>
- <ol>
- <li><a href="#Removing">Removing the Action Bar</a></li>
- </ol>
- </li>
- <li><a href="#ActionItems">Adding Action Items</a>
- <ol>
- <li><a href="#Home">Using the app icon as an action item</a></li>
- </ol>
- </li>
- <li><a href="#ActionView">Adding an Action View</a></li>
- <li><a href="#Tabs">Adding Tabs</a></li>
- <li><a href="#Dropdown">Adding Drop-down Navigation</a></li>
- <li><a href="#Style">Styling the Action Bar</a></li>
- </ol>
+<ol>
+ <li><a href="#Adding">Adding the Action Bar</a>
+ <ol>
+ <li><a href="#Removing">Removing the action bar</a></li>
+ </ol>
+ </li>
+ <li><a href="#ActionItems">Adding Action Items</a>
+ <ol>
+ <li><a href="#ChoosingActionItems">Choosing your action items</a></li>
+ <li><a href="#SplitBar">Using split action bar</a></li>
+ </ol>
+ </li>
+ <li><a href="#Home">Using the App Icon for Navigation</a>
+ <ol>
+ <li><a href="#Up">Navigating up</a></li>
+ </ol>
+ </li>
+ <li><a href="#ActionView">Adding an Action View</a>
+ <ol>
+ <li><a href="#ActionViewCollapsing">Handling collapsible action views</a></li>
+ </ol>
+ </li>
+ <li><a href="#ActionProvider">Adding an Action Provider</a>
+ <ol>
+ <li><a href="#ShareActionProvider">Using the ShareActionProvider</a></li>
+ <li><a href="#CreatingActionProvider">Creating a custom action provider</a></li>
+ </ol>
+ </li>
+ <li><a href="#Tabs">Adding Navigation Tabs</a></li>
+ <li><a href="#Dropdown">Adding Drop-down Navigation</a></li>
+ <li><a href="#Style">Styling the Action Bar</a>
+ <ol>
+ <li><a href="#GeneralStyles">General appearance</a></li>
+ <li><a href="#ActionItemStyles">Action items</a></li>
+ <li><a href="#NavigationStyles">Navigation tabs</a></li>
+ <li><a href="#DropDownStyles">Drop-down lists</a></li>
+ <li><a href="#AdvancedStyles">Advanced styling</a></li>
+ </ol>
+ </li>
+</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.app.ActionBar}</li>
<li>{@link android.view.Menu}</li>
+ <li>{@link android.view.ActionProvider}</li>
</ol>
-
+
<h2>Related samples</h2>
<ol>
- <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/index.html#ActionBar">API
- Demos</a></li>
<li><a
href="{@docRoot}resources/samples/HoneycombGallery/index.html">Honeycomb Gallery</a></li>
+ <li><a
+href="{@docRoot}resources/samples/ActionBarCompat/index.html">Action Bar Compatibility</a></li>
+ <li><a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/index.html#ActionBar">
+API Demos</a></li>
</ol>
-
- <h2>See also</h2>
+
+ <h2>See also</h2>item
<ol>
<li><a href="{@docRoot}guide/topics/ui/menus.html">Menus</a></li>
+ <li><a href="{@docRoot}guide/practices/tablets-and-handsets.html">Supporting Tablets
+and Handsets</a></li>
</ol>
</div>
</div>
-<p>The Action Bar is a widget for activities that replaces the traditional title bar at
-the top of the screen. By default, the Action Bar includes the application logo on the left side,
-followed by the activity title, and any available items from the Options Menu on the right side. The
-Action Bar offers several useful features, including the ability to:</p>
+<p>The action bar is a window feature that identifies the application and user location, and
+provides user actions and navigation modes. You should use the action bar in most activities that
+need to prominently present user actions or global navigation, because the action bar offers users a
+consistent interface across applications and the system gracefully adapts the action bar's
+appearance for different screen configurations. You can control the behaviors and visibility of the
+action bar with the {@link android.app.ActionBar} APIs, which were added in Android 3.0 (API level
+11).</p>
+
+<p>The primary goals of the action bar are to:</p>
<ul>
- <li>Display items from the <a
-href="{@docRoot}guide/topics/ui/menus.html#OptionsMenu">Options Menu</a> directly in the Action
-Bar, as "action
-items"—providing instant access to key user actions.
- <p>Menu items that do not appear as action items are placed in the overflow menu, revealed
-by a drop-down list in the Action Bar.</p></li>
- <li>Provide tabs for navigating between <a
-href="{@docRoot}guide/topics/fundamentals/fragments.html">fragments</a>.</li>
- <li>Provide a drop-down list for navigation.</li>
- <li>Provide interactive "action views" in place of action items (such as a search box).</li>
+ <li>Provide a dedicated space for identifying the application brand and user location.
+ <p>This is accomplished with the app icon or logo on the left side and the activity title.
+You might choose to remove the activity title, however, if the current view is identified by a
+navigation label, such as the currently selected tab.</p></li>
+
+ <li>Provide consistent navigation and view refinement across different applications.
+ <p>The action bar provides built-in tab navigation for switching between <a
+href="{@docRoot}guide/topics/fundamentals/fragments.html">fragments</a>. It also offers a drop-down
+list you can use as an alternative navigation mode or to refine the current view (such as to sort
+a list by different criteria).</p>
+ </li>
+
+ <li>Make key actions for the activity (such as "search", "create", "share", etc.) prominent and
+accessible to the user in a predictable way.
+ <p>You can provide instant access to key user actions by placing items from the <a
+href="{@docRoot}guide/topics/ui/menus.html#OptionsMenu">options menu</a> directly in the action bar,
+as "action items." Action items can also provide an "action view," which provides an embedded
+widget for even more immediate action behaviors. Menu items that are not promoted
+to an action item are available in the overflow menu, revealed by either the device MENU button
+(when available) or by an "overflow menu" button in the action bar (when the device does not
+include a MENU button).</p>
+</li>
</ul>
-<img src="{@docRoot}images/ui/actionbar.png" height="36" alt="" />
+<img src="{@docRoot}images/ui/actionbar.png" alt="" />
+<p class="img-caption"><strong>Figure 1.</strong> Action bar from the <a
+href="{@docRoot}resources/samples/HoneycombGallery/index.html">Honeycomb Gallery</a> app (on a
+landscape handset), showing the logo on the left, navigation tabs, and an action item on the
+right (plus the overflow menu button).</p>
-<p class="img-caption"><strong>Figure 1.</strong> A screenshot of the Action Bar in the Email
-application, containing action items to compose new email and refresh the inbox.</p>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+ <h2>Remaining backward-compatible</h2>
+<p>If you want to provide an action bar in your application <em>and</em> remain compatible with
+versions of Android older than 3.0, you need to create the action bar in your
+activity's layout (because the {@link android.app.ActionBar} class is not available on older
+versions).</p>
+<p>To help you, the <a
+href="{@docRoot}resources/samples/ActionBarCompat/index.html">Action Bar Compatibility</a> sample
+app provides an API layer and action bar layout that allows your app to use some of the {@link
+android.app.ActionBar} APIs and also support older versions of Android by replacing the traditional
+title bar with a custom action bar layout.</p>
+</div>
+</div>
<h2 id="Adding">Adding the Action Bar</h2>
-<p>The Action Bar is included by default in all activities that target Android 3.0 or greater. More
-specifically, all activities that use the new "holographic" theme include the Action Bar, and any
-application that targets Android 3.0 automatically receives this theme. An application is considered
-to "target" Android 3.0 when it has set either the {@code android:minSdkVersion} or {@code
-android:targetSdkVersion} attribute in the <a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code <uses-sdk>}</a> element to
-{@code "11"} or greater. For example:</p>
+<p>Beginning with Android 3.0 (API level 11), the action bar is included in all
+activities that use the {@link android.R.style#Theme_Holo Theme.Holo} theme (or one of its
+descendants), which is the default theme when either the <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> or
+<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a>
+attribute is set to {@code "11"} or greater. For example:</p>
<pre>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.example.helloworld"
- android:versionCode="1"
- android:versionName="1.0">
+<manifest ... >
<uses-sdk android:minSdkVersion="4"
<b>android:targetSdkVersion="11"</b> />
- <application ... >
- ...
- </application>
+ ...
</manifest>
</pre>
-<p>In this example, the application requires a minimum version of API
-Level 4 (Android 1.6), but it also targets API Level 11 (Android 3.0). This way, when
-the application is installed on a device running Android 3.0 or greater, the system applies the
-holographic theme to each activity, and thus, each activity includes the Action Bar.</p>
+<p>In this example, the application requires a minimum version of API Level 4 (Android 1.6), but it
+also targets API level 11 (Android 3.0). This way, when the application runs on Android 3.0 or
+greater, the system applies the holographic theme to each activity, and thus, each activity includes
+the action bar.</p>
-<p>However, if you want to use Action Bar APIs, such as to add tabs or modify Action Bar styles,
-you need to set the {@code android:minSdkVersion} to {@code "11"}, so you can access the
-{@link android.app.ActionBar} class.</p>
+<p>If you want to use {@link android.app.ActionBar} APIs, such as to add navigation modes and modify
+action bar styles, you should set the <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> to {@code
+"11"} or greater. If you want your app
+to support older versions of Android, there are ways to use a limited set of {@link
+android.app.ActionBar} APIs on devices that support API level 11 or higher, while still running
+on older versions. See the sidebox for information about remaining backward-compatible.</p>
-<h3 id="Removing">Removing the Action Bar</h3>
+<h3 id="Removing">Removing the action bar</h3>
-<p>If you want to remove the Action Bar for a particular activity, set the activity theme to
+<p>If you don't want the action bar for a particular activity, set the activity theme to
{@link android.R.style#Theme_Holo_NoActionBar Theme.Holo.NoActionBar}. For example:</p>
<pre>
<activity android:theme="@android:style/Theme.Holo.NoActionBar">
</pre>
-<p class="note"><strong>Tip:</strong> If you have a custom activity theme in which you'd like to
-remove the Action Bar, set the {@link android.R.styleable#Theme_windowActionBar
-android:windowActionBar} style property {@code false}. See <a href="#Style">Styling the Action
-Bar</a> for more about Action Bar styles.</p>
-
-<p>You can also hide the Action Bar at runtime by calling {@link android.app.ActionBar#hide},
-then show it again by calling {@link android.app.ActionBar#show}. For example:</p>
+<p>You can also hide the action bar at runtime by calling {@link android.app.ActionBar#hide}. For
+example:</p>
<pre>
-ActionBar actionBar = getActionBar();
+ActionBar actionBar = {@link android.app.Activity#getActionBar()};
actionBar.hide();
</pre>
-<p>When the Action Bar hides, the system adjusts your activity content to fill all the
-available screen space.</p>
+<p>When the action bar hides, the system adjusts your activity layout to fill all the
+screen space now available. You can bring the action bar back with {@link
+android.app.ActionBar#show()}.</p>
-<p class="note"><strong>Note:</strong> If you remove the Action Bar using a theme, then the
-window will not allow the Action Bar at all, so you cannot add it at runtime—calling
-{@link android.app.Activity#getActionBar getActionBar()} will return null.</p>
+<p>Beware that hiding and removing the action bar causes your activity to re-layout in order to
+account for the space consumed by the action bar. If your activity regularly hides and shows the
+action bar (such as in the Android Gallery app), you might want to use overlay mode. Overlay mode
+draws the action bar on top of your activity layout rather than in its own area of the screen. This
+way, your layout remains fixed when the action bar hides and re-appears. To enable overlay mode,
+create a theme for your activity and set {@link android.R.attr#windowActionBarOverlay
+android:windowActionBarOverlay} to {@code true}. For more information, see the section about <a
+href="#Style">Styling the Action Bar</a>.</p>
+
+<p class="note"><strong>Tip:</strong> If you have a custom activity theme in which you'd like to
+remove the action bar, set the {@link android.R.styleable#Theme_windowActionBar
+android:windowActionBar} style property to {@code false}. However, if you remove the action bar
+using a theme, then the window will not allow the action bar at all, so you cannot add it
+later—calling {@link android.app.Activity#getActionBar()} will return null.</p>
+
<h2 id="ActionItems">Adding Action Items</h2>
-<p>An action item is simply a menu item from the <a
-href="{@docRoot}guide/topics/ui/menus.html#OptionsMenu">Options Menu</a> which you declare should
-appear directly in the Action Bar. An action item can include an icon and/or text. If a menu
-item does not appear as an action item, then the system places it in the overflow menu, which
-the user can open with the menu icon on the right side of the Action Bar.</p>
+<p>Sometimes you might want to give users immediate access to an item from the <a
+href="{@docRoot}guide/topics/ui/menus.html#OptionsMenu">options menu</a>. To do this, you can
+declare that the menu item should appear in the action bar as an "action item." An action item can
+include an icon and/or a text title. If a menu item does not appear as an action item, then the
+system places it in the overflow menu. The overflow menu is revealed either by the device MENU
+button (if provided by the device) or an additional button in the action bar (if the device does not
+provide the MENU button).</p>
<div class="figure" style="width:359px">
<img src="{@docRoot}images/ui/actionbar-item-withtext.png" height="57" alt="" />
- <p class="img-caption"><strong>Figure 2.</strong> A screenshot from an Action Bar with two
-action items and the overflow menu.</p>
+ <p class="img-caption"><strong>Figure 2.</strong> Two action items with icon and text titles, and
+the overflow menu button.</p>
</div>
-<p>When the activity first starts, the system populates the Action Bar and overflow menu by calling
+<p>When the activity first starts, the system populates the action bar and overflow menu by calling
{@link android.app.Activity#onCreateOptionsMenu onCreateOptionsMenu()} for your activity. As
-discussed in the <a href="{@docRoot}guide/topics/ui/menus.html">Menus</a> developer guid, it's in
-this callback method that you define the Options Menu for the activity.</p>
+discussed in the <a href="{@docRoot}guide/topics/ui/menus.html">Menus</a> developer guide, it's in
+this callback method that you should inflate an XML <a
+href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a> that defines the
+menu items. For example:</p>
-<p>You can specify a menu item to appear as an action item—if there is room
-for it—from your <a href="{@docRoot}guide/topics/resources/menu-resource.html">menu
-resource</a> by declaring {@code
+<pre>
+@Override
+public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.main_activity, menu);
+ return true;
+}
+</pre>
+
+<p>In the XML file, you can request a menu item to appear as an action item by declaring {@code
android:showAsAction="ifRoom"} for the {@code <item>} element. This way, the menu item appears
-in the Action Bar for quick access only if there is room available for it. If there's not
-enough room, the item is placed the overflow menu (revealed by the menu icon on the right side
-of the Action Bar).</p>
+in the action bar for quick access only <em>if there is room</em> available. If there's not
+enough room, the item appears in the overflow menu.</p>
-<p>You can also declare a menu item to appear as an action item from your application code, by
-calling {@link android.view.MenuItem#setShowAsAction setShowAsAction()} on the {@link
-android.view.MenuItem} and passing {@link android.view.MenuItem#SHOW_AS_ACTION_IF_ROOM}.</p>
+<p>If your menu item supplies both a title and an icon—with the {@code android:title} and
+{@code android:icon} attributes—then the action item shows only the icon by default. If you
+want to display the text title, add {@code "withText"} to the {@code android:showAsAction}
+attribute. For example:</p>
-<p>If your menu item supplies both a title and an icon, then the action item shows only
-the icon by defult. If you want to include the text with the action item, add the "with
-text" flag: in XML, add {@code withText} to the {@code android:showAsAction} attribute or, in
-your application code, use the {@link android.view.MenuItem#SHOW_AS_ACTION_WITH_TEXT} flag when
-calling {@link android.view.MenuItem#setShowAsAction setShowAsAction()}. Figure 2 shows an Action
-Bar that has two action items with text and the icon for the overflow menu.</p>
-
-<p>Here's an example of how you can declare a menu item as an action item in a <a
-href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a> file:</p>
<pre>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
@@ -191,58 +261,200 @@
</menu>
</pre>
-<p>In this case, both the {@code ifRoom} and {@code withText} flags are set, so that when this
-item appears as an action item, it includes the title text along with the icon.</p>
+<p class="note"><strong>Note:</strong> The {@code "withText"} value is a <em>hint</em> to the
+action bar that the text title should appear. The action bar will show the title when possible, but
+might not if an icon is available and the action bar is constrained for space.</p>
-<p>A menu item placed in the Action Bar triggers the same callback methods as other items in the
-Options Menu. When the user selects an action item, your activity receives a call to
-{@link android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()}, passing the
-item ID.</p>
+<p>When the user selects an action item, your activity receives a call to
+{@link android.app.Activity#onOptionsItemSelected(MenuItem)
+onOptionsItemSelected()}, passing the ID supplied by the {@code android:id} attribute—the same
+callback received for all items in the options menu.</p>
-<p class="note"><strong>Note:</strong> If you added the menu item from a fragment, then the
-respective {@link
-android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} method is called
-for that fragment. However the activity gets a chance to handle it first, so the system calls {@link
-android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} on the activity
-before calling the fragment.</p>
+<p>It's important that you always define {@code android:title} for each menu item—even if you
+don't declare that the title appear with the action item—for three reasons:</p>
+<ul>
+ <li>If there's not enough room in the action bar for the action item, the menu item appears
+in the overflow menu and only the title appears.</li>
+ <li>Screen readers for sight-impaired users read the menu item's title.</li>
+ <li>If the action item appears with only the icon, a user can long-press the item to reveal a
+tool-tip that displays the action item's title.</li>
+</ul>
-<p>You can also declare an item to <em>always</em> appear as an action item, but you should avoid
-doing so, because it can create a cluttered UI if there are too many action items and they might
-collide with other elements in the Action Bar.</p>
+<p>The {@code android:icon} is always optional, but recommended. For icon design recommendations,
+see the <a href="{@docRoot}guide/practices/ui_guidelines/icon_design_action_bar.html">Action Bar
+Icon</a> design guidelines.</p>
-<p>For more information about menus, see the <a
+<p class="note"><strong>Note:</strong> If you added the menu item from a fragment, via the {@link
+android.app.Fragment} class's {@link android.app.Fragment#onCreateOptionsMenu onCreateOptionsMenu}
+callback, then the system calls the respective {@link
+android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} method for that
+fragment when the user selects one of the fragment's items. However the activity gets a chance to
+handle the event first, so the system calls {@link
+android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} on the activity before
+calling the same callback for the fragment.</p>
+
+<p>You can also declare an item to <em>"always"</em> appear as an action item, instead of being
+placed in the overflow menu when space is limited. In most cases, you <strong>should not</strong>
+force an item to appear in the action bar by using the {@code "always"} value. However, you might
+need an item to always appear when it provides an <a href="#ActionView">action view</a> that does
+not offer a default action for the overflow menu. Beware that too
+many action items can create a cluttered UI and cause layout problems on devices with a narrow
+screen. It's best to instead use {@code "ifRoom"} to request that an item appear in the action
+bar, but allow the system to move it into the overflow menu when there's not enough room.</p>
+
+<p>For more information about creating the options menu that defines your action items, see the <a
href="{@docRoot}guide/topics/ui/menus.html#options-menu">Menus</a> developer guide.</p>
-<h3 id="Home">Using the app icon as an action item</h3>
-<p>By default, your application icon appears in the Action Bar on the left side. It also responds
-to user interaction (when the user taps it, it visually responds the same way action
-items do) and it's your responsibility to do something when the user taps it.</p>
+<h3 id="ChoosingActionItems">Choosing your action items</h3>
-<img src="{@docRoot}images/ui/actionbar.png" height="36" alt="" />
-<p class="img-caption"><strong>Figure 3.</strong> Email's Action Bar, with the
-application icon on the left.</p>
+<div class="sidebox-wrapper">
+<div class="sidebox">
+ <h4>Menu items vs. other app controls</h4>
+ <p>As a general rule, all items in the <a
+href="{@docRoot}guide/topics/ui/menus.html#OptionsMenu">options menu</a> (let alone action items)
+should have a global impact on the app, rather than affect only a small portion of the interface.
+For example, if you have a multi-pane layout and one pane shows a video while another lists all
+videos, the video player controls should appear within the pane containing the video (not in the
+action bar), while the action bar might provide action items to share the video or save the video to
+a favorites list.</p>
+ <p>So, even before deciding whether a menu item should appear as an action item, be sure that
+the item has a global scope for the current activity. If it doesn't, then you should place it
+as a button in the appropriate context of the activity layout.</p>
+</div>
+</div>
-<p>The normal behavior should be for your application to return to the "home" activity or the
-initial state (such as when the activity hasn't changed, but fragments have changed) when the user
-taps the icon. If the user is already at home or the initial state, then you don't need to do
-anything.</p>
+<p>You should carefully choose which items from your options menu should appear as action items by
+assessing a few key traits. In general, each action item should be <em>at least one</em>
+of the following:</p>
-<p>When the user taps the icon, the system calls your activity's {@link
+<ol>
+ <li><strong>Frequently used</strong>: It's an action that your users need seven out of ten visits
+or they use it several times in a row.
+ <p>Example frequent actions: "New message" in the Messaging app and
+"Search" in Android Market.</p>
+ </li>
+
+ <li><strong>Important</strong>: It's an action that you need users to easily discover or, if it's
+not frequently used, it's important that it be effortless to perform in the few cases that users do
+need it.
+ <p>Example important actions: "Add network" in Wi-Fi settings and "Switch to camera" in the
+Gallery app.</p>
+ </li>
+
+ <li><strong>Typical</strong>: It's an action that is typically provided in the action bar in
+similar apps, so your users expect to find it in yours.
+ <p>Example typical actions: "Refresh" in an email or social app, and "New contact" in the
+People app.</p>
+</ol>
+
+<p>If you believe that more than four of your menu items can be justified as action items, then you
+should carefully consider their relative level of importance and try to set no more than four as
+action items (and do so using the {@code "ifRoom"} value to allow the system to put some back in the
+overflow menu when space is limited on smaller screens). Even if space is available on a wide
+screen, you should not create a long stream of action items that clutter the UI and appear like a
+desktop toolbar, so keep the number of action items to a minimum.</p>
+
+<p>Additionally, the following actions should never appear as action items: Settings, Help,
+Feedback, or similar. Always keep them in the overflow menu.</p>
+
+<p class="note"><strong>Note:</strong> Remember that not all devices provide a dedicated hardware
+button for Search, so if it's an important feature in your app, it should always appear as an
+action item (and usually as the first item, especially if you offer it with an <a
+href="#ActionView">action view</a>).</p>
+
+
+
+<h3 id="SplitBar">Using split action bar</h3>
+
+<p>When your application is running on Android 4.0 (API level 14) and higher, there's an extra mode
+available for the action bar called "split action bar." When you enable split action bar, a separate
+bar appears at the bottom of the screen to display all action items when the activity is running on
+a narrow screen (such as a portrait-oriented handset). Splitting the action bar to separate
+the action items ensures that a reasonable amount of space is available to display all your action
+items on a narrow screen, while leaving room for navigation and title elements at the top.</p>
+
+<p>To enable split action bar, simply add {@code uiOptions="splitActionBarWhenNarrow"} to your
+<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> or
+<a href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>
+manifest element.</p>
+
+<p>Be aware that Android adjusts the action bar's appearance in a variety of ways, based on the
+current screen size. Using split action bar is just one option that you can enable to allow the
+action bar to further optimize the user experience for different screen sizes. In doing so, you
+may also allow the action bar to collapse navigation tabs into the main action bar. That is, if you
+use <a href="#Tabs">navigation tabs</a> in your action bar, once the action items are
+separated on a narrow screen, the navigation tabs may be able to fit into the main action bar rather
+than be separated into the "stacked action bar." Specifically, if you've disabled the action bar
+icon and title (with {@link android.app.ActionBar#setDisplayShowHomeEnabled
+setDisplayShowHomeEnabled(false)} and {@link android.app.ActionBar#setDisplayShowTitleEnabled
+setDisplayShowTitleEnabled(false)}), then the navigation tabs collapse into the main action bar, as
+shown by the second device in figure 3.</p>
+
+<img src="{@docRoot}images/practices/actionbar-phone-splitaction.png" alt=""/>
+<p class="img-caption"><strong>Figure 3.</strong> Mock-ups of split action bar with navigation tabs
+on the left; with the app icon and title disabled on the right.</p>
+
+<p class="note"><strong>Note:</strong> Although the {@link android.R.attr#uiOptions
+android:uiOptions} attribute was added in Android 4.0 (API level 14), you can safely include it in
+your application even if your <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> is set to
+a value lower than {@code "14"} to remain compatible with older versions of Android. When running on
+older versions, the system simply ignores the XML attribute because it doesn't understand it. The
+only condition to including it in your manifest is that you must compile your application against a
+platform version that supports API level 14 or higher. Just be sure that you don't openly use other
+APIs in your application code that aren't supported by the version declared by your <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a>
+attribute—only XML attributes are safely ignored by older platforms.</p>
+
+
+
+
+<h2 id="Home">Using the App Icon for Navigation</h2>
+
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+ <h2>Using a logo instead of icon</h2>
+<p>By default, the system uses your application icon in the action bar, as specified by the <a
+href="{@docRoot}guide/topics/manifest/application-element.html#icon">{@code android:icon}</a>
+attribute in the <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code
+<application>}</a> or <a
+href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
+<activity>}</a> element. However, if you also specify the <a
+href="{@docRoot}guide/topics/manifest/application-element.html#logo">{@code android:logo}</a>
+attribute, then the action bar uses the logo image instead of the icon.</p>
+<p>A logo should usually be wider than the icon, but should not include unnecessary text. You
+should generally use a logo only when it represents your brand in a traditional format that users
+recognize. A good example is the YouTube app's logo—the logo represents the expected user
+brand, whereas the app's icon is a modified version that conforms to the square requirement.</p>
+</div>
+</div>
+
+
+<p>By default, your application icon appears in the action bar on the left side. If you'd like,
+you can enable the icon to behave as an action item. In response to user action on the icon, your
+application should do one of two things:</p>
+
+<ul>
+ <li>Go to the application "home" activity, or</li>
+ <li>Navigate "up" the application's structural hierarchy</li>
+</ul>
+
+<p>When the user touches the icon, the system calls your activity's {@link
android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} method with the {@code
-android.R.id.home} ID. So, you need to add a condition to your {@link
-android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} method to listen for {@code
-android.R.id.home} and perform the appropriate action, such as start the home activity or pop recent
-fragment transactions off the stack.</p>
+android.R.id.home} ID. In response, you should either start the home activity or
+take the user one step up in your application's structural hierarchy.</p>
<p>If you respond to the application icon by returning to the home activity, you should include
the {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP} flag in the {@link
android.content.Intent}. With this flag, if the activity you're starting already exists in the
current task, then all activities on top of it are destroyed and it is brought to the front.
-You should favor this approach, because going "home" is an action that's equivalent to "going
+Adding this flag is often important because going "home" is an action that's equivalent to "going
back" and you should usually not create a new instance of the home activity. Otherwise, you
-might end up with a long stack of activities in the current task.</p>
+might end up with a long stack of activities in the current task with multiple instances of the
+home activity.</p>
<p>For example, here's an implementation of {@link android.app.Activity#onOptionsItemSelected
onOptionsItemSelected()} that returns to the application's "home" activity:</p>
@@ -252,7 +464,7 @@
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
- // app icon in Action Bar clicked; go home
+ // app icon in action bar clicked; go home
Intent intent = new Intent(this, HomeActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
@@ -263,129 +475,153 @@
}
</pre>
-
-
-
-<h4>Using the app icon to navigate "up"</h4>
-
-<div class="figure" style="width:144px">
- <img src="{@docRoot}images/ui/actionbar-logo.png" height="140" alt="" />
- <p class="img-caption"><strong>Figure 4.</strong> The standard icon for the Email application
-(top) and the "up" icon (bottom).</p>
-</div>
-
-<p>You can also use the application icon to provide "up" navigation for the user. This is especially
-useful when your application is composed of activities that generally appear in a certain order and
-you want to facilitate the ability for the user to navigate up the activity hierarchy
-(regardless of how they entered the current activity).</p>
-
-<p>The way you respond to this event is the same as when navigating home (as
-discussed above, except you start a different activity, based on the current activity). All you
-need to do to indicate to the user that the behavior is different is set the Action Bar to "show
-home as up." You can do so by calling {@link android.app.ActionBar#setDisplayHomeAsUpEnabled
-setDisplayHomeAsUpEnabled(true)} on your activity's {@link android.app.ActionBar}. When you do, the
-system draws your application icon with an arrow indicating the up behavior, as shown in figure
-4.</p>
-
-<p>For example, here's how you can show the application icon as an "up" action:</p>
+<p>In case the user can enter the current activity from another application, you might also want to
+add the {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag. This flag ensures that, when the
+user navigates either "home" or "up", the new activity is <strong>not</strong> added to the current
+task, but instead started in a task that belongs to your application. For example, if the user
+starts an activity in your application through an intent invoked by another application, then
+selects the action bar icon to navigate home or up, the {@link
+android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP} flag starts the activity in a task that belongs to
+your application (not the current task). The system either starts a new task with your new activity
+as the root activity or, if an existing task exists in the background with an instance of that
+activity, then that task is brought forward and the target activity receives {@link
+android.app.Activity#onNewIntent onNewIntent()}. So if your activity accepts intents from other
+applications (it declares any generic intent filters), you should usually add the {@link
+android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag to the intent:</p>
<pre>
-@Override
-protected void onStart() {
- super.onStart();
- ActionBar actionBar = this.getActionBar();
+intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
+</pre>
+
+<p>For more information about these flags and other back stack behaviors, read the <a
+href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back Stack</a>
+developer guide.</p>
+
+<p class="note"><strong>Note:</strong> If you're using the icon to navigate to the home
+activity, beware that beginning with Android 4.0 (API level 14), you must explicitly enable the
+icon as an action item by calling {@link android.app.ActionBar#setHomeButtonEnabled
+setHomeButtonEnabled(true)} (in previous versions, the icon was enabled as an action item by
+default).</p>
+
+
+
+<h3 id="Up">Navigating up</h3>
+
+<div class="figure" style="width:230px;margin-top:-1em">
+ <img src="{@docRoot}images/ui/actionbar-logo.png" alt="" />
+ <p class="img-caption"><strong>Figure 4.</strong> The Email app's standard icon
+(left) and the "navigate up" icon (right). The system automatically adds the "up" indicator.</p>
+</div>
+
+<p>As a supplement to traditional "back" navigation—which takes the user to the previous
+screen in the task history—you can enable the action bar icon to offer "up"
+navigation, which should take the user one step up in your application's structural hierarchy. For
+instance, if the current screen is somewhere deep in the hierarchy of the application, touching the
+app icon should navigate upward one level, to the parent of the current screen.</p>
+
+<p>For example, figure 5 illustrates how the BACK button behaves when the user navigates from one
+application to an activity belonging to a different application (specifically, when composing an
+email to a person selected from the People app).</p>
+
+<img src="{@docRoot}images/ui/actionbar-navigate-back.png" alt="" />
+<p class="img-caption"><strong>Figure 5.</strong> The BACK button behavior
+after entering the Email app from the People (or Contacts) app.</p>
+
+<p>However, if the user wants to stay within the email application after composing the email,
+up navigation allows the user to navigate upward in the email application, rather than go back
+to the previous activity. Figure 6 illustrates this scenario, in which the user again comes into
+the email application, but presses the action bar icon to navigate up, rather than back.</p>
+
+<img src="{@docRoot}images/ui/actionbar-navigate-up.png" alt="" />
+<p class="img-caption"><strong>Figure 6.</strong> Example behavior for UP navigation after
+entering the Email app from the People app.</p>
+
+<p>To enable the icon for up navigation (which displays the "up" indicator next to the icon), call
+{@link android.app.ActionBar#setDisplayHomeAsUpEnabled setDisplayHomeAsUpEnabled(true)} on your
+{@link android.app.ActionBar}:</p>
+
+<pre>
+protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.main);
+ ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
+ ...
}
</pre>
-<p>Then, your activity should respond to the user tapping the icon, from the {@link
-android.app.Activity#onOptionsItemSelected
-onOptionsItemSelected()}, by listening for the {@code android.R.id.home} ID (as shown above). In
-this case, when navigating up, it's even more important that you use the {@link
-android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP} flag in the {@link android.content.Intent}, so that
-you don't create a new instance of the parent activity if one already exists.</p>
+<p>When the user touches the icon, the system calls your activity's {@link
+android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} method with the {@code
+android.R.id.home} ID, as shown in the above section about <a href="#Home">Using the App Icon
+for Navigation</a>.</p>
+
+<p>Remember to use the {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP} flag in the {@link
+android.content.Intent}, so that you don't create a new instance of the parent activity if one
+already exists. For instance, if you don't use the {@link
+android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP} flag, then after navigating up, the BACK button will
+actually take the user "forward", with respect to the application structure, which would be
+strange.</p>
+
+<p class="note"><strong>Note:</strong> If there are many paths that the user could have taken to
+reach the current activity within your application, the up icon should navigate backward along the
+path the user actually followed to get to the current activity.</p>
<h2 id="ActionView">Adding an Action View</h2>
-<div class="figure" style="width:429px">
- <img src="{@docRoot}images/ui/actionbar-actionview.png" alt="" />
- <p class="img-caption"><strong>Figure 5.</strong> An action view with a {@link
-android.widget.SearchView} widget.</p>
+<div class="figure" style="width:300px;margin-top:-1em">
+ <img src="/images/ui/actionbar-searchview.png" alt="" />
+ <p class="img-caption"><strong>Figure 7.</strong> An action bar with a collapsed action
+view for Search (top), then expanded action view with the <code><a
+href="/reference/android/widget/SearchView.html">SearchView</a></code> widget (bottom).</p>
</div>
-<p>An action view is a widget that appears in the Action Bar as a substitute for an action
-item. For example, if you have an item in the Options Menu for "Search", you can add an action view
-for the item that provides a {@link android.widget.SearchView} widget in the Action Bar whenever
-the item is enabled as an action item.</p>
-<p>When adding an action view for a menu item, it's important that you still allow the item to
-behave as a normal menu item when it does not appear in the Action Bar. For example, a menu item to
-perform a search should, by default, bring up the Android search dialog, but if the item is
-placed in the Action Bar, the action view appears with a {@link android.widget.SearchView}
-widget. Figure 4 shows an example of the {@link android.widget.SearchView} widget in an action
-view.</p>
+<p>An action view is a widget that appears in the action bar as a substitute for an action item's
+button. For example, if you have an item in the options menu for "Search," you can add an action
+view that replaces the button with a {@link android.widget.SearchView} widget, as shown in figure
+7.</p>
-<p>The best way to declare an action view for an item is in your <a
-href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a>, using the {@code
-android:actionLayout} or {@code android:actionViewClass} attribute:</p>
+<p>To declare an action view for an item in your <a
+href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a>, use either the {@code
+android:actionLayout} or {@code android:actionViewClass} attribute to specify either a layout
+resource or widget class to use, respectively. For example:</p>
-<ul>
- <li>The value for {@code android:actionLayout} must be a resource pointer to a layout file.
-For example:
<pre>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_search"
- android:title="Search"
- android:icon="@drawable/ic_menu_search"
- android:showAsAction="ifRoom"
- <b>android:actionLayout="@layout/searchview"</b> />
+ android:title="@string/menu_search"
+ android:icon="@drawable/ic_menu_search"
+ android:showAsAction="ifRoom|collapseActionView"
+ <b>android:actionViewClass="android.widget.SearchView"</b> />
</menu>
</pre>
-</li>
- <li>The value for {@code android:actionViewClass} must be a fully-qualified class name for
-the {@link android.view.View} you want to use. For example:
-<pre>
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@+id/menu_search"
- android:title="Search"
- android:icon="@drawable/ic_menu_search"
- android:showAsAction="ifRoom"
- <b>android:actionViewClass="android.widget.SearchView"</b> />
-</menu>
-</pre></li>
-</ul>
+<p>Notice that the {@code android:showAsAction} attribute also includes {@code
+"collapseActionView"}. This is optional and declares that the action view should be collapsed into a
+button. When the user selects the button, the action view expands. Otherwise, the action view is
+visible by default and might consume valuable action bar space even when the user is not using it.
+For more information, see the next section about <a href="#ActionViewCollapsing">Handling
+collapsible action views</a>.</p>
-<p class="note">You must include {@code android:showAsAction="ifRoom"} in order for the item to
-appear as an action view when room is available. If necessary, however, you can force the item to
-always appear as an action view by setting {@code android:showAsAction} to {@code "always"}.</p>
-
-<p>Now, when the menu item is displayed as an action item, it's action view appears instead of
-the icon and/or title text. However, if there's not enough room in the Action Bar, the item appears
-in the overflow menu as a normal menu item and you must respond to it from the {@link
-android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} callback method.</p>
-
-<p>When the activity first starts, the system populates the Action Bar and overflow menu by calling
-{@link android.app.Activity#onCreateOptionsMenu onCreateOptionsMenu()}.
-After you've inflated your menu in this method, you can acquire elements in an action view
-(perhaps in order to attach listeners) by calling {@link android.view.Menu#findItem
-findItem()} with the ID of the menu item, then {@link android.view.MenuItem#getActionView} on
-the returned {@link android.view.MenuItem}. For example, the search widget from the above samples is
-acquired like this:</p>
+<p>If you need to add some event hooks to your action view, you can do so during the {@link
+android.app.Activity#onCreateOptionsMenu onCreateOptionsMenu()} callback. You can acquire elements
+in an action view by calling {@link android.view.Menu#findItem findItem()} with the ID of the menu
+item, then call {@link android.view.MenuItem#getActionView}. For
+example, the search widget from the above sample is acquired like this:</p>
<pre>
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.options, menu);
- SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
- // Set appropriate listeners for searchView
- ...
- return super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.options, menu);
+ SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
+ // Configure the search info and add any event listeners
+ ...
+ return super.onCreateOptionsMenu(menu);
}
</pre>
@@ -393,167 +629,487 @@
href="{@docRoot}guide/topics/search/search-dialog.html">Creating a Search Interface</a>.</p>
+<h3 id="ActionViewCollapsing">Handling collapsible action views</h3>
-
-<h2 id="Tabs">Adding Tabs</h2>
-
-
-<div class="figure" style="width:504px">
- <img src="{@docRoot}images/ui/actionbar-tabs.png" alt="" />
- <p class="img-caption"><strong>Figure 6.</strong> Screenshot of tabs in the
-Action Bar, from the <a
-href="{@docRoot}resources/samples/HoneycombGallery/index.html">Honeycomb Gallery</a> sample
-application.</p>
+<div class="sidebox-wrapper">
+<div class="sidebox">
+ <h3>Supporting Android 3.0 with an action view</h3>
+ <p>The {@code "collapseActionView"} option was added with Android 4.0 (API level 14). However, if
+your application supports older versions, you should
+still declare {@code "collapseActionView"} in order to better support smaller screens.
+Devices running Android 4.0 and higher will show the action view collapsed, while older versions
+work as designed otherwise.</p>
+ <p>Adding this value requires that you set your build target to Android 4.0 or higher in order to
+compile. Older versions of Android ignore the {@code "collapseActionView"} value because they don't
+understand it. Just be sure not to use other APIs in your source code that are not supported in the
+version declared by your <a href="{@docRoot}guide/topics/manifest/uses-sdk-elementl.html#min">{@code
+minSdkVersion}</a>, unless you add the appropriate version check at runtime.</p>
+</div>
</div>
-<p>The Action Bar can display tabs that allow the user navigate between different fragments in the
-activity. Each tab can include a title and/or an icon.</p>
-<p>To begin, your layout must include a {@link android.view.View} in which each {@link
-android.app.Fragment} associated with a tab is displayed. Be sure the view has an ID that you
-can use to reference it from your code.</p>
+<p>Action views allow you to provide fast access to rich actions without changing activities or
+fragments, or replacing the action bar. However, it might not be appropriate to make an action view
+visible by default. To preserve the action bar space (especially when running on smaller screens),
+you can collapse your action view into an action item button. When the user selects the
+button, the action view appears in the action bar. When collapsed, the system might place the item
+into the overflow menu if you've defined {@code android:showAsAction} with {@code "ifRoom"}, but the
+action view still appears in the action bar when the user selects the item. You can make your action
+view collapsible by adding {@code "collapseActionView"} to the {@code android:showAsAction}
+attribute, as shown in the XML above.</p>
-<p>To add tabs to the Action Bar:</p>
-<ol>
- <li>Create an implementation of {@link android.app.ActionBar.TabListener} to handle the
-interaction events on the Action Bar tabs. You must implement all methods: {@link
-android.app.ActionBar.TabListener#onTabSelected onTabSelected()}, {@link
-android.app.ActionBar.TabListener#onTabUnselected onTabUnselected()}, and {@link
-android.app.ActionBar.TabListener#onTabReselected onTabReselected()}.
- <p>Each callback method passes the {@link android.app.ActionBar.Tab} that received the
-event and a {@link android.app.FragmentTransaction} for you to perform the fragment
-transactions (add or remove fragments).</p>
- <p>For example:</p>
+<p>Because the system will expand the action view when the user selects the item, so you
+<em>do not</em> need to respond to the item in the {@link
+android.app.Activity#onOptionsItemSelected onOptionsItemSelected} callback. The system still calls
+{@link android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} when the user selects it,
+but the system will always expand the action view unless you return {@code true} (indicating
+you've handled the event instead).</p>
+
+<p>The system also collapses your action view when the user selects the "up" icon in the action
+bar or presses the BACK button.</p>
+
+<p>If necessary, you can expand or collapse the action view in your own code by calling {@link
+android.view.MenuItem#expandActionView()} and {@link android.view.MenuItem#collapseActionView()} on
+the {@link android.view.MenuItem}.</p>
+
+<p class="note"><strong>Note:</strong> Although collapsing your action view is optional, we
+recommend that you always collapse your action view if it includes {@link
+android.widget.SearchView}. Also be aware that some devices provide a dedicated SEARCH button and
+you should expand your search action view if the user presses the SEARCH button. Simply override
+your activity's {@link android.app.Activity#onKeyUp onKeyUp()} callback method, listen for the
+{@link android.view.KeyEvent#KEYCODE_SEARCH} event, then call {@link
+android.view.MenuItem#expandActionView()}.</p>
+
+<p>If you need to update your activity based on the visibility of your action view, you can receive
+callbacks when it's expanded and collapsed by defining an {@link
+android.view.MenuItem.OnActionExpandListener OnActionExpandListener} and registering it with {@link
+android.view.MenuItem#setOnActionExpandListener setOnActionExpandListener()}. For example:</p>
+
<pre>
-private class MyTabListener implements ActionBar.TabListener {
- private TabContentFragment mFragment;
+@Override
+public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.options, menu);
+ MenuItem menuItem = menu.findItem(R.id.actionItem);
+ ...
- // Called to create an instance of the listener when adding a new tab
- public MyTabListener(TabContentFragment fragment) {
- mFragment = fragment;
+ menuItem.setOnActionExpandListener(new OnActionExpandListener() {
+ @Override
+ public boolean onMenuItemActionCollapse(MenuItem item) {
+ // Do something when collapsed
+ return true; // Return true to collapse action view
+ }
+
+ @Override
+ public boolean onMenuItemActionExpand(MenuItem item) {
+ // Do something when expanded
+ return true; // Return true to expand action view
+ }
+ });
+}
+</pre>
+
+
+
+
+<h2 id="ActionProvider">Adding an Action Provider</h2>
+
+<div class="figure" style="width:200px">
+ <img src="{@docRoot}images/ui/actionbar-shareaction.png" alt="" />
+ <p class="img-caption"><strong>Figure 8.</strong> Screenshot from the Gallery app, with the
+ {@link android.widget.ShareActionProvider} submenu expanded to show share targets.</p>
+</div>
+
+<p>Similar to an <a href="#ActionView">action view</a>, an action provider (defined by the {@link
+android.view.ActionProvider} class) replaces an action item with a customized layout, but it also
+takes control of all the item's behaviors. When you declare an action provider for a menu
+item in the action bar, it not only controls the appearance of the item in the action bar with a
+custom layout, but also handles the default event for the menu item when it appears in the overflow
+menu. It can also provide a submenu from either the action bar or the overflow menu.</p>
+
+<p>For example, the {@link android.widget.ShareActionProvider} is an extension of {@link
+android.view.ActionProvider} that facilitates a “share" action by showing a list of available share
+targets from the action bar. Instead of using a
+traditional action item that invokes the {@link android.content.Intent#ACTION_SEND} intent, you can
+declare an instance of {@link android.widget.ShareActionProvider} to handle an action item. This
+action provider presents an action view with a drop-down list of applications that handle
+the {@link android.content.Intent#ACTION_SEND} intent, even when the menu item appears in the
+overflow menu. Hence, when you use an action provider such as this one, you don't
+have to handle user events on the menu item.</p>
+
+<p>To declare an action provider for an action item, define the {@code android:actionProviderClass}
+attribute for the appropriate the {@code <item>} element in your <a
+href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a>, using the
+fully-qualified class name of the action provider. For example:</p>
+
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/menu_share"
+ android:title="@string/share"
+ android:showAsAction="ifRoom"
+ <strong>android:actionProviderClass="android.widget.ShareActionProvider"</strong> />
+ ...
+</menu>
+</pre>
+
+<p>In this example, the {@link android.widget.ShareActionProvider} is used as the action provider.
+At this point, the action provider officially takes control of the menu item and handles both
+its appearance and behavior in the action bar and its behavior in the overflow menu. You must
+still provide a text title for the item to be used in the overflow menu.</p>
+
+<p>Although the action provider can perform the default action for the menu item when it appears in
+the overflow menu, your activity (or fragment) can override that behavior by
+also handling the click event from the {@link android.app.Activity#onOptionsItemSelected
+onOptionsItemSelected()} callback method. If you do not handle the event in that callback, then
+the action provider receives the {@link android.view.ActionProvider#onPerformDefaultAction()}
+callback to handle the event. However, if the action provider provides a submenu, then your
+activity will not receive the {@link android.app.Activity#onOptionsItemSelected
+onOptionsItemSelected()} callback, because the submenu is shown instead of invoking the default
+menu item behavior when selected.</p>
+
+
+
+<h3 id="ShareActionProvider">Using the ShareActionProvider</h3>
+
+<p>If you want to provide a "share" action in your action bar by leveraging other applications
+installed on the device (for example, to share a photo using a messaging or social app), then using
+{@link android.widget.ShareActionProvider} is an effective way to do so, rather than adding an
+action item that invokes the {@link android.content.Intent#ACTION_SEND} intent. When
+you use {@link android.widget.ShareActionProvider} for an action item, it presents an action view
+with a drop-down list of applications that handle the {@link android.content.Intent#ACTION_SEND}
+intent (as shown in figure 8).</p>
+
+<p>All the logic for creating the submenu, populating it with share targets, and handling click
+events (including when the item appears in the overflow menu) is implemented by the {@link
+android.widget.ShareActionProvider}—the only code you need to write is to declare the action
+provider for the menu item and specify the share intent.</p>
+
+<p>By default, the {@link android.widget.ShareActionProvider} retains a ranking for each
+share target based on how often the user selects each one. The share targets used more frequently
+appear at the top of the drop-down list and the target used most often appears directly in the
+action bar as the default share target. By default, the ranking information is
+saved in a private file with a name specified by {@link
+android.widget.ShareActionProvider#DEFAULT_SHARE_HISTORY_FILE_NAME}. If you use the {@link
+android.widget.ShareActionProvider} or an extension of it for only one type of action, then you
+should continue to use this default history file and there's nothing you need to do. However, if you
+use {@link android.widget.ShareActionProvider} or an extension of it for multiple actions with
+semantically different meanings, then each {@link android.widget.ShareActionProvider} should specify
+its own history file in order to maintain its own history. To specify a
+different history file for the {@link android.widget.ShareActionProvider}, call {@link
+android.widget.ShareActionProvider#setShareHistoryFileName setShareHistoryFileName()} and provide
+an XML file name (for example, {@code "custom_share_history.xml"}).</p>
+
+<p class="note"><strong>Note:</strong> Although the {@link android.widget.ShareActionProvider} ranks
+share targets based on frequency of use, the behavior is extensible and extensions of {@link
+android.widget.ShareActionProvider} can perform different behaviors and ranking based on the history
+file (if appropriate).</p>
+
+<p>To add {@link android.widget.ShareActionProvider}, simply define the {@code
+android:actionProviderClass} attribute with {@code "android.widget.ShareActionProvider"}, as shown
+in the XML example above. The only thing left to do is define
+the {@link android.content.Intent} you want to use for sharing. To do so, you must call {@link
+android.view.MenuItem#getActionProvider} to retrieve the {@link android.widget.ShareActionProvider}
+that's associated with a {@link android.view.MenuItem}, then call {@link
+android.widget.ShareActionProvider#setShareIntent setShareIntent()}.</p>
+
+<p>If the format for the share intent depends on the selected item or other variables that change
+during the activity lifecycle, you should save the {@link android.widget.ShareActionProvider} in a
+member field and update it by calling {@link android.widget.ShareActionProvider#setShareIntent
+setShareIntent()} as necessary. For example:</p>
+
+<pre>
+private ShareActionProvider mShareActionProvider;
+...
+
+@Override
+public boolean onCreateOptionsMenu(Menu menu) {
+ mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.menu_share).getActionProvider();
+
+ // If you use more than one ShareActionProvider, each for a different action,
+ // use the following line to specify a unique history file for each one.
+ // mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
+
+ // Set the default share intent
+ mShareActionProvider.setShareIntent(getDefaultShareIntent());
+
+ return true;
+}
+// When you need to update the share intent somewhere else in the app, call
+// mShareActionProvider.{@link android.widget.ShareActionProvider#setShareIntent setShareIntent()}
+</pre>
+
+<p>The {@link android.widget.ShareActionProvider} now handles all user interaction with the item and
+you <em>do not</em> need to handle click events from the {@link
+android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} callback method.</p>
+
+<p>For a sample using the share action provider, see
+<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ActionBarActionProviderActivity.html"
+>ActionBarActionProviderActivity</a>.
+
+
+
+<h3 id="CreatingActionProvider">Creating a custom action provider</h3>
+
+<p>When you want to create an action view that has dynamic behaviors and a default action in the
+overflow menu, extending {@link android.view.ActionProvider} to define those behaviors is a good
+solution. Creating your own action provider offers you an organized and reusable component, rather
+than handling the various action item transformations and behaviors in your fragment or activity
+code. As shown in the previous section, Android provides one implementation of {@link
+android.view.ActionProvider} for share actions: the {@link android.widget.ShareActionProvider}.</p>
+
+<p>To create your own, simply extend the {@link android.view.ActionProvider} class and implement
+its callback methods as appropriate. Most importantly, you should implement the following:</p>
+
+<dl>
+ <dt>{@link android.view.ActionProvider#ActionProvider ActionProvider()}</dt>
+ <dd>This constructor passes you the application {@link android.content.Context}, which you
+should save in a member field to use in the other callback methods.</dd>
+
+ <dt>{@link android.view.ActionProvider#onCreateActionView()}</dt>
+ <dd>This is where you define the action view for the item. Use the {@link
+android.content.Context} acquired from the constructor to instantiate a {@link
+android.view.LayoutInflater} and inflate your action view layout from an XML resource, then hook
+up event listeners. For example:
+<pre>
+public View onCreateActionView() {
+ // Inflate the action view to be shown on the action bar.
+ LayoutInflater layoutInflater = LayoutInflater.from(mContext);
+ View view = layoutInflater.inflate(R.layout.action_provider, null);
+ ImageButton button = (ImageButton) view.findViewById(R.id.button);
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // Do something...
+ }
+ });
+ return view;
+}
+</pre>
+</dd>
+
+ <dt>{@link android.view.ActionProvider#onPerformDefaultAction()}</dt>
+ <dd>The system calls this when the menu item is selected from the overflow menu and the
+action provider should perform a default action for the menu item.
+ <p>However, if your action provider provides a submenu, through the {@link
+android.view.ActionProvider#onPrepareSubMenu onPrepareSubMenu()} callback, then the submenu
+appears even when the menu item is in the overflow menu. Thus, {@link
+android.view.ActionProvider#onPerformDefaultAction()} is never called when there is a
+submenu.</p>
+ <p class="note"><strong>Note:</strong> An activity or a fragment that implements {@link
+android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} can override the action
+provider's default behavior by handling the item-selected event (and returning true), in which
+case, the system does not call {@link android.view.ActionProvider#onPerformDefaultAction()}.</p>
+</dd>
+</dl>
+
+<p>For an example extension of {@link android.view.ActionProvider}, see <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ActionBarSettingsActionProviderActivity.html"
+>ActionBarSettingsActionProviderActivity</a>.</p>
+
+
+
+
+<h2 id="Tabs">Adding Navigation Tabs</h2>
+
+
+<div class="figure" style="width:450px">
+ <img src="{@docRoot}images/ui/actionbar.png" alt="" />
+ <p class="img-caption"><strong>Figure 9.</strong> Screenshot of action bar tabs from the <a
+href="{@docRoot}resources/samples/HoneycombGallery/index.html">Honeycomb Gallery</a> app.</p>
+</div>
+
+<div class="figure" style="width:250px">
+ <img src="{@docRoot}images/ui/actionbar-stacked.png" alt="" />
+ <p class="img-caption"><strong>Figure 10.</strong> Screenshot of tabs in the stacked action
+bar on a narrow screen.</p>
+</div>
+
+<p>When you want to provide navigation tabs in an activity, using the action bar's
+tabs is a great option (instead of using {@link android.widget.TabWidget}), because the
+system adapts the action bar tabs for different screen sizes—placing them in the main action
+bar when the screen is sufficiently wide, or in a separate bar (known as the "stacked action bar")
+when the screen is too narrow, as shown in figures 9 and 10.</p>
+
+<p>To switch between fragments using the tabs, you must perform a fragment
+transaction each time a tab is selected. If you're not familiar with how to change fragments
+using {@link android.app.FragmentTransaction}, first read the <a
+href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> developer guide.</p>
+
+<p>To get started, your layout must include a {@link android.view.ViewGroup} in which you place each
+{@link android.app.Fragment} associated with a tab. Be sure the {@link android.view.ViewGroup} has a
+resource ID so you can reference it from your tab-swapping code. Alternatively, if the tab content
+will fill the activity layout (excluding the action bar), then your activity doesn't need a layout
+at all (you don't even need to call {@link android.app.Activity#setContentView
+setContentView()}). Instead, you can place each fragment in the default root {@link
+android.view.ViewGroup}, which you can refer to with the {@code android.R.id.content} ID (you can
+see this ID used in the sample code below, during fragment transactions).</p>
+
+<p>Once you determine where the fragments appear in the layout, the basic procedure to add tabs
+is:</p>
+<ol>
+ <li>Implement the {@link android.app.ActionBar.TabListener} interface. Callbacks in this
+interface respond to user events on the tabs so you can swap fragments.</li>
+ <li>For each tab you want to add, instantiate an {@link android.app.ActionBar.Tab} and set the
+{@link android.app.ActionBar.TabListener} by calling {@link android.app.ActionBar.Tab#setTabListener
+setTabListener()}. Also set the tab's title and/or icon with {@link
+android.app.ActionBar.Tab#setText setText()} and/or {@link android.app.ActionBar.Tab#setIcon
+setIcon()}.</li>
+ <li>Add each tab to the action bar by calling {@link android.app.ActionBar#addTab addTab()}.</li>
+</ol>
+
+<p>When looking at the {@link android.app.ActionBar.TabListener} interface, notice that the
+callback methods provide only the {@link android.app.ActionBar.Tab} that was selected and a {@link
+android.app.FragmentTransaction} for you to perform fragment transactions—it doesn't say
+anything about what fragment you should swap in or out. Thus, you must define your own association
+between each {@link android.app.ActionBar.Tab} and the appropriate {@link android.app.Fragment} that
+it represents (in order to perform the appropriate fragment transaction). There are several ways you
+can define the association, depending on your design. In the example below, the {@link
+android.app.ActionBar.TabListener} implementation provides a constructor such that each new tab uses
+its own instance of the listener. Each instance of the listener defines several fields that are
+necessary to later perform a transaction on the appropriate fragment.</p>
+
+<p>For example, here's how you might implement the {@link android.app.ActionBar.TabListener}
+such that each tab uses its own instance of the listener:</p>
+<pre>
+public static class TabListener<T extends Fragment> implements ActionBar.TabListener {
+ private Fragment mFragment;
+ private final Activity mActivity;
+ private final String mTag;
+ private final Class<T> mClass;
+
+ /** Constructor used each time a new tab is created.
+ * @param activity The host Activity, used to instantiate the fragment
+ * @param tag The identifier tag for the fragment
+ * @param clz The fragment's Class, used to instantiate the fragment
+ */
+ public TabListener(Activity activity, String tag, Class<T> clz) {
+ mActivity = activity;
+ mTag = tag;
+ mClass = clz;
}
+ /* The following are each of the {@link android.app.ActionBar.TabListener} callbacks */
+
public void onTabSelected(Tab tab, FragmentTransaction ft) {
- ft.add(R.id.fragment_content, mFragment, null);
+ // Check if the fragment is already initialized
+ if (mFragment == null) {
+ // If not, instantiate and add it to the activity
+ mFragment = Fragment.instantiate(mActivity, mClass.getName());
+ ft.add(android.R.id.content, mFragment, mTag);
+ } else {
+ // If it exists, simply attach it in order to show it
+ ft.attach(mFragment);
+ }
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
- ft.remove(mFragment);
+ if (mFragment != null) {
+ // Detach the fragment, because another one is being attached
+ ft.detach(mFragment);
+ }
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
- // do nothing
+ // User selected the already selected tab. Usually do nothing.
}
-
}
</pre>
- <p>This implementation of {@link android.app.ActionBar.TabListener} adds a constructor
-that saves the {@link android.app.Fragment} associated with a tab so that each callback
-can add or remove that fragment.</p>
- </li>
- <li>Get the {@link android.app.ActionBar} for your activity by calling {@link
-android.app.Activity#getActionBar} from your {@link android.app.Activity}, during {@link
-android.app.Activity#onCreate onCreate()} (but be sure you do so <em>after</em> you've called
-{@link android.app.Activity#setContentView setContentView()}).</li>
- <li>Call {@link android.app.ActionBar#setNavigationMode(int)
-setNavigationMode(NAVIGATION_MODE_TABS)} to enable tab mode for the {@link
-android.app.ActionBar}.</li>
- <li>Create each tab for the Action Bar:
- <ol>
- <li>Create a new {@link android.app.ActionBar.Tab} by calling {@link
-android.app.ActionBar#newTab()} on the {@link android.app.ActionBar}.</li>
- <li>Add title text and/or an icon for the tab by calling {@link
-android.app.ActionBar.Tab#setText setText()} and/or {@link android.app.ActionBar.Tab#setIcon
-setIcon()}.
- <p class="note"><strong>Tip:</strong> These methods return the same {@link
-android.app.ActionBar.Tab} instance, so you can chain the calls together.</p></li>
- <li>Declare the {@link android.app.ActionBar.TabListener} to use for the tab by passing an
-instance of your implementation to {@link android.app.ActionBar.Tab#setTabListener
-setTabListener()}.
- </ol>
- </li>
- <li>Add each {@link android.app.ActionBar.Tab} to the Action Bar by calling {@link
-android.app.ActionBar#addTab addTab()} on the {@link android.app.ActionBar} and passing the
-{@link android.app.ActionBar.Tab}.</li>
-</ol>
-<p>For example, the following code combines steps 2 - 5 to create two tabs and add them to
-the Action Bar:</p>
+
+<p class="caution"><strong>Caution:</strong> You <strong>must not</strong> call {@link
+android.app.FragmentTransaction#commit} for the fragment transaction in each of these
+callbacks—the system calls it for you and it may throw an exception if you call it yourself.
+You also <strong>cannot</strong> add these fragment transactions to the back stack.</p>
+
+<p>In this example, the listener simply attaches ({@link android.app.FragmentTransaction#attach
+attach()}) a fragment to the activity layout—or if not instantiated, creates the fragment and
+adds ({@link android.app.FragmentTransaction#add add()}) it to the layout (as a child of the {@code
+android.R.id.content} view group)—when the respective tab is selected, and detaches ({@link
+android.app.FragmentTransaction#detach detach()}) it when the tab is unselected.</p>
+
+<p>The {@link android.app.ActionBar.TabListener} implementation is the bulk of the work. All that
+remains is to create each {@link android.app.ActionBar.Tab} and add it to the {@link
+android.app.ActionBar}. Additionally, you must call {@link
+android.app.ActionBar#setNavigationMode(int) setNavigationMode(NAVIGATION_MODE_TABS)} to make the
+tabs visible. You might also want to disable the activity title by calling {@link
+android.app.ActionBar#setDisplayShowTitleEnabled setDisplayShowTitleEnabled(false)} if the tab
+titles actually indicate the current view.</p>
+
+<p>For example, the following code adds two tabs using the listener defined above:</p>
+
<pre>
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
+ // Notice that setContentView() is not used, because we use the root
+ // android.R.id.content as the container for each fragment
- // setup Action Bar for tabs
- final ActionBar actionBar = getActionBar();
+ // setup action bar for tabs
+ ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
- // remove the activity title to make space for tabs
actionBar.setDisplayShowTitleEnabled(false);
- // instantiate fragment for the tab
- Fragment artistsFragment = new ArtistsFragment();
- // add a new tab and set its title text and tab listener
- actionBar.addTab(actionBar.newTab().setText(R.string.tab_artists)
- .setTabListener(new TabListener(artistsFragment)));
+ Tab tab = actionBar.newTab()
+ .setText(R.string.artist)
+ .setTabListener(new TabListener<ArtistFragment>(
+ this, "artist", ArtistFragment.class));
+ actionBar.addTab(tab);
- Fragment albumsFragment = new AlbumsFragment();
- actionBar.addTab(actionBar.newTab().setText(R.string.tab_albums)
- .setTabListener(new TabListener(albumsFragment)));
+ tab = actionBar.newTab()
+ .setText(R.string.album)
+ .setTabListener(new TabListener<AlbumFragment>(
+ this, "album", AlbumFragment.class));
+ actionBar.addTab(tab);
}
</pre>
-<p>All the behaviors that occur when a tab is selected must be defined by your {@link
-android.app.ActionBar.TabListener} callback methods. When a tab is selected, it receives a call to
-{@link android.app.ActionBar.TabListener#onTabSelected onTabSelected()} and that's where you should
-add the appropriate fragment to the designated view in your layout, using {@link
-android.app.FragmentTransaction#add add()} with the provided {@link
-android.app.FragmentTransaction}. Likewise, when a tab is deselected (because another tab becomes
-selected), you should remove that fragment from the layout, using {@link
-android.app.FragmentTransaction#remove remove()}.</p>
+<p class="note"><strong>Note:</strong> The above implementation for {@link
+android.app.ActionBar.TabListener} is one of several possible techniques. You can see more of
+this style in the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentTabs.html"
+>API Demos</a> app.</p>
-<p class="caution"><strong>Caution:</strong> You <strong>must not</strong> call {@link
-android.app.FragmentTransaction#commit} for these transactions—the system calls it for you
-and it may throw an exception if you call it yourself. You also <strong>cannot</strong> add these
-fragment transactions to the back stack.</p>
-<p>If your activity is stopped, you should retain the currently selected tab with the saved state so
-that when the user returns to your application, you can open the tab. When it's time to save the
+<p>If your activity stops, you should retain the currently selected tab with the <a
+href="{@docRoot}guide/topics/fundamentals/activities.html#SavingActivityState">saved instance
+state</a> so you can open the appropriate tab when the user returns. When it's time to save the
state, you can query the currently selected tab with {@link
android.app.ActionBar#getSelectedNavigationIndex()}. This returns the index position of the selected
tab.</p>
-<p class="caution"><strong>Caution:</strong> It's important that you save
-the state of each fragment as necessary, so when the user switches fragments with the tabs,
-then returns to a previous fragment, it appears the way they left. For information about saving
-the state of your fragment, see the <a
-href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> developer guide.</p>
+<p class="caution"><strong>Caution:</strong> It's important that you save the state of each fragment
+as necessary, so that when users switch fragments with the tabs and then return to a previous
+fragment, it looks the way it did when they left. For information about saving the state of your
+fragment, see the <a href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a>
+developer guide.</p>
+<p class="note"><strong>Note:</strong> In some cases, the Android system will show your action
+bar tabs as a drop-down list in order to ensure the best fit in the action bar.</p>
<h2 id="Dropdown">Adding Drop-down Navigation</h2>
-<p>As another mode of navigation within your activity, you can provide a drop-down list in the
-Action Bar. For example, the drop-down list can provide alternative modes for sorting the content in
-the activity or switching the user's account.</p>
+<p>As another mode of navigation (or filtering) within your activity, the action bar offers a
+built in drop-down list. For example, the drop-down list can offer different modes by which content
+in the activity is sorted.</p>
<!--
<div class="figure" style="width:135px">
<img src="{@docRoot}images/ui/actionbar-dropdown.png" alt="" />
<p class="img-caption"><strong>Figure 5.</strong> Screenshot of a drop-down navigation list in the
-Action Bar.</p>
+action bar.</p>
</div>
-->
-<p>Here's a quick list of steps to enable drop-down navigation:</p>
+<p>The basic procedure to enable drop-down navigation is:</p>
<ol>
<li>Create a {@link android.widget.SpinnerAdapter} that provides the
list of selectable items for the drop-down and the layout to use when drawing each item in the
list.</li>
- <li>Implement {@link android.app.ActionBar.OnNavigationListener} to define the behavior when the
-user selects an item from the list.</li>
- <li>Enable navigation mode for the Action Bar with {@link
+ <li>Implement {@link android.app.ActionBar.OnNavigationListener} to define the behavior that
+occurs when the user selects an item from the list.</li>
+ <li>Enable navigation mode for the action bar with {@link
android.app.ActionBar#setNavigationMode setNavigationMode()}. For example:
<pre>
ActionBar actionBar = getActionBar();
@@ -563,13 +1119,13 @@
android.app.Activity#onCreate
onCreate()} method.</p>
</li>
- <li>Then, set the callback for the drop-down list with {@link
+ <li>Set the callback for the drop-down list with {@link
android.app.ActionBar#setListNavigationCallbacks setListNavigationCallbacks()}. For example:
<pre>
actionBar.setListNavigationCallbacks(mSpinnerAdapter, mNavigationCallback);
</pre>
<p>This method takes your {@link android.widget.SpinnerAdapter} and {@link
-android.app.ActionBar.OnNavigationListener}. More about these next.</p>
+android.app.ActionBar.OnNavigationListener}.</p>
</li>
</ol>
@@ -594,7 +1150,7 @@
<div class="toggle-content-toggleme">
<p>{@link android.widget.SpinnerAdapter} is an adapter that provides data for a spinner widget,
-such as the drop-down list in the Action Bar. {@link android.widget.SpinnerAdapter} is an interface
+such as the drop-down list in the action bar. {@link android.widget.SpinnerAdapter} is an interface
that you can implement, but Android includes some useful implementations that you can extend, such
as {@link android.widget.ArrayAdapter} and {@link
android.widget.SimpleCursorAdapter}. For example, here's an easy way to create a {@link
@@ -713,140 +1269,199 @@
<h2 id="Style">Styling the Action Bar</h2>
-<p>The Action Bar is the heading for your application and a primary interaction point for users,
-so you might want to modify some of its design in order to make it feel more integrated with your
-application design. There are several ways you can do this if you wish.</p>
+<p>If you've implemented a custom design for the widgets in your application, you might
+also want to redesign some of the action bar to match your app design. To do so, you need to use
+Android's <a
+href="{@docRoot}guide/topics/ui/themes.html">style and theme</a> framework to restyle the action
+bar using special style properties.</p>
-<p>For simple modifications to the {@link android.app.ActionBar}, you can use the following
-methods:</p>
+
+<p class="note"><strong>Note:</strong> In order for background images to change appearance
+depending on the current button state (selected, pressed, unselected), the drawable resource you use
+must be a <a href="{@docRoot}guide/topics/resources/drawable-resource.html#StateList">state
+list drawable</a>.</p>
+
+<p class="caution"><strong>Caution:</strong> For all background drawables you provide, be sure to use <a
+href="{@docRoot}guide/topics/graphics/2d-graphics.html#nine-patch">Nine-Patch drawables</a> to allow
+stretching. The Nine-Patch image should be <em>smaller</em> than 40px tall and 30px wide (for the mdpi asset).</p>
+
+
+<h3 id="GeneralStyles">General appearance</h3>
<dl>
- <dt>{@link android.app.ActionBar#setBackgroundDrawable setBackgroundDrawable()}</dt>
- <dd>Sets a drawable to use as the Action Bar's background. The drawable should be a <a
-href="{@docRoot}guide/topics/graphics/2d-graphics.html#nine-patch">Nine-patch</a> image, a <a
-href="{@docRoot}guide/topics/resources/drawable-resource.html#Shape">shape</a>, or a <a
-href="{@docRoot}guide/topics/resources/more-resources.html#Color">solid color</a>, so the system can
-resize the drawable based on the size of the Action Bar (you should <em>not</em> use a fixed-size
-bitmap image).</dd>
- <dt>{@link android.app.ActionBar#setDisplayUseLogoEnabled setDisplayUseLogoEnabled()}</dt>
- <dd>Enables the use of an alternative image (a "logo") in the Action Bar, instead of the default
-application icon. A logo is often a wider, more detailed image that represents the application.
-When this is enabled, the system uses the logo image defined for the application (or the
-individual activity) in the manifest file, with the <a
-href="{@docRoot}guide/topics/manifest/application-element.html#logo">{@code android:logo}</a>
-attribute. The logo will be resized as necessary to fit the height of the Action Bar. (Best
-practice is to design the logo at the same size as your application icon.)</dd>
-</dl>
-
-
-<p>For more complex customizations, you can use Android's <a
-href="{@docRoot}guide/topics/ui/themes.html">style and theme</a> framework to restyle your Action
-Bar in several ways.</p>
-
-<p>The Action Bar has two standard themes, "dark" and "light". The dark theme is applied with
-the default holographic theme, as specified by the {@link android.R.style#Theme_Holo Theme.Holo}
-theme. If you want a white background with dark text, instead, you can apply the {@link
-android.R.style#Theme_Holo_Light Theme.Holo.Light} theme to the activity in the manifest file. For
-example:</p>
-
+ <dt>{@link android.R.attr#windowActionBarOverlay
+ android:windowActionBarOverlay}</dt>
+ <dd>Declares whether the action bar should overlay the activity layout rather than offset the
+activity's layout position (for example, the Gallery app uses overlay mode). This is
+{@code false} by default.
+ <p>Normally, the action bar requires its own space on the screen and your activity layout fills in
+what's left over. When the action bar is in overlay mode, your activity layout uses all the
+available space and the system draws the action bar on top. Overlay mode can be useful if you want
+your content to keep a fixed size and position when the action bar is hidden and shown. You might
+also like to use it purely as a visual effect, because you can use a semi-transparent background
+for the action bar so the user can still see some of your activity layout behind the action
+bar.</p>
+ <p class="note"><strong>Note:</strong> The {@link android.R.style#Theme_Holo Holo} theme families
+draw the action bar with a semi-transparent background by default. However, you can modify it with
+your own styles and the {@link android.R.style#Theme_DeviceDefault DeviceDefault} theme on
+different devices might use an opaque background by default.</p>
+ <p>When overlay mode is enabled, your activity layout has no awareness of the action bar laying on
+top of it. So, you must be careful not to place any important information or UI components in the
+area overlayed by the action bar. If appropriate, you can refer to the platform's value for {@link
+android.R.attr#actionBarSize} to determine the height of the action bar, by referencing it
+in your XML layout. For example:</p>
<pre>
-<activity android:name=".ExampleActivity"
- android:theme="@android:style/Theme.Holo.Light" />
+<SomeView
+ ...
+ android:layout_marginTop="?android:attr/actionBarSize" />
</pre>
-
-<p>For more control, you can override either the {@link android.R.style#Theme_Holo
-Theme.Holo} or {@link android.R.style#Theme_Holo_Light Theme.Holo.Light} theme and apply custom
-styles to certain aspects of the Action Bar. Some of the Action Bar properties you can customize
-include the following:</p>
-
-<dl>
- <dt>{@link android.R.styleable#Theme_actionBarTabStyle
- android:actionBarTabStyle}</dt>
- <dd>Style for tabs in the Action Bar.</dd>
-
- <dt>{@link android.R.styleable#Theme_actionBarTabBarStyle
- android:actionBarTabBarStyle}</dt>
- <dd>Style for the bar that appears below tabs in the Action Bar.</dd>
-
- <dt>{@link android.R.styleable#Theme_actionBarTabTextStyle
- android:actionBarTabTextStyle}</dt>
- <dd>Style for the text in the tabs.</dd>
-
- <dt>{@link android.R.styleable#Theme_actionDropDownStyle
- android:actionDropDownStyle}</dt>
- <dd>Style for the drop-down list used for the overflow menu and drop-down navigation.</dd>
-
- <dt>{@link android.R.styleable#Theme_actionButtonStyle
- android:actionButtonStyle}</dt>
- <dd>Style for the background image used for buttons in the Action Bar.</dd>
+ <p>You can also retrieve the action bar height at runtime with {@link
+android.app.ActionBar#getHeight()}. This reflects the height of the action bar at the time it's
+called, which might not include the stacked action bar (due to navigation tabs) if called during early
+activity lifecycle methods. To see how you can determine the total height at runtime, including the
+stacked action bar, see the <a
+href="{@docRoot}resources/samples/HoneycombGallery/src/com/example/android/hcgallery/TitlesFragment.html"
+>{@code TitlesFragment}</a> class in the <a
+href="{@docRoot}resources/samples/HoneycombGallery/index.html"
+>Honeycomb Gallery</a> sample app.</p>
+</dd>
</dl>
-<p>For example, here's a resource file that defines a custom theme for the Action Bar, based on
-the standard {@link android.R.style#Theme_Holo Theme.Holo} theme:</p>
+
+<h3 id="ActionItemStyles">Action items</h3>
+
+<dl>
+ <dt>{@link android.R.attr#actionButtonStyle
+ android:actionButtonStyle}</dt>
+ <dd>Defines a style resource for the action item buttons.</dd>
+
+ <dt>{@link android.R.attr#actionBarItemBackground
+ android:actionBarItemBackground}</dt>
+ <dd>Defines a drawable resource for each action item's background. (Added in API level 14.)</dd>
+
+ <dt>{@link android.R.attr#itemBackground
+ android:itemBackground}</dt>
+ <dd>Defines a drawable resource for each overflow menu item's background.</dd>
+
+ <dt>{@link android.R.attr#actionBarDivider
+ android:actionBarDivider}</dt>
+ <dd>Defines a drawable resource for the divider between action items. (Added in API level
+14.)</dd>
+
+ <dt>{@link android.R.attr#actionMenuTextColor
+ android:actionMenuTextColor}</dt>
+ <dd>Defines a color for text that appears in an action item.</dd>
+
+ <dt>{@link android.R.attr#actionMenuTextAppearance
+ android:actionMenuTextAppearance}</dt>
+ <dd>Defines a style resource for text that appears in an action item.</dd>
+
+ <dt>{@link android.R.attr#actionBarWidgetTheme
+ android:actionBarWidgetTheme}</dt>
+ <dd>Defines a theme resource for widgets that are inflated into the action bar as <a
+href="#ActionView">action views</a>. (Added in API level 14.)</dd>
+</dl>
+
+
+<h3 id="NavigationStyles">Navigation tabs</h3>
+
+<dl>
+ <dt>{@link android.R.attr#actionBarTabStyle
+ android:actionBarTabStyle}</dt>
+ <dd>Defines a style resource for tabs in the action bar.</dd>
+
+ <dt>{@link android.R.attr#actionBarTabBarStyle
+ android:actionBarTabBarStyle}</dt>
+ <dd>Defines a style resource for the thin bar that appears below the navigation tabs.</dd>
+
+ <dt>{@link android.R.attr#actionBarTabTextStyle
+ android:actionBarTabTextStyle}</dt>
+ <dd>Defines a style resource for text in the navigation tabs.</dd>
+</dl>
+
+
+<h3 id="DropDownStyles">Drop-down lists</h3>
+
+<dl>
+ <dt>{@link android.R.attr#actionDropDownStyle
+ android:actionDropDownStyle}</dt>
+ <dd>Defines a style for the drop-down navigation (such as the background and text styles).</dd>
+</dl>
+
+
+
+<p>For example, here's a file that defines a few custom styles for the action bar:</p>
<pre>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- the theme applied to the application or activity -->
- <style name="CustomActionBar" parent="android:style/Theme.Holo.Light">
- <item name="android:actionBarTabTextStyle">@style/customActionBarTabTextStyle</item>
- <item name="android:actionBarTabStyle">@style/customActionBarTabStyle</item>
- <item name="android:actionBarTabBarStyle">@style/customActionBarTabBarStyle</item>
+ <style name="CustomActivityTheme" parent="@android:style/Theme.Holo">
+ <item name="android:actionBarTabTextStyle">@style/CustomTabTextStyle</item>
+ <item name="android:actionBarDivider">@drawable/ab_divider</item>
+ <item name="android:actionBarItemBackground">@drawable/ab_item_background</item>
</style>
- <!-- style for the tab text -->
- <style name="customActionBarTabTextStyle">
- <item name="android:textColor">#2966c2</item>
- <item name="android:textSize">20sp</item>
- <item name="android:typeface">sans</item>
- </style>
-
- <!-- style for the tabs -->
- <style name="customActionBarTabStyle">
- <item name="android:background">@drawable/actionbar_tab_bg</item>
- <item name="android:paddingLeft">20dp</item>
- <item name="android:paddingRight">20dp</item>
- </style>
-
- <!-- style for the tab bar -->
- <style name="customActionBarTabBarStyle">
- <item name="android:background">@drawable/actionbar_tab_bar</item>
+ <!-- style for the action bar tab text -->
+ <style name="CustomTabTextStyle">
+ <item name="android:textColor">#2456c2</item>
</style>
</resources>
</pre>
-<p class="note"><strong>Note:</strong> In order for the tab background image to change,
-depending on the current tab state (selected, pressed, unselected), the drawable resource used
-must be a <a href="{@docRoot}guide/topics/resources/drawable-resource.html#StateList">state
-list drawable</a>. Also be certain that your theme declares a parent theme, from which it
-inherits all styles not explicitly declared in your theme.</p>
+<p class="note"><strong>Note:</strong> Be certain that your theme declares a parent theme in the
+{@code <style>} tag, from which it inherits all styles not explicitly declared by your theme.
+When modifying the action bar, using a parent theme is important so that you can simply override the
+action bar styles you want to change without re-implementing the styles you want to leave alone
+(such as text appearance or padding in action items).</p>
<p>You can apply your custom theme to the entire application or to individual activities in your
-manifest file, like this:</p>
+manifest file like this:</p>
<pre>
-<application android:theme="@style/CustomActionBar"
+<application android:theme="@style/CustomActivityTheme"
... />
</pre>
-<p>Additionally, if you want to create a custom theme for your activity that removes the Action
-Bar completely, use the following style attributes:</p>
-
-<dl>
- <dt>{@link android.R.styleable#Theme_windowActionBar
- android:windowActionBar}</dt>
- <dd>Set this style property {@code false} to remove the Action Bar.</dd>
-
- <dt>{@link android.R.styleable#Theme_windowNoTitle
- android:windowNoTitle}</dt>
- <dd>Set this style property {@code true} to also remove the traditional title bar.</dd>
-</dl>
-
-<p>For more information about using themes in your application, read <a
+<p>For more information about using style and theme resources in your application, read <a
href="{@docRoot}guide/topics/ui/themes.html">Styles and Themes</a>.</p>
+<h3 id="AdvancedStyles">Advanced styling</h3>
+
+ <p>If you need more advanced styling for the action bar than is available with the
+properties above, you can include {@link android.R.attr#actionBarStyle android:actionBarStyle} and
+{@link android.R.attr#actionBarSplitStyle android:actionBarSplitStyle} in your activity's theme.
+Each of these specifies another style that can define various properties for the action bar,
+including different backgrounds with {@link android.R.attr#background android:background}, {@link
+android.R.attr#backgroundSplit android:backgroundSplit}, and {@link android.R.attr#backgroundStacked
+android:backgroundStacked}. If you override these action bar styles, be sure that you define a
+parent action bar style such as {@link android.R.style#Widget_Holo_ActionBar
+Widget.Holo.ActionBar}.</p>
+
+<p>For example, if you want to change the action bar's background, you could use the following
+styles:</p>
+
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- the theme applied to the application or activity -->
+ <style name="CustomActivityTheme" parent="@android:style/Theme.Holo">
+ <item name="android:actionBarTabTextStyle">@style/customTabTextStyle</item>
+ <!-- other activity and action bar styles here -->
+ </style>
+
+ <!-- style for the action bar, simply to change the background -->
+ <style parent="@android:style/Widget.Holo.ActionBar">
+ <item name="android:background">@drawable/ab_background</item>
+ <item name="android:backgroundSplit">@drawable/ab_background</item>
+ </style>
+</resources>
+</pre>
+
+
+
diff --git a/docs/html/guide/topics/ui/menus.jd b/docs/html/guide/topics/ui/menus.jd
index 2948244..7b5b3dc 100644
--- a/docs/html/guide/topics/ui/menus.jd
+++ b/docs/html/guide/topics/ui/menus.jd
@@ -198,10 +198,11 @@
}
</pre>
-<div class="figure" style="width:500px">
-<img src="{@docRoot}images/ui/actionbar.png" height="34" alt="" />
-<p class="img-caption"><strong>Figure 2.</strong> Screenshot of the Action Bar in the Email
-application, with two action items from the Options Menu, plus the overflow menu.</p>
+<div class="figure" style="width:450px">
+<img src="{@docRoot}images/ui/actionbar.png" alt="" />
+<p class="img-caption"><strong>Figure 2.</strong> Action bar from the <a
+href="{@docRoot}resources/samples/HoneycombGallery/index.html">Honeycomb Gallery</a> app, including
+navigation tabs and a camera action item (plus the overflow menu button).</p>
</div>
<p>You can also populate the menu in code, using {@link android.view.Menu#add(int,int,int,int)
diff --git a/docs/html/images/ui/actionbar-actionview.png b/docs/html/images/ui/actionbar-actionview.png
index cc18f9b..9103dc4 100644
--- a/docs/html/images/ui/actionbar-actionview.png
+++ b/docs/html/images/ui/actionbar-actionview.png
Binary files differ
diff --git a/docs/html/images/ui/actionbar-item-withtext.png b/docs/html/images/ui/actionbar-item-withtext.png
index 61742d3..5f7aecc 100644
--- a/docs/html/images/ui/actionbar-item-withtext.png
+++ b/docs/html/images/ui/actionbar-item-withtext.png
Binary files differ
diff --git a/docs/html/images/ui/actionbar-logo.png b/docs/html/images/ui/actionbar-logo.png
index df914bc..c62b3e2 100644
--- a/docs/html/images/ui/actionbar-logo.png
+++ b/docs/html/images/ui/actionbar-logo.png
Binary files differ
diff --git a/docs/html/images/ui/actionbar-navigate-back.png b/docs/html/images/ui/actionbar-navigate-back.png
new file mode 100644
index 0000000..9431bca
--- /dev/null
+++ b/docs/html/images/ui/actionbar-navigate-back.png
Binary files differ
diff --git a/docs/html/images/ui/actionbar-navigate-up.png b/docs/html/images/ui/actionbar-navigate-up.png
new file mode 100644
index 0000000..09243b4
--- /dev/null
+++ b/docs/html/images/ui/actionbar-navigate-up.png
Binary files differ
diff --git a/docs/html/images/ui/actionbar-navigate-up.xcf b/docs/html/images/ui/actionbar-navigate-up.xcf
new file mode 100644
index 0000000..bf1849a
--- /dev/null
+++ b/docs/html/images/ui/actionbar-navigate-up.xcf
Binary files differ
diff --git a/docs/html/images/ui/actionbar-searchview.png b/docs/html/images/ui/actionbar-searchview.png
new file mode 100644
index 0000000..7ae46a0
--- /dev/null
+++ b/docs/html/images/ui/actionbar-searchview.png
Binary files differ
diff --git a/docs/html/images/ui/actionbar-shareaction.png b/docs/html/images/ui/actionbar-shareaction.png
new file mode 100644
index 0000000..fdbb02c
--- /dev/null
+++ b/docs/html/images/ui/actionbar-shareaction.png
Binary files differ
diff --git a/docs/html/images/ui/actionbar-stacked.png b/docs/html/images/ui/actionbar-stacked.png
new file mode 100644
index 0000000..76c8908
--- /dev/null
+++ b/docs/html/images/ui/actionbar-stacked.png
Binary files differ
diff --git a/docs/html/images/ui/actionbar.png b/docs/html/images/ui/actionbar.png
index dcd8449..1d01583 100644
--- a/docs/html/images/ui/actionbar.png
+++ b/docs/html/images/ui/actionbar.png
Binary files differ
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index 941f693..50b20ce 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -1,8 +1,8 @@
page.title=ADT Plugin for Eclipse
-adt.zip.version=15.0.0
-adt.zip.download=ADT-15.0.0.zip
-adt.zip.bytes=6750682
-adt.zip.checksum=264f40a89a1107b0c422adae4e1ce0d1
+adt.zip.version=15.0.1
+adt.zip.download=ADT-15.0.1.zip
+adt.zip.bytes=6752327
+adt.zip.checksum=2c12a71d7124aa512b8ee016e19c0e69
@jd:body
@@ -109,10 +109,44 @@
</style>
+
<div class="toggleable opened">
<a href="#" onclick="return toggleDiv(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px"
width="9px" />
+ADT 15.0.1</a> <em>(November 2011)</em>
+ <div class="toggleme">
+<dl>
+ <dt>Dependencies:</dt>
+
+ <dd>ADT 15.0.1 is designed for use with <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r15</a>.
+ If you haven't already installed SDK Tools r15 into your SDK, use the Android SDK and AVD Manager to
+ do so.</dd>
+
+ <dt>Bug fixes:</dt>
+ <dd>
+ <ul>
+ <li>Fixed how source files are attached to library project <code>.jar</code> files.</li>
+ <li>Fixed how the <code>bin/</code> folder for library projects are refreshed. This ensures that parent projects pick up changes in library projects.</li>
+ <li>Fixed how a parent project's library container is updated when a library project is recompiled. This ensures that parent projects are
+ recompiled when code in a library project changes.</li>
+ <li>Fixed how <code>res/</code> folders are checked in library projects. This ensures that all <code>res</code> folders are properly included
+ even if Eclipse is not aware of them due to refresh issues.</li>
+ <li>Fixed issue that prevented <code>aapt</code> from running when editing certain XML files.</li>
+ <li>Fixed minor XML formatting issues.</li>
+ </ul>
+ </dd>
+</dl>
+
+</div>
+</div>
+
+
+
+<div class="toggleable closed">
+ <a href="#" onclick="return toggleDiv(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px"
+width="9px" />
ADT 15.0.0</a> <em>(October 2011)</em>
<div class="toggleme">
<dl>
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index afe6a6e..0ae2c6d 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -169,7 +169,7 @@
<span style="display:none" class="zh-TW"></span>
</h2>
<ul>
- <li><a href="<?cs var:toroot ?>sdk/eclipse-adt.html">ADT 15.0.0
+ <li><a href="<?cs var:toroot ?>sdk/eclipse-adt.html">ADT 15.0.1
<span style="display:none" class="de"></span>
<span style="display:none" class="es"></span>
<span style="display:none" class="fr"></span>
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 27d863d..15c2bab 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -202,6 +202,10 @@
// getCurrentScalingMode returns the scaling mode of the current buffer
uint32_t getCurrentScalingMode() const;
+ // isSynchronousMode returns whether the SurfaceTexture is currently in
+ // synchronous mode.
+ bool isSynchronousMode() const;
+
// abandon frees all the buffers and puts the SurfaceTexture into the
// 'abandoned' state. Once put in this state the SurfaceTexture can never
// leave it. When in the 'abandoned' state, all methods of the
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index 57f9e15..971a1b8 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -40,6 +40,7 @@
protected:
SurfaceTextureClient();
+ virtual ~SurfaceTextureClient();
void setISurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture);
private:
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index 8c1c593..446720b 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -153,6 +153,9 @@
bool mStarted;
int32_t mNumFramesEncoded;
+ // Time between capture of two frames.
+ int64_t mTimeBetweenFrameCaptureUs;
+
CameraSource(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId,
Size videoSize, int32_t frameRate,
diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h
index 0e264c7..b060691 100644
--- a/include/media/stagefright/CameraSourceTimeLapse.h
+++ b/include/media/stagefright/CameraSourceTimeLapse.h
@@ -57,10 +57,6 @@
int32_t mVideoWidth;
int32_t mVideoHeight;
- // Time between capture of two frames during time lapse recording
- // Negative value indicates that timelapse is disabled.
- int64_t mTimeBetweenTimeLapseFrameCaptureUs;
-
// Time between two frames in final video (1/frameRate)
int64_t mTimeBetweenTimeLapseVideoFramesUs;
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index c21d19d..84f8282 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -336,6 +336,10 @@
int64_t retrieveDecodingTimeUs(bool isCodecSpecific);
+ status_t parseAVCCodecSpecificData(
+ const void *data, size_t size,
+ unsigned *profile, unsigned *level);
+
OMXCodec(const OMXCodec &);
OMXCodec &operator=(const OMXCodec &);
};
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index ee54bf4..beb23f6 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -441,6 +441,11 @@
mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
}
+ if (mCurrentTexture == buf) {
+ // The current texture no longer references the buffer in this slot
+ // since we just allocated a new buffer.
+ mCurrentTexture = INVALID_BUFFER_SLOT;
+ }
returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
}
ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", buf,
@@ -641,8 +646,9 @@
Mutex::Autolock lock(mMutex);
if (mAbandoned) {
- ST_LOGE("disconnect: SurfaceTexture has been abandoned!");
- return NO_INIT;
+ // it is not really an error to disconnect after the surface
+ // has been abandoned, it should just be a no-op.
+ return NO_ERROR;
}
int err = NO_ERROR;
@@ -1004,6 +1010,11 @@
return mCurrentScalingMode;
}
+bool SurfaceTexture::isSynchronousMode() const {
+ Mutex::Autolock lock(mMutex);
+ return mSynchronousMode;
+}
+
int SurfaceTexture::query(int what, int* outValue)
{
Mutex::Autolock lock(mMutex);
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 98fa171..48070d6 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -36,6 +36,12 @@
SurfaceTextureClient::init();
}
+SurfaceTextureClient::~SurfaceTextureClient() {
+ if (mConnectedToCpu) {
+ SurfaceTextureClient::disconnect(NATIVE_WINDOW_API_CPU);
+ }
+}
+
void SurfaceTextureClient::init() {
// Initialize the ANativeWindow function pointers.
ANativeWindow::setSwapInterval = hook_setSwapInterval;
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 93ebfb9..6d1b951 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -396,7 +396,8 @@
1.0f, 1.0f,
};
- glVertexAttribPointer(mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, triangleVertices);
+ glVertexAttribPointer(mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0,
+ triangleVertices);
ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
glEnableVertexAttribArray(mPositionHandle);
ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
@@ -410,13 +411,17 @@
// XXX: These calls are not needed for GL_TEXTURE_EXTERNAL_OES as
// they're setting the defautls for that target, but when hacking things
// to use GL_TEXTURE_2D they are needed to achieve the same behavior.
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR);
ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER,
+ GL_LINEAR);
ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S,
+ GL_CLAMP_TO_EDGE);
ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T,
+ GL_CLAMP_TO_EDGE);
ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
GLfloat texMatrix[16];
@@ -640,8 +645,8 @@
for (int i = 0; i < 5; i++) {
const android_native_rect_t& crop(crops[i]);
- SCOPED_TRACE(String8::format("rect{ l: %d t: %d r: %d b: %d }", crop.left,
- crop.top, crop.right, crop.bottom).string());
+ SCOPED_TRACE(String8::format("rect{ l: %d t: %d r: %d b: %d }",
+ crop.left, crop.top, crop.right, crop.bottom).string());
ASSERT_EQ(NO_ERROR, native_window_set_crop(mANW.get(), &crop));
@@ -650,13 +655,15 @@
ASSERT_TRUE(anb != NULL);
sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
- ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
+ ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(),
+ buf->getNativeBuffer()));
uint8_t* img = NULL;
buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
fillYV12BufferRect(img, texWidth, texHeight, buf->getStride(), crop);
buf->unlock();
- ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
+ ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(),
+ buf->getNativeBuffer()));
mST->updateTexImage();
@@ -708,7 +715,8 @@
class ProducerThread : public Thread {
public:
- ProducerThread(const sp<ANativeWindow>& anw, const TestPixel* testPixels):
+ ProducerThread(const sp<ANativeWindow>& anw,
+ const TestPixel* testPixels):
mANW(anw),
mTestPixels(testPixels) {
}
@@ -940,82 +948,6 @@
EXPECT_TRUE(checkPixel( 3, 52, 35, 231, 35, 35));
}
-TEST_F(SurfaceTextureGLTest, TexturingFromGLFilledRGBABufferPow2) {
- const int texWidth = 64;
- const int texHeight = 64;
-
- mST->setDefaultBufferSize(texWidth, texHeight);
-
- // Do the producer side of things
- EGLSurface stcEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
- mANW.get(), NULL);
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
- ASSERT_NE(EGL_NO_SURFACE, stcEglSurface);
-
- EXPECT_TRUE(eglMakeCurrent(mEglDisplay, stcEglSurface, stcEglSurface,
- mEglContext));
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
- glClearColor(0.6, 0.6, 0.6, 0.6);
- glClear(GL_COLOR_BUFFER_BIT);
-
- glEnable(GL_SCISSOR_TEST);
- glScissor(4, 4, 4, 4);
- glClearColor(1.0, 0.0, 0.0, 1.0);
- glClear(GL_COLOR_BUFFER_BIT);
-
- glScissor(24, 48, 4, 4);
- glClearColor(0.0, 1.0, 0.0, 1.0);
- glClear(GL_COLOR_BUFFER_BIT);
-
- glScissor(37, 17, 4, 4);
- glClearColor(0.0, 0.0, 1.0, 1.0);
- glClear(GL_COLOR_BUFFER_BIT);
-
- eglSwapBuffers(mEglDisplay, stcEglSurface);
-
- // Do the consumer side of things
- EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
- mEglContext));
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
- glDisable(GL_SCISSOR_TEST);
-
- mST->updateTexImage();
-
- // We must wait until updateTexImage has been called to destroy the
- // EGLSurface because we're in synchronous mode.
- eglDestroySurface(mEglDisplay, stcEglSurface);
-
- glClearColor(0.2, 0.2, 0.2, 0.2);
- glClear(GL_COLOR_BUFFER_BIT);
-
- glViewport(0, 0, texWidth, texHeight);
- drawTexture();
-
- EXPECT_TRUE(checkPixel( 0, 0, 153, 153, 153, 153));
- EXPECT_TRUE(checkPixel(63, 0, 153, 153, 153, 153));
- EXPECT_TRUE(checkPixel(63, 63, 153, 153, 153, 153));
- EXPECT_TRUE(checkPixel( 0, 63, 153, 153, 153, 153));
-
- EXPECT_TRUE(checkPixel( 4, 7, 255, 0, 0, 255));
- EXPECT_TRUE(checkPixel(25, 51, 0, 255, 0, 255));
- EXPECT_TRUE(checkPixel(40, 19, 0, 0, 255, 255));
- EXPECT_TRUE(checkPixel(29, 51, 153, 153, 153, 153));
- EXPECT_TRUE(checkPixel( 5, 32, 153, 153, 153, 153));
- EXPECT_TRUE(checkPixel(13, 8, 153, 153, 153, 153));
- EXPECT_TRUE(checkPixel(46, 3, 153, 153, 153, 153));
- EXPECT_TRUE(checkPixel(30, 33, 153, 153, 153, 153));
- EXPECT_TRUE(checkPixel( 6, 52, 153, 153, 153, 153));
- EXPECT_TRUE(checkPixel(55, 33, 153, 153, 153, 153));
- EXPECT_TRUE(checkPixel(16, 29, 153, 153, 153, 153));
- EXPECT_TRUE(checkPixel( 1, 30, 153, 153, 153, 153));
- EXPECT_TRUE(checkPixel(41, 37, 153, 153, 153, 153));
- EXPECT_TRUE(checkPixel(46, 29, 153, 153, 153, 153));
- EXPECT_TRUE(checkPixel(15, 25, 153, 153, 153, 153));
- EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153));
-}
-
TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) {
class ProducerThread : public Thread {
public:
@@ -1093,13 +1025,284 @@
reinterpret_cast<ProducerThread*>(pt.get())->getDequeueError());
}
+TEST_F(SurfaceTextureGLTest, InvalidWidthOrHeightFails) {
+ int texHeight = 16;
+ ANativeWindowBuffer* anb;
+
+ GLint maxTextureSize;
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
+
+ // make sure it works with small textures
+ mST->setDefaultBufferSize(16, texHeight);
+ EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+ EXPECT_EQ(16, anb->width);
+ EXPECT_EQ(texHeight, anb->height);
+ EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
+ EXPECT_EQ(NO_ERROR, mST->updateTexImage());
+
+ // make sure it works with GL_MAX_TEXTURE_SIZE
+ mST->setDefaultBufferSize(maxTextureSize, texHeight);
+ EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+ EXPECT_EQ(maxTextureSize, anb->width);
+ EXPECT_EQ(texHeight, anb->height);
+ EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
+ EXPECT_EQ(NO_ERROR, mST->updateTexImage());
+
+ // make sure it fails with GL_MAX_TEXTURE_SIZE+1
+ mST->setDefaultBufferSize(maxTextureSize+1, texHeight);
+ EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+ EXPECT_EQ(maxTextureSize+1, anb->width);
+ EXPECT_EQ(texHeight, anb->height);
+ EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
+ ASSERT_NE(NO_ERROR, mST->updateTexImage());
+}
+
/*
- * This test is for testing GL -> GL texture streaming via SurfaceTexture. It
- * contains functionality to create a producer thread that will perform GL
- * rendering to an ANativeWindow that feeds frames to a SurfaceTexture.
- * Additionally it supports interlocking the producer and consumer threads so
- * that a specific sequence of calls can be deterministically created by the
- * test.
+ * This test fixture is for testing GL -> GL texture streaming. It creates an
+ * EGLSurface and an EGLContext for the image producer to use.
+ */
+class SurfaceTextureGLToGLTest : public SurfaceTextureGLTest {
+protected:
+ SurfaceTextureGLToGLTest():
+ mProducerEglSurface(EGL_NO_SURFACE),
+ mProducerEglContext(EGL_NO_CONTEXT) {
+ }
+
+ virtual void SetUp() {
+ SurfaceTextureGLTest::SetUp();
+
+ EGLConfig myConfig = {0};
+ EGLint numConfigs = 0;
+ EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &myConfig,
+ 1, &numConfigs));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ mProducerEglSurface = eglCreateWindowSurface(mEglDisplay, myConfig,
+ mANW.get(), NULL);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, mProducerEglSurface);
+
+ mProducerEglContext = eglCreateContext(mEglDisplay, myConfig,
+ EGL_NO_CONTEXT, getContextAttribs());
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_CONTEXT, mProducerEglContext);
+ }
+
+ virtual void TearDown() {
+ if (mProducerEglContext != EGL_NO_CONTEXT) {
+ eglDestroyContext(mEglDisplay, mProducerEglContext);
+ }
+ if (mProducerEglSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(mEglDisplay, mProducerEglSurface);
+ }
+ SurfaceTextureGLTest::TearDown();
+ }
+
+ EGLSurface mProducerEglSurface;
+ EGLContext mProducerEglContext;
+};
+
+TEST_F(SurfaceTextureGLToGLTest, TexturingFromGLFilledRGBABufferPow2) {
+ const int texWidth = 64;
+ const int texHeight = 64;
+
+ mST->setDefaultBufferSize(texWidth, texHeight);
+
+ // Do the producer side of things
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+ mProducerEglSurface, mProducerEglContext));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ // This is needed to ensure we pick up a buffer of the correct size.
+ eglSwapBuffers(mEglDisplay, mProducerEglSurface);
+
+ glClearColor(0.6, 0.6, 0.6, 0.6);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(4, 4, 4, 4);
+ glClearColor(1.0, 0.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glScissor(24, 48, 4, 4);
+ glClearColor(0.0, 1.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glScissor(37, 17, 4, 4);
+ glClearColor(0.0, 0.0, 1.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ eglSwapBuffers(mEglDisplay, mProducerEglSurface);
+
+ // Do the consumer side of things
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+ mEglContext));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ glDisable(GL_SCISSOR_TEST);
+
+ mST->updateTexImage(); // Skip the first frame, which was empty
+ mST->updateTexImage();
+
+ glClearColor(0.2, 0.2, 0.2, 0.2);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glViewport(0, 0, texWidth, texHeight);
+ drawTexture();
+
+ EXPECT_TRUE(checkPixel( 0, 0, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(63, 0, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(63, 63, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel( 0, 63, 153, 153, 153, 153));
+
+ EXPECT_TRUE(checkPixel( 4, 7, 255, 0, 0, 255));
+ EXPECT_TRUE(checkPixel(25, 51, 0, 255, 0, 255));
+ EXPECT_TRUE(checkPixel(40, 19, 0, 0, 255, 255));
+ EXPECT_TRUE(checkPixel(29, 51, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel( 5, 32, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(13, 8, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(46, 3, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(30, 33, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel( 6, 52, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(55, 33, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(16, 29, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel( 1, 30, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(41, 37, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(46, 29, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(15, 25, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153));
+}
+
+TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceUnrefsBuffers) {
+ sp<GraphicBuffer> buffers[3];
+
+ // This test requires async mode to run on a single thread.
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+ mProducerEglSurface, mProducerEglContext));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ EXPECT_TRUE(eglSwapInterval(mEglDisplay, 0));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ for (int i = 0; i < 3; i++) {
+ // Produce a frame
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+ mProducerEglSurface, mProducerEglContext));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ glClear(GL_COLOR_BUFFER_BIT);
+ eglSwapBuffers(mEglDisplay, mProducerEglSurface);
+
+ // Consume a frame
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+ mEglContext));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ mST->updateTexImage();
+ buffers[i] = mST->getCurrentBuffer();
+ }
+
+ // Destroy the GL texture object to release its ref on buffers[2].
+ GLuint texID = TEX_ID;
+ glDeleteTextures(1, &texID);
+
+ // Destroy the EGLSurface
+ EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ // Release the ref that the SurfaceTexture has on buffers[2].
+ mST->abandon();
+
+ EXPECT_EQ(1, buffers[0]->getStrongCount());
+ EXPECT_EQ(1, buffers[1]->getStrongCount());
+
+ // Depending on how lazily the GL driver dequeues buffers, we may end up
+ // with either two or three total buffers. If there are three, make sure
+ // the last one was properly down-ref'd.
+ if (buffers[2] != buffers[0]) {
+ EXPECT_EQ(1, buffers[2]->getStrongCount());
+ }
+}
+
+TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceAfterAbandonUnrefsBuffers) {
+ sp<GraphicBuffer> buffers[3];
+
+ // This test requires async mode to run on a single thread.
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+ mProducerEglSurface, mProducerEglContext));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ EXPECT_TRUE(eglSwapInterval(mEglDisplay, 0));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ for (int i = 0; i < 3; i++) {
+ // Produce a frame
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+ mProducerEglSurface, mProducerEglContext));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ glClear(GL_COLOR_BUFFER_BIT);
+ EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ // Consume a frame
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+ mEglContext));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_EQ(NO_ERROR, mST->updateTexImage());
+ buffers[i] = mST->getCurrentBuffer();
+ }
+
+ // Abandon the SurfaceTexture, releasing the ref that the SurfaceTexture has
+ // on buffers[2].
+ mST->abandon();
+
+ // Destroy the GL texture object to release its ref on buffers[2].
+ GLuint texID = TEX_ID;
+ glDeleteTextures(1, &texID);
+
+ // Destroy the EGLSurface.
+ EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ EXPECT_EQ(1, buffers[0]->getStrongCount());
+ EXPECT_EQ(1, buffers[1]->getStrongCount());
+
+ // Depending on how lazily the GL driver dequeues buffers, we may end up
+ // with either two or three total buffers. If there are three, make sure
+ // the last one was properly down-ref'd.
+ if (buffers[2] != buffers[0]) {
+ EXPECT_EQ(1, buffers[2]->getStrongCount());
+ }
+}
+
+TEST_F(SurfaceTextureGLToGLTest, EglSurfaceDefaultsToSynchronousMode) {
+ // This test requires 3 buffers to run on a single thread.
+ mST->setBufferCountServer(3);
+
+ ASSERT_TRUE(mST->isSynchronousMode());
+
+ for (int i = 0; i < 10; i++) {
+ // Produce a frame
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+ mProducerEglSurface, mProducerEglContext));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ glClear(GL_COLOR_BUFFER_BIT);
+ EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ // Consume a frame
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+ mEglContext));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_EQ(NO_ERROR, mST->updateTexImage());
+ }
+
+ ASSERT_TRUE(mST->isSynchronousMode());
+}
+
+/*
+ * This test fixture is for testing GL -> GL texture streaming from one thread
+ * to another. It contains functionality to create a producer thread that will
+ * perform GL rendering to an ANativeWindow that feeds frames to a
+ * SurfaceTexture. Additionally it supports interlocking the producer and
+ * consumer threads so that a specific sequence of calls can be
+ * deterministically created by the test.
*
* The intended usage is as follows:
*
@@ -1122,7 +1325,7 @@
* }
*
*/
-class SurfaceTextureGLToGLTest : public SurfaceTextureGLTest {
+class SurfaceTextureGLThreadToGLTest : public SurfaceTextureGLToGLTest {
protected:
// ProducerThread is an abstract base class to simplify the creation of
@@ -1223,30 +1426,8 @@
Condition mFrameFinishCondition;
};
- SurfaceTextureGLToGLTest():
- mProducerEglSurface(EGL_NO_SURFACE),
- mProducerEglContext(EGL_NO_CONTEXT) {
- }
-
virtual void SetUp() {
- SurfaceTextureGLTest::SetUp();
-
- EGLConfig myConfig = {0};
- EGLint numConfigs = 0;
- EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &myConfig,
- 1, &numConfigs));
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
- mProducerEglSurface = eglCreateWindowSurface(mEglDisplay, myConfig,
- mANW.get(), NULL);
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
- ASSERT_NE(EGL_NO_SURFACE, mProducerEglSurface);
-
- mProducerEglContext = eglCreateContext(mEglDisplay, myConfig,
- EGL_NO_CONTEXT, getContextAttribs());
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
- ASSERT_NE(EGL_NO_CONTEXT, mProducerEglContext);
-
+ SurfaceTextureGLToGLTest::SetUp();
mFC = new FrameCondition();
mST->setFrameAvailableListener(mFC);
}
@@ -1255,15 +1436,9 @@
if (mProducerThread != NULL) {
mProducerThread->requestExitAndWait();
}
- if (mProducerEglContext != EGL_NO_CONTEXT) {
- eglDestroyContext(mEglDisplay, mProducerEglContext);
- }
- if (mProducerEglSurface != EGL_NO_SURFACE) {
- eglDestroySurface(mEglDisplay, mProducerEglSurface);
- }
mProducerThread.clear();
mFC.clear();
- SurfaceTextureGLTest::TearDown();
+ SurfaceTextureGLToGLTest::TearDown();
}
void runProducerThread(const sp<ProducerThread> producerThread) {
@@ -1274,13 +1449,12 @@
producerThread->run();
}
- EGLSurface mProducerEglSurface;
- EGLContext mProducerEglContext;
sp<ProducerThread> mProducerThread;
sp<FrameCondition> mFC;
};
-TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedCompletes) {
+TEST_F(SurfaceTextureGLThreadToGLTest,
+ UpdateTexImageBeforeFrameFinishedCompletes) {
class PT : public ProducerThread {
virtual void render() {
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
@@ -1298,7 +1472,8 @@
// TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
}
-TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedCompletes) {
+TEST_F(SurfaceTextureGLThreadToGLTest,
+ UpdateTexImageAfterFrameFinishedCompletes) {
class PT : public ProducerThread {
virtual void render() {
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
@@ -1316,7 +1491,8 @@
// TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
}
-TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedCompletes) {
+TEST_F(SurfaceTextureGLThreadToGLTest,
+ RepeatedUpdateTexImageBeforeFrameFinishedCompletes) {
enum { NUM_ITERATIONS = 1024 };
class PT : public ProducerThread {
@@ -1344,7 +1520,8 @@
}
}
-TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedCompletes) {
+TEST_F(SurfaceTextureGLThreadToGLTest,
+ RepeatedUpdateTexImageAfterFrameFinishedCompletes) {
enum { NUM_ITERATIONS = 1024 };
class PT : public ProducerThread {
@@ -1373,7 +1550,8 @@
}
// XXX: This test is disabled because it is currently hanging on some devices.
-TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedSwapBuffersWhileDequeueStalledCompletes) {
+TEST_F(SurfaceTextureGLThreadToGLTest,
+ DISABLED_RepeatedSwapBuffersWhileDequeueStalledCompletes) {
enum { NUM_ITERATIONS = 64 };
class PT : public ProducerThread {
@@ -1438,118 +1616,4 @@
}
}
-TEST_F(SurfaceTextureGLTest, EglDestroySurfaceUnrefsBuffers) {
- EGLSurface stcEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
- mANW.get(), NULL);
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
- ASSERT_NE(EGL_NO_SURFACE, stcEglSurface);
-
- sp<GraphicBuffer> buffers[3];
-
- for (int i = 0; i < 3; i++) {
- // Produce a frame
- EXPECT_TRUE(eglMakeCurrent(mEglDisplay, stcEglSurface, stcEglSurface,
- mEglContext));
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
- glClear(GL_COLOR_BUFFER_BIT);
- eglSwapBuffers(mEglDisplay, stcEglSurface);
-
- // Consume a frame
- EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
- mEglContext));
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
- mST->updateTexImage();
- buffers[i] = mST->getCurrentBuffer();
- }
-
- // Destroy the GL texture object to release its ref on buffers[2].
- GLuint texID = TEX_ID;
- glDeleteTextures(1, &texID);
-
- // Destroy the EGLSurface
- EXPECT_TRUE(eglDestroySurface(mEglDisplay, stcEglSurface));
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
- // Release the ref that the SurfaceTexture has on buffers[2].
- mST->abandon();
-
- EXPECT_EQ(1, buffers[0]->getStrongCount());
- EXPECT_EQ(1, buffers[1]->getStrongCount());
- EXPECT_EQ(1, buffers[2]->getStrongCount());
-}
-
-TEST_F(SurfaceTextureGLTest, EglDestroySurfaceAfterAbandonUnrefsBuffers) {
- EGLSurface stcEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
- mANW.get(), NULL);
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
- ASSERT_NE(EGL_NO_SURFACE, stcEglSurface);
-
- sp<GraphicBuffer> buffers[3];
-
- for (int i = 0; i < 3; i++) {
- // Produce a frame
- EXPECT_TRUE(eglMakeCurrent(mEglDisplay, stcEglSurface, stcEglSurface,
- mEglContext));
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
- glClear(GL_COLOR_BUFFER_BIT);
- EXPECT_TRUE(eglSwapBuffers(mEglDisplay, stcEglSurface));
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
- // Consume a frame
- EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
- mEglContext));
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
- ASSERT_EQ(NO_ERROR, mST->updateTexImage());
- buffers[i] = mST->getCurrentBuffer();
- }
-
- // Abandon the SurfaceTexture, releasing the ref that the SurfaceTexture has
- // on buffers[2].
- mST->abandon();
-
- // Destroy the GL texture object to release its ref on buffers[2].
- GLuint texID = TEX_ID;
- glDeleteTextures(1, &texID);
-
- // Destroy the EGLSurface.
- EXPECT_TRUE(eglDestroySurface(mEglDisplay, stcEglSurface));
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
- EXPECT_EQ(1, buffers[0]->getStrongCount());
- EXPECT_EQ(1, buffers[1]->getStrongCount());
- EXPECT_EQ(1, buffers[2]->getStrongCount());
-}
-
-TEST_F(SurfaceTextureGLTest, InvalidWidthOrHeightFails) {
- int texHeight = 16;
- ANativeWindowBuffer* anb;
-
- GLint maxTextureSize;
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
-
- // make sure it works with small textures
- mST->setDefaultBufferSize(16, texHeight);
- EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
- EXPECT_EQ(16, anb->width);
- EXPECT_EQ(texHeight, anb->height);
- EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
- EXPECT_EQ(NO_ERROR, mST->updateTexImage());
-
- // make sure it works with GL_MAX_TEXTURE_SIZE
- mST->setDefaultBufferSize(maxTextureSize, texHeight);
- EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
- EXPECT_EQ(maxTextureSize, anb->width);
- EXPECT_EQ(texHeight, anb->height);
- EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
- EXPECT_EQ(NO_ERROR, mST->updateTexImage());
-
- // make sure it fails with GL_MAX_TEXTURE_SIZE+1
- mST->setDefaultBufferSize(maxTextureSize+1, texHeight);
- EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
- EXPECT_EQ(maxTextureSize+1, anb->width);
- EXPECT_EQ(texHeight, anb->height);
- EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
- ASSERT_NE(NO_ERROR, mST->updateTexImage());
-}
-
} // namespace android
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 32595e4..7561a47 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -208,7 +208,7 @@
glDisable(GL_DITHER);
- glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo());
+ glBindFramebuffer(GL_FRAMEBUFFER, mSnapshot->fbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
mCaches.blend = true;
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index d51154d..aff7b93 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -213,7 +213,8 @@
Layer* layer;
/**
- * Only set when the flag kFlagIsFboLayer is set.
+ * Target FBO used for rendering. Set to 0 when rendering directly
+ * into the framebuffer.
*/
GLuint fbo;
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
old mode 100644
new mode 100755
index 4e271c7..98617d2
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -38,6 +38,7 @@
import java.io.File;
import java.util.HashMap;
+import java.util.Locale;
/**
* {@hide}
@@ -120,6 +121,20 @@
mMediaStoragePath = storagePath;
mObjectsUri = Files.getMtpObjectsUri(volumeName);
mMediaScanner = new MediaScanner(context);
+
+ // Set locale to MediaScanner.
+ Locale locale = context.getResources().getConfiguration().locale;
+ if (locale != null) {
+ String language = locale.getLanguage();
+ String country = locale.getCountry();
+ if (language != null) {
+ if (country != null) {
+ mMediaScanner.setLocale(language + "_" + country);
+ } else {
+ mMediaScanner.setLocale(language);
+ }
+ }
+ }
initDeviceProperties(context);
}
diff --git a/media/libmedia/MediaScannerClient.cpp b/media/libmedia/MediaScannerClient.cpp
index 7a7aeb6..629b165 100644
--- a/media/libmedia/MediaScannerClient.cpp
+++ b/media/libmedia/MediaScannerClient.cpp
@@ -82,7 +82,7 @@
// save the strings for later so they can be used for native encoding detection
mNames->push_back(name);
mValues->push_back(value);
- return true;
+ return OK;
}
// else fall through
}
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 7d9d7ed..f6d054d 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -224,17 +224,18 @@
mClient.disconnect();
}
-void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
+void AwesomePlayer::cancelPlayerEvents(bool keepNotifications) {
mQueue.cancelEvent(mVideoEvent->eventID());
mVideoEventPending = false;
- mQueue.cancelEvent(mStreamDoneEvent->eventID());
- mStreamDoneEventPending = false;
- mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
- mAudioStatusEventPending = false;
mQueue.cancelEvent(mVideoLagEvent->eventID());
mVideoLagEventPending = false;
- if (!keepBufferingGoing) {
+ if (!keepNotifications) {
+ mQueue.cancelEvent(mStreamDoneEvent->eventID());
+ mStreamDoneEventPending = false;
+ mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
+ mAudioStatusEventPending = false;
+
mQueue.cancelEvent(mBufferingEvent->eventID());
mBufferingEventPending = false;
}
@@ -1095,7 +1096,7 @@
return OK;
}
- cancelPlayerEvents(true /* keepBufferingGoing */);
+ cancelPlayerEvents(true /* keepNotifications */);
if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
if (at_eos) {
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 256f3ba..57989c5 100755
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -33,6 +33,8 @@
namespace android {
+static const int64_t CAMERA_SOURCE_TIMEOUT_NS = 3000000000LL;
+
struct CameraSourceListener : public CameraListener {
CameraSourceListener(const sp<CameraSource> &source);
@@ -156,6 +158,7 @@
mLastFrameTimestampUs(0),
mStarted(false),
mNumFramesEncoded(0),
+ mTimeBetweenFrameCaptureUs(0),
mFirstFrameTimeUs(0),
mNumFramesDropped(0),
mNumGlitches(0),
@@ -644,7 +647,8 @@
releaseQueuedFrames();
while (!mFramesBeingEncoded.empty()) {
if (NO_ERROR !=
- mFrameCompleteCondition.waitRelative(mLock, 3000000000LL)) {
+ mFrameCompleteCondition.waitRelative(mLock,
+ mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
LOGW("Timed out waiting for outstanding frames being encoded: %d",
mFramesBeingEncoded.size());
}
@@ -736,7 +740,8 @@
Mutex::Autolock autoLock(mLock);
while (mStarted && mFramesReceived.empty()) {
if (NO_ERROR !=
- mFrameAvailableCondition.waitRelative(mLock, 1000000000LL)) {
+ mFrameAvailableCondition.waitRelative(mLock,
+ mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
if (mCameraRecordingProxy != 0 &&
!mCameraRecordingProxy->asBinder()->isBinderAlive()) {
LOGW("camera recording proxy is gone");
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index e4de20a..eb456f4 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -39,12 +39,12 @@
Size videoSize,
int32_t videoFrameRate,
const sp<Surface>& surface,
- int64_t timeBetweenTimeLapseFrameCaptureUs) {
+ int64_t timeBetweenFrameCaptureUs) {
CameraSourceTimeLapse *source = new
CameraSourceTimeLapse(camera, proxy, cameraId,
videoSize, videoFrameRate, surface,
- timeBetweenTimeLapseFrameCaptureUs);
+ timeBetweenFrameCaptureUs);
if (source != NULL) {
if (source->initCheck() != OK) {
@@ -62,15 +62,15 @@
Size videoSize,
int32_t videoFrameRate,
const sp<Surface>& surface,
- int64_t timeBetweenTimeLapseFrameCaptureUs)
+ int64_t timeBetweenFrameCaptureUs)
: CameraSource(camera, proxy, cameraId, videoSize, videoFrameRate, surface, true),
- mTimeBetweenTimeLapseFrameCaptureUs(timeBetweenTimeLapseFrameCaptureUs),
mTimeBetweenTimeLapseVideoFramesUs(1E6/videoFrameRate),
mLastTimeLapseFrameRealTimestampUs(0),
mSkipCurrentFrame(false) {
+ mTimeBetweenFrameCaptureUs = timeBetweenFrameCaptureUs;
LOGD("starting time lapse mode: %lld us",
- mTimeBetweenTimeLapseFrameCaptureUs);
+ mTimeBetweenFrameCaptureUs);
mVideoWidth = videoSize.width;
mVideoHeight = videoSize.height;
@@ -271,14 +271,14 @@
// The first 2 output frames from the encoder are: decoder specific info and
// the compressed video frame data for the first input video frame.
if (mNumFramesEncoded >= 1 && *timestampUs <
- (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenTimeLapseFrameCaptureUs)) {
+ (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenFrameCaptureUs)) {
// Skip all frames from last encoded frame until
- // sufficient time (mTimeBetweenTimeLapseFrameCaptureUs) has passed.
+ // sufficient time (mTimeBetweenFrameCaptureUs) has passed.
// Tell the camera to release its recording frame and return.
LOGV("dataCallbackTimestamp timelapse: skipping intermediate frame");
return true;
} else {
- // Desired frame has arrived after mTimeBetweenTimeLapseFrameCaptureUs time:
+ // Desired frame has arrived after mTimeBetweenFrameCaptureUs time:
// - Reset mLastTimeLapseFrameRealTimestampUs to current time.
// - Artificially modify timestampUs to be one frame time (1/framerate) ahead
// of the last encoded frame's time stamp.
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index dfd3f4a..86b3fe4 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -520,6 +520,85 @@
return NULL;
}
+status_t OMXCodec::parseAVCCodecSpecificData(
+ const void *data, size_t size,
+ unsigned *profile, unsigned *level) {
+ const uint8_t *ptr = (const uint8_t *)data;
+
+ // verify minimum size and configurationVersion == 1.
+ if (size < 7 || ptr[0] != 1) {
+ return ERROR_MALFORMED;
+ }
+
+ *profile = ptr[1];
+ *level = ptr[3];
+
+ // There is decodable content out there that fails the following
+ // assertion, let's be lenient for now...
+ // CHECK((ptr[4] >> 2) == 0x3f); // reserved
+
+ size_t lengthSize = 1 + (ptr[4] & 3);
+
+ // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
+ // violates it...
+ // CHECK((ptr[5] >> 5) == 7); // reserved
+
+ size_t numSeqParameterSets = ptr[5] & 31;
+
+ ptr += 6;
+ size -= 6;
+
+ for (size_t i = 0; i < numSeqParameterSets; ++i) {
+ if (size < 2) {
+ return ERROR_MALFORMED;
+ }
+
+ size_t length = U16_AT(ptr);
+
+ ptr += 2;
+ size -= 2;
+
+ if (size < length) {
+ return ERROR_MALFORMED;
+ }
+
+ addCodecSpecificData(ptr, length);
+
+ ptr += length;
+ size -= length;
+ }
+
+ if (size < 1) {
+ return ERROR_MALFORMED;
+ }
+
+ size_t numPictureParameterSets = *ptr;
+ ++ptr;
+ --size;
+
+ for (size_t i = 0; i < numPictureParameterSets; ++i) {
+ if (size < 2) {
+ return ERROR_MALFORMED;
+ }
+
+ size_t length = U16_AT(ptr);
+
+ ptr += 2;
+ size -= 2;
+
+ if (size < length) {
+ return ERROR_MALFORMED;
+ }
+
+ addCodecSpecificData(ptr, length);
+
+ ptr += length;
+ size -= length;
+ }
+
+ return OK;
+}
+
status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
LOGV("configureCodec protected=%d",
(mFlags & kEnableGrallocUsageProtected) ? 1 : 0);
@@ -542,66 +621,17 @@
} else if (meta->findData(kKeyAVCC, &type, &data, &size)) {
// Parse the AVCDecoderConfigurationRecord
- const uint8_t *ptr = (const uint8_t *)data;
-
- CHECK(size >= 7);
- CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1
- uint8_t profile = ptr[1];
- uint8_t level = ptr[3];
-
- // There is decodable content out there that fails the following
- // assertion, let's be lenient for now...
- // CHECK((ptr[4] >> 2) == 0x3f); // reserved
-
- size_t lengthSize = 1 + (ptr[4] & 3);
-
- // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
- // violates it...
- // CHECK((ptr[5] >> 5) == 7); // reserved
-
- size_t numSeqParameterSets = ptr[5] & 31;
-
- ptr += 6;
- size -= 6;
-
- for (size_t i = 0; i < numSeqParameterSets; ++i) {
- CHECK(size >= 2);
- size_t length = U16_AT(ptr);
-
- ptr += 2;
- size -= 2;
-
- CHECK(size >= length);
-
- addCodecSpecificData(ptr, length);
-
- ptr += length;
- size -= length;
- }
-
- CHECK(size >= 1);
- size_t numPictureParameterSets = *ptr;
- ++ptr;
- --size;
-
- for (size_t i = 0; i < numPictureParameterSets; ++i) {
- CHECK(size >= 2);
- size_t length = U16_AT(ptr);
-
- ptr += 2;
- size -= 2;
-
- CHECK(size >= length);
-
- addCodecSpecificData(ptr, length);
-
- ptr += length;
- size -= length;
+ unsigned profile, level;
+ status_t err;
+ if ((err = parseAVCCodecSpecificData(
+ data, size, &profile, &level)) != OK) {
+ LOGE("Malformed AVC codec specific data.");
+ return err;
}
CODEC_LOGI(
- "AVC profile = %d (%s), level = %d",
- (int)profile, AVCProfileToString(profile), level);
+ "AVC profile = %u (%s), level = %u",
+ profile, AVCProfileToString(profile), level);
if (!strcmp(mComponentName, "OMX.TI.Video.Decoder")
&& (profile != kAVCProfileBaseline || level > 30)) {
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index bb6e4cd..2505096 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -94,7 +94,7 @@
char buffer[20];
sprintf(buffer, "%ld", temp);
status_t status = client->addStringTag("duration", buffer);
- if (status) {
+ if (status != OK) {
return MEDIA_SCAN_RESULT_ERROR;
}
return MEDIA_SCAN_RESULT_OK;
@@ -178,7 +178,7 @@
const char *value;
if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) {
status = client.addStringTag(kKeyMap[i].tag, value);
- if (status) {
+ if (status != OK) {
return MEDIA_SCAN_RESULT_ERROR;
}
}
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index c13d6cb..0985f47 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -250,7 +250,7 @@
void notifyVideoSize_l();
void seekAudioIfNecessary_l();
- void cancelPlayerEvents(bool keepBufferingGoing = false);
+ void cancelPlayerEvents(bool keepNotifications = false);
void setAudioSource(sp<MediaSource> source);
status_t initAudioDecoder();
diff --git a/opengl/java/android/opengl/GLES11Ext.java b/opengl/java/android/opengl/GLES11Ext.java
index 25d5467..484439a 100644
--- a/opengl/java/android/opengl/GLES11Ext.java
+++ b/opengl/java/android/opengl/GLES11Ext.java
@@ -125,6 +125,10 @@
public static final int GL_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE;
public static final int GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
public static final int GL_BGRA = 0x80E1;
+ public static final int GL_TEXTURE_EXTERNAL_OES = 0x8D65;
+ public static final int GL_SAMPLER_EXTERNAL_OES = 0x8D66;
+ public static final int GL_TEXTURE_BINDING_EXTERNAL_OES = 0x8D67;
+ public static final int GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES = 0x8D68;
native private static void _nativeClassInit();
static {
diff --git a/opengl/java/android/opengl/ManagedEGLContext.java b/opengl/java/android/opengl/ManagedEGLContext.java
new file mode 100644
index 0000000..61fa565
--- /dev/null
+++ b/opengl/java/android/opengl/ManagedEGLContext.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2010 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.opengl;
+
+import static javax.microedition.khronos.egl.EGL10.EGL_DEFAULT_DISPLAY;
+import static javax.microedition.khronos.egl.EGL10.EGL_NO_DISPLAY;
+
+import java.util.ArrayList;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+
+import android.os.Looper;
+import android.util.Log;
+
+import com.google.android.gles_jni.EGLImpl;
+
+/**
+ * The per-process memory overhead of hardware accelerated graphics can
+ * be quite large on some devices. For small memory devices, being able to
+ * terminate all EGL contexts so that this graphics driver memory can be
+ * reclaimed can significant improve the overall behavior of the device. This
+ * class helps app developers participate in releasing their EGL context
+ * when appropriate and possible.
+ *
+ * <p>To use, simple instantiate this class with the EGLContext you create.
+ * When you have done this, if the device is getting low on memory and all
+ * of the currently created EGL contexts in the process are being managed
+ * through this class, then they will all be asked to terminate through the
+ * call to {@link #onTerminate}.
+ *
+ * @hide
+ */
+public abstract class ManagedEGLContext {
+ static final String TAG = "ManagedEGLContext";
+
+ static final ArrayList<ManagedEGLContext> sActive = new ArrayList<ManagedEGLContext>();
+
+ final EGLContext mContext;
+
+ /**
+ * Instantiate to manage the given EGLContext.
+ */
+ public ManagedEGLContext(EGLContext context) {
+ mContext = context;
+ synchronized (sActive) {
+ sActive.add(this);
+ }
+ }
+
+ /**
+ * Retrieve the EGLContext being managed by the class.
+ */
+ public EGLContext getContext() {
+ return mContext;
+ }
+
+ /**
+ * Force-terminate the ManagedEGLContext. This will cause
+ * {@link #onTerminate(EGLContext)} to be called. You <em>must</em>
+ * call this when destroying the EGLContext, so that the framework
+ * knows to stop managing it.
+ */
+ public void terminate() {
+ execTerminate();
+ }
+
+ void execTerminate() {
+ onTerminate(mContext);
+ }
+
+ /**
+ * Override this method to destroy the EGLContext when appropriate.
+ * <em>Note that this method is always called on the main thread
+ * of the process.</em> If your EGLContext was created on a different
+ * thread, you will need to implement this method to hand off the work
+ * of destroying the context to that thread.
+ */
+ public abstract void onTerminate(EGLContext context);
+
+ /** @hide */
+ public static boolean doTerminate() {
+ ArrayList<ManagedEGLContext> active;
+
+ if (Looper.getMainLooper() != Looper.myLooper()) {
+ throw new IllegalStateException("Called on wrong thread");
+ }
+
+ synchronized (sActive) {
+ // If there are no active managed contexts, we will not even
+ // try to terminate.
+ if (sActive.size() <= 0) {
+ return false;
+ }
+
+ // Need to check how many EGL contexts are actually running,
+ // to compare with how many we are managing.
+ EGL10 egl = (EGL10) EGLContext.getEGL();
+ EGLDisplay display = egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+
+ if (display == EGL_NO_DISPLAY) {
+ Log.w(TAG, "doTerminate failed: no display");
+ return false;
+ }
+
+ if (EGLImpl.getInitCount(display) != sActive.size()) {
+ Log.w(TAG, "doTerminate failed: EGL count is " + EGLImpl.getInitCount(display)
+ + " but managed count is " + sActive.size());
+ return false;
+ }
+
+ active = new ArrayList<ManagedEGLContext>(sActive);
+ sActive.clear();
+ }
+
+ for (int i = 0; i < active.size(); i++) {
+ active.get(i).execTerminate();
+ }
+
+ return true;
+ }
+}
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index 5855b63..9c1a10e 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -44,10 +44,17 @@
LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
endif
+ifneq ($(MAX_EGL_CACHE_ENTRY_SIZE),)
+ LOCAL_CFLAGS += -DMAX_EGL_CACHE_ENTRY_SIZE=$(MAX_EGL_CACHE_ENTRY_SIZE)
+endif
+
+ifneq ($(MAX_EGL_CACHE_SIZE),)
+ LOCAL_CFLAGS += -DMAX_EGL_CACHE_SIZE=$(MAX_EGL_CACHE_SIZE)
+endif
+
include $(BUILD_SHARED_LIBRARY)
installed_libEGL := $(LOCAL_INSTALLED_MODULE)
-
# OpenGL drivers config file
ifneq ($(BOARD_EGL_CFG),)
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 2237eb6..a63d5b0 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -370,6 +370,11 @@
}
}
+ // the EGL spec requires that a new EGLSurface default to swap interval
+ // 1, so explicitly set that on the window here.
+ ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
+ anw->setSwapInterval(anw, 1);
+
EGLSurface surface = cnx->egl.eglCreateWindowSurface(
iDpy, iConfig, window, attrib_list);
if (surface != EGL_NO_SURFACE) {
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index 13a4929..c4a7466 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -25,10 +25,18 @@
#include <sys/types.h>
#include <unistd.h>
+#ifndef MAX_EGL_CACHE_ENTRY_SIZE
+#define MAX_EGL_CACHE_ENTRY_SIZE (16 * 1024);
+#endif
+
+#ifndef MAX_EGL_CACHE_SIZE
+#define MAX_EGL_CACHE_SIZE (64 * 1024);
+#endif
+
// Cache size limits.
static const size_t maxKeySize = 1024;
-static const size_t maxValueSize = 4096;
-static const size_t maxTotalSize = 64 * 1024;
+static const size_t maxValueSize = MAX_EGL_CACHE_ENTRY_SIZE;
+static const size_t maxTotalSize = MAX_EGL_CACHE_SIZE;
// Cache file header
static const char* cacheFileMagic = "EGL$";
@@ -85,7 +93,7 @@
bool atStart = !strncmp(BC_EXT_STR " ", exts, bcExtLen+1);
bool atEnd = (bcExtLen+1) < extsLen &&
!strcmp(" " BC_EXT_STR, exts + extsLen - (bcExtLen+1));
- bool inMiddle = strstr(" " BC_EXT_STR " ", exts);
+ bool inMiddle = strstr(exts, " " BC_EXT_STR " ");
if (equal || atStart || atEnd || inMiddle) {
PFNEGLSETBLOBCACHEFUNCSANDROIDPROC eglSetBlobCacheFuncsANDROID;
eglSetBlobCacheFuncsANDROID =
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 862b48d2..31119f9 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -220,15 +220,19 @@
if (end) {
// length of the extension string
const size_t len = end - start;
- // NOTE: we could avoid the copy if we had strnstr.
- const String8 ext(start, len);
- // now go through all implementations and look for this extension
- for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
- // if we find it, add this extension string to our list
- // (and don't forget the space)
- const char* match = strstr(disp[i].queryString.extensions, ext.string());
- if (match && (match[len] == ' ' || match[len] == 0)) {
- mExtensionString.append(start, len+1);
+ if (len) {
+ // NOTE: we could avoid the copy if we had strnstr.
+ const String8 ext(start, len);
+ // now go through all implementations and look for this extension
+ for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
+ if (disp[i].queryString.extensions) {
+ // if we find it, add this extension string to our list
+ // (and don't forget the space)
+ const char* match = strstr(disp[i].queryString.extensions, ext.string());
+ if (match && (match[len] == ' ' || match[len] == 0)) {
+ mExtensionString.append(start, len+1);
+ }
+ }
}
}
// process the next extension string, and skip the space.
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11ExtHeader.java-if b/opengl/tools/glgen/stubs/gles11/GLES11ExtHeader.java-if
index c5e34cd..0c5fa04 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES11ExtHeader.java-if
+++ b/opengl/tools/glgen/stubs/gles11/GLES11ExtHeader.java-if
@@ -124,6 +124,10 @@
public static final int GL_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE;
public static final int GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
public static final int GL_BGRA = 0x80E1;
+ public static final int GL_TEXTURE_EXTERNAL_OES = 0x8D65;
+ public static final int GL_SAMPLER_EXTERNAL_OES = 0x8D66;
+ public static final int GL_TEXTURE_BINDING_EXTERNAL_OES = 0x8D67;
+ public static final int GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES = 0x8D68;
native private static void _nativeClassInit();
static {
@@ -135,4 +139,4 @@
private static final int GL_FLOAT = GLES10.GL_FLOAT;
private static final int GL_SHORT = GLES10.GL_SHORT;
- private static Buffer _matrixIndexPointerOES;
\ No newline at end of file
+ private static Buffer _matrixIndexPointerOES;
diff --git a/packages/BackupRestoreConfirmation/res/values-af/strings.xml b/packages/BackupRestoreConfirmation/res/values-af/strings.xml
index 8ee5550..fadd125 100644
--- a/packages/BackupRestoreConfirmation/res/values-af/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-af/strings.xml
@@ -18,10 +18,10 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="backup_confirm_title" msgid="827563724209303345">"Volledige rugsteun"</string>
<string name="restore_confirm_title" msgid="5469365809567486602">"Volledige herstel"</string>
- <string name="backup_confirm_text" msgid="1878021282758896593">"\'n Volledige rugsteun van al die data na \'n tafelrekenaar is aangevra. Wil jy dit toelaat? "\n\n"As jy nie self die rugsteun versoek het nie, moenie toelaat dat die aksie voortgaan nie."</string>
+ <string name="backup_confirm_text" msgid="1878021282758896593">"\'n Volledige rugsteun van al die data na \'n rekenaar is aangevra. Wil jy dit toelaat? "\n\n"As jy nie self die rugsteun versoek het nie, moenie toelaat dat die aksie voortgaan nie."</string>
<string name="allow_backup_button_label" msgid="4217228747769644068">"Rugsteun my data"</string>
<string name="deny_backup_button_label" msgid="6009119115581097708">"Moenie rugsteun nie"</string>
- <string name="restore_confirm_text" msgid="7499866728030461776">"\'n Volle teruglaai van alle data van \'n gekoppelde tafelrekenaar is versoek. Wil jy dit toelaat? "\n\n" As jy nie die teruglaai self versoek het nie, moenie die aksie toelaat nie. Dit sal enige data tans op die toestel vervang!"</string>
+ <string name="restore_confirm_text" msgid="7499866728030461776">"\'n Volle teruglaai van alle data van \'n gekoppelde rekenaar is versoek. Wil jy dit toelaat? "\n\n" As jy nie die teruglaai self versoek het nie, moenie die aksie toelaat nie. Dit sal enige data tans op die toestel vervang!"</string>
<string name="allow_restore_button_label" msgid="3081286752277127827">"Laai my data terug"</string>
<string name="deny_restore_button_label" msgid="1724367334453104378">"Moenie herstel nie"</string>
<string name="current_password_text" msgid="8268189555578298067">"Voer asseblief jou huidige rugsteunwagwoord hieronder in:"</string>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 5495d08..aa08e64 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -723,6 +723,8 @@
upgradeVersion = 57;
}
+ /************* The following are Honeycomb changes ************/
+
if (upgradeVersion == 57) {
/*
* New settings to:
@@ -751,13 +753,13 @@
if (upgradeVersion == 58) {
/* Add default for new Auto Time Zone */
+ int autoTimeValue = getIntValueFromSystem(db, Settings.System.AUTO_TIME, 0);
db.beginTransaction();
SQLiteStatement stmt = null;
try {
- stmt = db.compileStatement("INSERT INTO secure(name,value)"
- + " VALUES(?,?);");
- loadBooleanSetting(stmt, Settings.System.AUTO_TIME_ZONE,
- R.bool.def_auto_time_zone); // Sync timezone to NITZ
+ stmt = db.compileStatement("INSERT INTO system(name,value)" + " VALUES(?,?);");
+ loadSetting(stmt, Settings.System.AUTO_TIME_ZONE,
+ autoTimeValue); // Sync timezone to NITZ if auto_time was enabled
db.setTransactionSuccessful();
} finally {
db.endTransaction();
@@ -784,18 +786,24 @@
}
if (upgradeVersion == 60) {
- upgradeScreenTimeout(db);
+ // Don't do this for upgrades from Gingerbread
+ // Were only required for intra-Honeycomb upgrades for testing
+ // upgradeScreenTimeout(db);
upgradeVersion = 61;
}
if (upgradeVersion == 61) {
- upgradeScreenTimeout(db);
+ // Don't do this for upgrades from Gingerbread
+ // Were only required for intra-Honeycomb upgrades for testing
+ // upgradeScreenTimeout(db);
upgradeVersion = 62;
}
// Change the default for screen auto-brightness mode
if (upgradeVersion == 62) {
- upgradeAutoBrightness(db);
+ // Don't do this for upgrades from Gingerbread
+ // Were only required for intra-Honeycomb upgrades for testing
+ // upgradeAutoBrightness(db);
upgradeVersion = 63;
}
@@ -839,6 +847,8 @@
upgradeVersion = 65;
}
+ /************* The following are Ice Cream Sandwich changes ************/
+
if (upgradeVersion == 65) {
/*
* Animations are removed from Settings. Turned on by default
@@ -1232,12 +1242,13 @@
stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
+ " VALUES(?,?);");
- // Vibrate off by default for ringer, on for notification
+ // Vibrate on by default for ringer, on for notification
int vibrate = 0;
vibrate = AudioService.getValueForVibrateSetting(vibrate,
- AudioManager.VIBRATE_TYPE_NOTIFICATION, AudioManager.VIBRATE_SETTING_ON);
+ AudioManager.VIBRATE_TYPE_NOTIFICATION,
+ AudioManager.VIBRATE_SETTING_ONLY_SILENT);
vibrate |= AudioService.getValueForVibrateSetting(vibrate,
- AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_OFF);
+ AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_ONLY_SILENT);
loadSetting(stmt, Settings.System.VIBRATE_ON, vibrate);
} finally {
if (stmt != null) stmt.close();
@@ -1509,4 +1520,20 @@
loadSetting(stmt, key,
Float.toString(mContext.getResources().getFraction(resid, base, base)));
}
+
+ private int getIntValueFromSystem(SQLiteDatabase db, String name, int defaultValue) {
+ int value = defaultValue;
+ Cursor c = null;
+ try {
+ c = db.query("system", new String[] { Settings.System.VALUE }, "name='" + name + "'",
+ null, null, null, null);
+ if (c != null && c.moveToFirst()) {
+ String val = c.getString(0);
+ value = val == null ? defaultValue : Integer.parseInt(val);
+ }
+ } finally {
+ if (c != null) c.close();
+ }
+ return value;
+ }
}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index eefb9fe..e937587 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -46,18 +46,29 @@
</intent-filter>
</receiver>
- <!-- handle dock insertion, launch screensaver instead -->
+ <!-- should you need to launch the screensaver, this is a good way to do it -->
<activity android:name=".DreamsDockLauncher"
+ android:theme="@android:style/Theme.Dialog"
android:label="@string/dreams_dock_launcher">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.DESK_DOCK" />
</intent-filter>
</activity>
+ <!-- launch screensaver on (desk) dock event -->
+ <receiver android:name=".DreamsDockLauncher$DockEventReceiver"
+ android:exported="true"
+ >
+ <intent-filter>
+ <action android:name="android.intent.action.DOCK_EVENT" />
+ </intent-filter>
+ </receiver>
+
+
<activity android:name=".usb.UsbStorageActivity"
- android:excludeFromRecents="true">
+ android:label="@*android:string/usb_storage_activity_title"
+ android:excludeFromRecents="true">
</activity>
<activity android:name="com.android.internal.app.ExternalMediaFormatActivity"
android:theme="@*android:style/Theme.Dialog.Alert"
@@ -124,7 +135,7 @@
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.DREAM" />
+<!-- <category android:name="android.intent.category.DREAM" />-->
</intent-filter>
</activity>
</application>
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png b/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png
index cbd72fb..c02bd42 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png b/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png
index 7651331..05cdd9a 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_launcher_settings.png b/packages/SystemUI/res/drawable-xhdpi/ic_launcher_settings.png
index b631779..2b2907b 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_launcher_settings.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 841f6e2..b518898 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -33,7 +33,7 @@
</plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ingen meddelelser"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"I gang"</string>
- <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meddelelser"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Underretninger"</string>
<string name="battery_low_title" msgid="2783104807551211639">"Tilslut oplader"</string>
<string name="battery_low_subtitle" msgid="1752040062087829196">"Batteriet er ved at være fladt."</string>
<string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> tilbage"</string>
@@ -45,7 +45,7 @@
<string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Automatisk skærmrotation"</string>
<string name="status_bar_settings_mute_label" msgid="554682549917429396">"LYDLØS"</string>
<string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
- <string name="status_bar_settings_notifications" msgid="397146176280905137">"Meddelelser"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Underretninger"</string>
<string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth-tethering anvendt"</string>
<string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfigurer inputmetoder"</string>
<string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Brug fysisk tastatur"</string>
@@ -119,7 +119,7 @@
<string name="accessibility_airplane_mode" msgid="834748999790763092">"Flytilstand."</string>
<string name="accessibility_battery_level" msgid="7451474187113371965">"Batteri <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Systemindstillinger."</string>
- <string name="accessibility_notifications_button" msgid="4498000369779421892">"Meddelelser."</string>
+ <string name="accessibility_notifications_button" msgid="4498000369779421892">"Underretninger."</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Ryd meddelelse."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS aktiveret."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS samler data."</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index ed62c10..a5bfb4a 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -106,7 +106,7 @@
<string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX-i on üks riba."</string>
<string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX-i on kaks riba."</string>
<string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX-i on kolm riba."</string>
- <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX-i signaal on täis."</string>
+ <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX-i signaal on tugev."</string>
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 54c8482..d9c9aa2 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -102,7 +102,7 @@
<string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi電波: レベル2"</string>
<string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi電波: レベル3"</string>
<string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Wi-Fi電波:フル"</string>
- <string name="accessibility_no_wimax" msgid="4329180129727630368">"WiMAX電波状態:レベル0"</string>
+ <string name="accessibility_no_wimax" msgid="4329180129727630368">"WiMAX電波状態:圏外"</string>
<string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX電波状態:レベル1"</string>
<string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX電波状態:レベル2"</string>
<string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX電波状態:レベル3"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index bc32081a..5f64f7b 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -102,7 +102,7 @@
<string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Dua bar Wi-Fi."</string>
<string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Tiga bar Wi-Fi."</string>
<string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Isyarat WiFi penuh."</string>
- <string name="accessibility_no_wimax" msgid="4329180129727630368">"No. WiMAX"</string>
+ <string name="accessibility_no_wimax" msgid="4329180129727630368">"Tiada WiMAX"</string>
<string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX satu bar."</string>
<string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX dua bar."</string>
<string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX tiga bar."</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 7320d6e..b90876a 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -138,5 +138,5 @@
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Søker etter GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Posisjon angitt av GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Fjern alle varslinger."</string>
- <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivér skjermbeskytter"</string>
+ <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktiver skjermbeskytter"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 8996b2a..cf85c75 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -106,7 +106,7 @@
<string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX: één streepje."</string>
<string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX: twee streepjes."</string>
<string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX: drie streepjes."</string>
- <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX-signaal is op volledige sterkte."</string>
+ <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX-signaal is op volle sterkte."</string>
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index d623990..6e94cc5 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -102,7 +102,7 @@
<string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi: два деления."</string>
<string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi: три деления."</string>
<string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Надежный сигнал Wi-Fi."</string>
- <string name="accessibility_no_wimax" msgid="4329180129727630368">"Сигнал WiMAX отсутствует."</string>
+ <string name="accessibility_no_wimax" msgid="4329180129727630368">"Нет сигнала WiMAX."</string>
<string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Сигнал WiMAX: одно деление."</string>
<string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Сигнал WiMAX: два деления."</string>
<string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Сигнал WiMAX: три деления."</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 70e29eb..3843ea9 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -26,7 +26,7 @@
<string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Ondoa kwenye orodha"</string>
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Taarifa za programu-matumizi"</string>
<string name="status_bar_no_recent_apps" msgid="6576392951053994640">"Hakuna programu za sasa"</string>
- <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Ondosha prog za hivi karibuni"</string>
+ <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Ondosha programu za hivi karibuni"</string>
<!-- String.format failed for translation -->
<!-- no translation found for status_bar_accessibility_recent_apps:other (1040784359794890744) -->
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Hakuna arifa"</string>
diff --git a/packages/SystemUI/res/values-sw600dp/donottranslate.xml b/packages/SystemUI/res/values-sw600dp/donottranslate.xml
new file mode 100644
index 0000000..0996067
--- /dev/null
+++ b/packages/SystemUI/res/values-sw600dp/donottranslate.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- For formatting day of week and date in DateView. %1$s is DOW, %2$s is date.
+ We show both (DOW on one line, then the date) but this can be overridden for locales as
+ necessary.
+ -->
+ <string name="status_bar_date_formatter">%1$s\n%2$s</string>
+
+</resources>
+
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 9cf90d2..34b84af 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -20,7 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7164937344850004466">"Giao diện người dùng hệ thống"</string>
- <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Xoá"</string>
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Xóa"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Không làm phiền"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Hiển thị thông báo"</string>
<string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Xóa khỏi danh sách"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 52a44a3..39b428a 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -68,7 +68,7 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Umfanekiso weskrini uqoshiwe"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Thinta ukubona imifanekiso yakho yeskrini"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Yehlulekile ukulondoloza umfanekiso weskrini."</string>
- <string name="screenshot_failed_text" msgid="8134011269572415402">"Ayikwazanga ukulondoloza isithombe-skrini. Ukugcina kwangaphandle kungenzeka kuyasetshenziswa."</string>
+ <string name="screenshot_failed_text" msgid="8134011269572415402">"Ayikwazanga ukulondoloza isithombe-skrini. Isitoreji sangaphandle kungenzeka kuyasetshenziswa."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Okukhethwa kokudluliswa kwefayela ye-USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Lengisa njengesidlali semediya (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Lengisa ikhamera (PTP)"</string>
diff --git a/packages/SystemUI/res/values/donottranslate.xml b/packages/SystemUI/res/values/donottranslate.xml
index 089a54d..4ca2116 100644
--- a/packages/SystemUI/res/values/donottranslate.xml
+++ b/packages/SystemUI/res/values/donottranslate.xml
@@ -21,6 +21,6 @@
We show both (DOW on one line, then the date) but this can be overridden for locales as
necessary.
-->
- <string name="status_bar_date_formatter">%1$s\n%2$s</string>
+ <string name="status_bar_date_formatter">%2$s</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java b/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java
index b8cdd73..1db2a7f 100644
--- a/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java
+++ b/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java
@@ -12,21 +12,38 @@
public class DreamsDockLauncher extends Activity {
private static final String TAG = "DreamsDockLauncher";
+
+ // Launch the screen saver if started as an activity.
@Override
protected void onCreate (Bundle icicle) {
super.onCreate(icicle);
+ launchDream(this);
+ finish();
+ }
+
+ private static void launchDream(Context context) {
try {
String component = Settings.Secure.getString(
- getContentResolver(), Settings.Secure.DREAM_COMPONENT);
+ context.getContentResolver(), Settings.Secure.SCREENSAVER_COMPONENT);
+ if (component == null) {
+ component = context.getResources().getString(
+ com.android.internal.R.string.config_defaultDreamComponent);
+ }
if (component != null) {
+ // dismiss the notification shade, recents, etc.
+ context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+
ComponentName cn = ComponentName.unflattenFromString(component);
Intent zzz = new Intent(Intent.ACTION_MAIN)
.setComponent(cn)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | Intent.FLAG_ACTIVITY_NO_USER_ACTION
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+ | Intent.FLAG_ACTIVITY_NO_USER_ACTION
+ | Intent.FLAG_FROM_BACKGROUND
+ | Intent.FLAG_ACTIVITY_NO_HISTORY
);
- startActivity(zzz);
+ Slog.v(TAG, "Starting screen saver on dock event: " + component);
+ context.startActivity(zzz);
} else {
Slog.e(TAG, "Couldn't start screen saver: none selected");
}
@@ -34,6 +51,28 @@
// no screensaver? give up
Slog.e(TAG, "Couldn't start screen saver: none installed");
}
- finish();
+ }
+
+ // Trap low-level dock events and launch the screensaver.
+ public static class DockEventReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final boolean activateOnDock = 0 != Settings.Secure.getInt(
+ context.getContentResolver(),
+ Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, 1);
+
+ if (!activateOnDock) return;
+
+ if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
+ Bundle extras = intent.getExtras();
+ int state = extras
+ .getInt(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED);
+ if (state == Intent.EXTRA_DOCK_STATE_DESK
+ || state == Intent.EXTRA_DOCK_STATE_LE_DESK
+ || state == Intent.EXTRA_DOCK_STATE_HE_DESK) {
+ launchDream(context);
+ }
+ }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java
index 43dfb96..e61ef8a 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java
@@ -114,16 +114,11 @@
thr.start();
mAsyncStorageHandler = new Handler(thr.getLooper());
- requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
- setProgressBarIndeterminateVisibility(true);
-
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
if (Environment.isExternalStorageRemovable()) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
}
- setTitle(getString(com.android.internal.R.string.usb_storage_activity_title));
-
setContentView(com.android.internal.R.layout.usb_storage_activity);
mIcon = (ImageView) findViewById(com.android.internal.R.id.icon);
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index 84540a15..b4b82aa 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -110,10 +110,14 @@
* the intent and provide a {@link SimCard.State} result.
*/
private static class SimArgs {
-
public final IccCard.State simState;
- private SimArgs(Intent intent) {
+ SimArgs(IccCard.State state) {
+ simState = state;
+ }
+
+ static SimArgs fromIntent(Intent intent) {
+ IccCard.State state;
if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
}
@@ -124,27 +128,28 @@
if (IccCard.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
absentReason)) {
- this.simState = IccCard.State.PERM_DISABLED;
+ state = IccCard.State.PERM_DISABLED;
} else {
- this.simState = IccCard.State.ABSENT;
+ state = IccCard.State.ABSENT;
}
} else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
- this.simState = IccCard.State.READY;
+ state = IccCard.State.READY;
} else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
final String lockedReason = intent
.getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);
if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
- this.simState = IccCard.State.PIN_REQUIRED;
+ state = IccCard.State.PIN_REQUIRED;
} else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
- this.simState = IccCard.State.PUK_REQUIRED;
+ state = IccCard.State.PUK_REQUIRED;
} else {
- this.simState = IccCard.State.UNKNOWN;
+ state = IccCard.State.UNKNOWN;
}
} else if (IccCard.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
- this.simState = IccCard.State.NETWORK_LOCKED;
+ state = IccCard.State.NETWORK_LOCKED;
} else {
- this.simState = IccCard.State.UNKNOWN;
+ state = IccCard.State.UNKNOWN;
}
+ return new SimArgs(state);
}
public String toString() {
@@ -279,8 +284,7 @@
mHandler.sendMessage(msg);
} else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
mHandler.sendMessage(mHandler.obtainMessage(
- MSG_SIM_STATE_CHANGE,
- new SimArgs(intent)));
+ MSG_SIM_STATE_CHANGE, SimArgs.fromIntent(intent)));
} else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
@@ -571,12 +575,16 @@
}
/**
- * Report that the user succesfully entered the sim pin or puk so we
+ * Report that the user successfully entered the SIM PIN or PUK/SIM PIN so we
* have the information earlier than waiting for the intent
* broadcast from the telephony code.
+ *
+ * NOTE: Because handleSimStateChange() invokes callbacks immediately without going
+ * through mHandler, this *must* be called from the UI thread.
*/
public void reportSimUnlocked() {
mSimState = IccCard.State.READY;
+ handleSimStateChange(new SimArgs(mSimState));
}
public boolean isKeyguardBypassEnabled() {
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index dd3b75d..6eff4b6 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -558,9 +558,12 @@
mScreenOn = false;
mForgotPattern = false;
mHasOverlay = mUpdateMonitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE;
- if (mMode == Mode.LockScreen) {
+
+ // Emulate activity life-cycle for both lock and unlock screen.
+ if (mLockScreen != null) {
((KeyguardScreen) mLockScreen).onPause();
- } else {
+ }
+ if (mUnlockScreen != null) {
((KeyguardScreen) mUnlockScreen).onPause();
}
@@ -651,9 +654,11 @@
@Override
public void show() {
- if (mMode == Mode.LockScreen) {
+ // Emulate activity life-cycle for both lock and unlock screen.
+ if (mLockScreen != null) {
((KeyguardScreen) mLockScreen).onResume();
- } else {
+ }
+ if (mUnlockScreen != null) {
((KeyguardScreen) mUnlockScreen).onResume();
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index b4dd07b..fd9e095 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -39,6 +39,7 @@
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.os.BatteryManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -157,6 +158,14 @@
static final boolean SHOW_STARTING_ANIMATIONS = true;
static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
+ // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
+ // No longer recommended for desk docks; still useful in car docks.
+ static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true;
+ static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
+
+ // Should screen savers use their own timeout, or the SCREEN_OFF_TIMEOUT?
+ static final boolean SEPARATE_TIMEOUT_FOR_SCREEN_SAVER = false;
+
static final int LONG_PRESS_POWER_NOTHING = 0;
static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
static final int LONG_PRESS_POWER_SHUT_OFF = 2;
@@ -391,7 +400,9 @@
// visual screen saver support
int mScreenSaverTimeout = 0;
- boolean mScreenSaverEnabled = true;
+ boolean mScreenSaverEnabledByUser = false;
+ boolean mScreenSaverMayRun = true; // false if a wakelock is held
+ boolean mPluggedIn;
// Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.)
int mEndcallBehavior;
@@ -456,7 +467,11 @@
resolver.registerContentObserver(Settings.System.getUriFor(
"fancy_rotation_anim"), false, this);
resolver.registerContentObserver(Settings.Secure.getUriFor(
- Settings.Secure.DREAM_TIMEOUT), false, this);
+ Settings.Secure.SCREENSAVER_ENABLED), false, this);
+ if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) {
+ resolver.registerContentObserver(Settings.Secure.getUriFor(
+ "screensaver_timeout"), false, this);
+ } // otherwise SCREEN_OFF_TIMEOUT will do nicely
updateSettings();
}
@@ -763,6 +778,15 @@
mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
Intent.EXTRA_DOCK_STATE_UNDOCKED);
}
+
+ // watch the plug to know whether to trigger the screen saver
+ filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ intent = context.registerReceiver(mPowerReceiver, filter);
+ if (intent != null) {
+ mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
+ }
+
mVibrator = new Vibrator();
mLongPressVibePattern = getLongIntArray(mContext.getResources(),
com.android.internal.R.array.config_longPressVibePattern);
@@ -912,8 +936,21 @@
updateRotation = true;
}
- mScreenSaverTimeout = Settings.Secure.getInt(resolver,
- Settings.Secure.DREAM_TIMEOUT, 0);
+ mScreenSaverEnabledByUser = 0 != Settings.Secure.getInt(resolver,
+ Settings.Secure.SCREENSAVER_ENABLED, 1);
+
+ if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) {
+ mScreenSaverTimeout = Settings.Secure.getInt(resolver,
+ "screensaver_timeout", 0);
+ } else {
+ mScreenSaverTimeout = Settings.System.getInt(resolver,
+ Settings.System.SCREEN_OFF_TIMEOUT, 0);
+ if (mScreenSaverTimeout > 0) {
+ // We actually want to activate the screensaver just before the
+ // power manager's screen timeout
+ mScreenSaverTimeout -= 5000;
+ }
+ }
updateScreenSaverTimeoutLocked();
}
if (updateRotation) {
@@ -2949,6 +2986,15 @@
}
};
+ BroadcastReceiver mPowerReceiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
+ mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
+ if (localLOGV) Log.v(TAG, "BATTERY_CHANGED: " + intent + " plugged=" + mPluggedIn);
+ }
+ }
+ };
+
/** {@inheritDoc} */
public void screenTurnedOff(int why) {
EventLog.writeEvent(70000, 0);
@@ -3411,22 +3457,35 @@
Runnable mScreenSaverActivator = new Runnable() {
public void run() {
- if (!(mScreenSaverEnabled && mScreenOnEarly)) {
+ if (!(mScreenSaverMayRun && mScreenOnEarly)) {
Log.w(TAG, "mScreenSaverActivator ran, but the screensaver should not be showing. Who's driving this thing?");
return;
}
+ if (!mPluggedIn) {
+ if (localLOGV) Log.v(TAG, "mScreenSaverActivator: not running screen saver when not plugged in");
+ return;
+ }
if (localLOGV) Log.v(TAG, "mScreenSaverActivator entering dreamland");
+
try {
String component = Settings.Secure.getString(
- mContext.getContentResolver(), Settings.Secure.DREAM_COMPONENT);
+ mContext.getContentResolver(), Settings.Secure.SCREENSAVER_COMPONENT);
+ if (component == null) {
+ component = mContext.getResources().getString(R.string.config_defaultDreamComponent);
+ }
if (component != null) {
+ // dismiss the notification shade, recents, etc.
+ mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+
ComponentName cn = ComponentName.unflattenFromString(component);
Intent intent = new Intent(Intent.ACTION_MAIN)
.setComponent(cn)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
| Intent.FLAG_ACTIVITY_NO_USER_ACTION
+ | Intent.FLAG_FROM_BACKGROUND
+ | Intent.FLAG_ACTIVITY_NO_HISTORY
);
mContext.startActivity(intent);
} else {
@@ -3444,13 +3503,13 @@
if (mScreenSaverActivator == null) return;
mHandler.removeCallbacks(mScreenSaverActivator);
- if (mScreenSaverEnabled && mScreenOnEarly && mScreenSaverTimeout > 0) {
+ if (mScreenSaverEnabledByUser && mScreenSaverMayRun && mScreenOnEarly && mScreenSaverTimeout > 0) {
if (localLOGV)
Log.v(TAG, "scheduling screensaver for " + mScreenSaverTimeout + "ms from now");
mHandler.postDelayed(mScreenSaverActivator, mScreenSaverTimeout);
} else {
if (localLOGV) {
- if (mScreenSaverTimeout == 0)
+ if (!mScreenSaverEnabledByUser || mScreenSaverTimeout == 0)
Log.v(TAG, "screen saver disabled by user");
else if (!mScreenOnEarly)
Log.v(TAG, "screen saver disabled while screen off");
@@ -3508,21 +3567,35 @@
}
/**
- * Return an Intent to launch the currently active dock as home. Returns
- * null if the standard home should be launched.
+ * Return an Intent to launch the currently active dock app as home. Returns
+ * null if the standard home should be launched, which is the case if any of the following is
+ * true:
+ * <ul>
+ * <li>The device is not in either car mode or desk mode
+ * <li>The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false
+ * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
+ * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
+ * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
+ * </ul>
* @return
*/
Intent createHomeDockIntent() {
- Intent intent;
+ Intent intent = null;
// What home does is based on the mode, not the dock state. That
// is, when in car mode you should be taken to car home regardless
// of whether we are actually in a car dock.
if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
- intent = mCarDockIntent;
+ if (ENABLE_CAR_DOCK_HOME_CAPTURE) {
+ intent = mCarDockIntent;
+ }
} else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
- intent = mDeskDockIntent;
- } else {
+ if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
+ intent = mDeskDockIntent;
+ }
+ }
+
+ if (intent == null) {
return null;
}
@@ -3652,7 +3725,7 @@
// The window manager has just grabbed a wake lock. This is our cue to disable the screen
// saver.
synchronized (mLock) {
- mScreenSaverEnabled = false;
+ mScreenSaverMayRun = false;
}
}
@@ -3666,7 +3739,7 @@
synchronized (mLock) {
// even if the keyguard is up, now that all the wakelocks have been released, we
// should re-enable the screen saver
- mScreenSaverEnabled = true;
+ mScreenSaverMayRun = true;
updateScreenSaverTimeoutLocked();
}
}
diff --git a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
index 47a7157..ba06996 100644
--- a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
@@ -242,20 +242,24 @@
new CheckSimPuk(mPukText.getText().toString(),
mPinText.getText().toString()) {
- void onSimLockChangedResponse(boolean success) {
- if (mSimUnlockProgressDialog != null) {
- mSimUnlockProgressDialog.hide();
- }
- if (success) {
- // before closing the keyguard, report back that
- // the sim is unlocked so it knows right away
- mUpdateMonitor.reportSimUnlocked();
- mCallback.goToUnlockScreen();
- } else {
- mHeaderText.setText(R.string.badPuk);
- mPukText.setText("");
- mPinText.setText("");
- }
+ void onSimLockChangedResponse(final boolean success) {
+ mPinText.post(new Runnable() {
+ public void run() {
+ if (mSimUnlockProgressDialog != null) {
+ mSimUnlockProgressDialog.hide();
+ }
+ if (success) {
+ // before closing the keyguard, report back that
+ // the sim is unlocked so it knows right away
+ mUpdateMonitor.reportSimUnlocked();
+ mCallback.goToUnlockScreen();
+ } else {
+ mHeaderText.setText(R.string.badPuk);
+ mPukText.setText("");
+ mPinText.setText("");
+ }
+ }
+ });
}
}.start();
}
@@ -379,6 +383,9 @@
public void onClick(View v) {
if (v == mCancelButton) {
+ // clear the PIN/PUK entry fields if the user cancels
+ mPinText.setText("");
+ mPukText.setText("");
mCallback.goToLockScreen();
return;
}
diff --git a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
index 99e1ce1..9604cdc 100644
--- a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
@@ -214,21 +214,25 @@
getSimUnlockProgressDialog().show();
new CheckSimPin(mPinText.getText().toString()) {
- void onSimLockChangedResponse(boolean success) {
- if (mSimUnlockProgressDialog != null) {
- mSimUnlockProgressDialog.hide();
- }
- if (success) {
- // before closing the keyguard, report back that
- // the sim is unlocked so it knows right away
- mUpdateMonitor.reportSimUnlocked();
- mCallback.goToUnlockScreen();
- } else {
- mHeaderText.setText(R.string.keyguard_password_wrong_pin_code);
- mPinText.setText("");
- mEnteredDigits = 0;
- }
- mCallback.pokeWakelock();
+ void onSimLockChangedResponse(final boolean success) {
+ mPinText.post(new Runnable() {
+ public void run() {
+ if (mSimUnlockProgressDialog != null) {
+ mSimUnlockProgressDialog.hide();
+ }
+ if (success) {
+ // before closing the keyguard, report back that
+ // the sim is unlocked so it knows right away
+ mUpdateMonitor.reportSimUnlocked();
+ mCallback.goToUnlockScreen();
+ } else {
+ mHeaderText.setText(R.string.keyguard_password_wrong_pin_code);
+ mPinText.setText("");
+ mEnteredDigits = 0;
+ }
+ mCallback.pokeWakelock();
+ }
+ });
}
}.start();
}
@@ -355,6 +359,7 @@
public void onClick(View v) {
if (v == mCancelButton) {
+ mPinText.setText(""); // clear the PIN entry field if the user cancels
mCallback.goToLockScreen();
return;
}
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index a7eff93..5408436 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -142,5 +142,5 @@
# ---------------------------
# NetworkStatsService.java
# ---------------------------
-51100 netstats_mobile_sample (dev_rx_bytes|2|2),(dev_tx_bytes|2|2),(dev_rx_pkts|2|1),(dev_tx_pkts|2|1),(xt_rx_bytes|2|2),(xt_tx_bytes|2|2),(xt_rx_pkts|2|1),(xt_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1),(trusted_time|2|3)
-51101 netstats_wifi_sample (dev_rx_bytes|2|2),(dev_tx_bytes|2|2),(dev_rx_pkts|2|1),(dev_tx_pkts|2|1),(xt_rx_bytes|2|2),(xt_tx_bytes|2|2),(xt_rx_pkts|2|1),(xt_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1),(trusted_time|2|3)
+51100 netstats_mobile_sample (dev_rx_bytes|2|2),(dev_tx_bytes|2|2),(dev_rx_pkts|2|1),(dev_tx_pkts|2|1),(xt_rx_bytes|2|2),(xt_tx_bytes|2|2),(xt_rx_pkts|2|1),(xt_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1),(trusted_time|2|3),(dev_history_start|2|3)
+51101 netstats_wifi_sample (dev_rx_bytes|2|2),(dev_tx_bytes|2|2),(dev_rx_pkts|2|1),(dev_tx_pkts|2|1),(xt_rx_bytes|2|2),(xt_tx_bytes|2|2),(xt_rx_pkts|2|1),(xt_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1),(trusted_time|2|3),(dev_history_start|2|3)
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index ddac35c..f5c4ed4 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -382,6 +382,7 @@
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
mScreenOn = true;
+ refreshImeWindowVisibilityLocked();
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
mScreenOn = false;
setImeWindowVisibilityStatusHiddenLocked();
@@ -640,6 +641,21 @@
updateImeWindowStatusLocked();
}
+ private void refreshImeWindowVisibilityLocked() {
+ final Configuration conf = mRes.getConfiguration();
+ final boolean haveHardKeyboard = conf.keyboard
+ != Configuration.KEYBOARD_NOKEYS;
+ final boolean hardKeyShown = haveHardKeyboard
+ && conf.hardKeyboardHidden
+ != Configuration.HARDKEYBOARDHIDDEN_YES;
+ final boolean isScreenLocked = mKeyguardManager != null
+ && mKeyguardManager.isKeyguardLocked()
+ && mKeyguardManager.isKeyguardSecure();
+ mImeWindowVis = (!isScreenLocked && (mInputShown || hardKeyShown)) ?
+ (InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE) : 0;
+ updateImeWindowStatusLocked();
+ }
+
private void updateImeWindowStatusLocked() {
setImeWindowStatus(mCurToken, mImeWindowVis, mBackDisposition);
}
@@ -1285,16 +1301,7 @@
}
if (mCurMethod != null) {
try {
- final Configuration conf = mRes.getConfiguration();
- final boolean haveHardKeyboard = conf.keyboard
- != Configuration.KEYBOARD_NOKEYS;
- final boolean hardKeyShown = haveHardKeyboard
- && conf.hardKeyboardHidden
- != Configuration.HARDKEYBOARDHIDDEN_YES;
- mImeWindowVis = (mInputShown || hardKeyShown) ? (
- InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE)
- : 0;
- updateImeWindowStatusLocked();
+ refreshImeWindowVisibilityLocked();
// If subtype is null, try to find the most applicable one from
// getCurrentInputMethodSubtype.
if (subtype == null) {
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index af9152d..d04b440 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -360,7 +360,7 @@
}
final String sciId = info.getId();
final InternalServiceConnection connection = new InternalServiceConnection(
- sciId, locale, scListener, bundle);
+ sciId, locale, bundle);
final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE);
serviceIntent.setComponent(info.getComponent());
if (DBG) {
@@ -704,15 +704,13 @@
}
private class InternalServiceConnection implements ServiceConnection {
- private final ISpellCheckerSessionListener mListener;
private final String mSciId;
private final String mLocale;
private final Bundle mBundle;
public InternalServiceConnection(
- String id, String locale, ISpellCheckerSessionListener listener, Bundle bundle) {
+ String id, String locale, Bundle bundle) {
mSciId = id;
mLocale = locale;
- mListener = listener;
mBundle = bundle;
}
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index 280b329..e6392d7 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -63,6 +63,10 @@
private static final String KEY_LAST_UPDATE_INTERVAL = "LAST_UPDATE_INTERVAL";
+ // Enable launching of applications when entering the dock.
+ private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true;
+ private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = false;
+
private static final int MSG_UPDATE_TWILIGHT = 0;
private static final int MSG_ENABLE_LOCATION_UPDATES = 1;
private static final int MSG_GET_NEW_LOCATION_UPDATE = 2;
@@ -139,14 +143,16 @@
if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(intent.getAction())) {
// Only launch car home when car mode is enabled and the caller
// has asked us to switch to it.
- if ((enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
+ if (ENABLE_LAUNCH_CAR_DOCK_APP
+ && (enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
category = Intent.CATEGORY_CAR_DOCK;
}
} else if (UiModeManager.ACTION_ENTER_DESK_MODE.equals(intent.getAction())) {
// Only launch car home when desk mode is enabled and the caller
// has asked us to switch to it. Currently re-using the car
// mode flag since we don't have a formal API for "desk mode".
- if ((enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
+ if (ENABLE_LAUNCH_DESK_DOCK_APP
+ && (enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
category = Intent.CATEGORY_DESK_DOCK;
}
} else {
@@ -550,11 +556,13 @@
} else {
Intent homeIntent = null;
if (mCarModeEnabled) {
- if ((enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
+ if (ENABLE_LAUNCH_CAR_DOCK_APP
+ && (enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
homeIntent = buildHomeIntent(Intent.CATEGORY_CAR_DOCK);
}
} else if (isDeskDockState(mDockState)) {
- if ((enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
+ if (ENABLE_LAUNCH_DESK_DOCK_APP
+ && (enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
homeIntent = buildHomeIntent(Intent.CATEGORY_DESK_DOCK);
}
} else {
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 2a1b1db..8c0f1e0 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -393,6 +393,7 @@
// on background handler thread, and verified
// READ_NETWORK_USAGE_HISTORY permission above.
+ maybeRefreshTrustedTime();
synchronized (mRulesLock) {
updateNetworkEnabledLocked();
updateNotificationsLocked();
@@ -445,7 +446,7 @@
// cycle boundary to recompute notifications.
// examine stats for each active policy
- final long currentTime = currentTimeMillis(true);
+ final long currentTime = currentTimeMillis();
for (NetworkPolicy policy : mNetworkPolicy.values()) {
// ignore policies that aren't relevant to user
if (!isTemplateRelevant(policy.template)) continue;
@@ -683,6 +684,8 @@
public void onReceive(Context context, Intent intent) {
// on background handler thread, and verified CONNECTIVITY_INTERNAL
// permission above.
+
+ maybeRefreshTrustedTime();
synchronized (mRulesLock) {
ensureActiveMobilePolicyLocked();
updateNetworkEnabledLocked();
@@ -702,7 +705,7 @@
// TODO: reset any policy-disabled networks when any policy is removed
// completely, which is currently rare case.
- final long currentTime = currentTimeMillis(true);
+ final long currentTime = currentTimeMillis();
for (NetworkPolicy policy : mNetworkPolicy.values()) {
// shortcut when policy has no limit
if (policy.limitBytes == LIMIT_DISABLED) {
@@ -802,7 +805,7 @@
// apply each policy that we found ifaces for; compute remaining data
// based on current cycle and historical stats, and push to kernel.
- final long currentTime = currentTimeMillis(true);
+ final long currentTime = currentTimeMillis();
for (NetworkPolicy policy : mNetworkRules.keySet()) {
final String[] ifaces = mNetworkRules.get(policy);
@@ -1092,6 +1095,7 @@
public void setNetworkPolicies(NetworkPolicy[] policies) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+ maybeRefreshTrustedTime();
synchronized (mRulesLock) {
mNetworkPolicy.clear();
for (NetworkPolicy policy : policies) {
@@ -1119,7 +1123,8 @@
public void snoozePolicy(NetworkTemplate template) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
- final long currentTime = currentTimeMillis(true);
+ maybeRefreshTrustedTime();
+ final long currentTime = currentTimeMillis();
synchronized (mRulesLock) {
// find and snooze local policy that matches
final NetworkPolicy policy = mNetworkPolicy.get(template);
@@ -1140,6 +1145,7 @@
public void setRestrictBackground(boolean restrictBackground) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+ maybeRefreshTrustedTime();
synchronized (mRulesLock) {
mRestrictBackground = restrictBackground;
updateRulesForRestrictBackgroundLocked();
@@ -1193,7 +1199,7 @@
return null;
}
- final long currentTime = currentTimeMillis(false);
+ final long currentTime = currentTimeMillis();
// find total bytes used under policy
final long start = computeLastCycleBoundary(currentTime, policy);
@@ -1472,6 +1478,7 @@
case MSG_LIMIT_REACHED: {
final String iface = (String) msg.obj;
+ maybeRefreshTrustedTime();
synchronized (mRulesLock) {
if (mMeteredIfaces.contains(iface)) {
try {
@@ -1551,12 +1558,16 @@
}
}
- private long currentTimeMillis(boolean allowRefresh) {
- // try refreshing time source when stale
- if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE && allowRefresh) {
+ /**
+ * Try refreshing {@link #mTime} when stale.
+ */
+ private void maybeRefreshTrustedTime() {
+ if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
mTime.forceRefresh();
}
+ }
+ private long currentTimeMillis() {
return mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis();
}
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 28cb983..871ed68 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -203,6 +203,8 @@
/** Set of historical {@code xtables} stats for known UIDs. */
private HashMap<UidStatsKey, NetworkStatsHistory> mUidStats = Maps.newHashMap();
+ /** Flag if {@link #mNetworkDevStats} have been loaded from disk. */
+ private boolean mNetworkStatsLoaded = false;
/** Flag if {@link #mUidStats} have been loaded from disk. */
private boolean mUidStatsLoaded = false;
@@ -272,6 +274,7 @@
// until actually needed.
readNetworkDevStatsLocked();
readNetworkXtStatsLocked();
+ mNetworkStatsLoaded = true;
}
// bootstrap initial stats to prevent double-counting later
@@ -322,14 +325,17 @@
mTeleManager.listen(mPhoneListener, LISTEN_NONE);
- writeNetworkDevStatsLocked();
- writeNetworkXtStatsLocked();
+ if (mNetworkStatsLoaded) {
+ writeNetworkDevStatsLocked();
+ writeNetworkXtStatsLocked();
+ }
if (mUidStatsLoaded) {
writeUidStatsLocked();
}
mNetworkDevStats.clear();
mNetworkXtStats.clear();
mUidStats.clear();
+ mNetworkStatsLoaded = false;
mUidStatsLoaded = false;
}
@@ -472,6 +478,18 @@
}
}
+ private long getHistoryStartLocked(
+ NetworkTemplate template, HashMap<NetworkIdentitySet, NetworkStatsHistory> source) {
+ long start = Long.MAX_VALUE;
+ for (NetworkIdentitySet ident : source.keySet()) {
+ if (templateMatches(template, ident)) {
+ final NetworkStatsHistory history = source.get(ident);
+ start = Math.min(start, history.getStart());
+ }
+ }
+ return start;
+ }
+
@Override
public NetworkStats getSummaryForAllUid(
NetworkTemplate template, long start, long end, boolean includeTags) {
@@ -771,6 +789,12 @@
private void performPoll(int flags) {
synchronized (mStatsLock) {
mWakeLock.acquire();
+
+ // try refreshing time source when stale
+ if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
+ mTime.forceRefresh();
+ }
+
try {
performPollLocked(flags);
} finally {
@@ -791,11 +815,6 @@
final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
- // try refreshing time source when stale
- if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
- mTime.forceRefresh();
- }
-
// TODO: consider marking "untrusted" times in historical stats
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
: System.currentTimeMillis();
@@ -981,6 +1000,7 @@
final long start = end - largestBucketSize;
final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1;
+ long devHistoryStart = Long.MAX_VALUE;
NetworkTemplate template = null;
NetworkStats.Entry devTotal = null;
@@ -990,24 +1010,27 @@
// collect mobile sample
template = buildTemplateMobileAll(getActiveSubscriberId(mContext));
devTotal = getSummaryForNetworkDev(template, start, end).getTotal(devTotal);
+ devHistoryStart = getHistoryStartLocked(template, mNetworkDevStats);
xtTotal = getSummaryForNetworkXt(template, start, end).getTotal(xtTotal);
uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
+
EventLogTags.writeNetstatsMobileSample(
devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
- trustedTime);
+ trustedTime, devHistoryStart);
// collect wifi sample
template = buildTemplateWifi();
devTotal = getSummaryForNetworkDev(template, start, end).getTotal(devTotal);
+ devHistoryStart = getHistoryStartLocked(template, mNetworkDevStats);
xtTotal = getSummaryForNetworkXt(template, start, end).getTotal(xtTotal);
uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
EventLogTags.writeNetstatsWifiSample(
devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
- trustedTime);
+ trustedTime, devHistoryStart);
}
/**
@@ -1243,11 +1266,28 @@
// trim any history beyond max
if (mTime.hasCache()) {
- final long currentTime = Math.min(
- System.currentTimeMillis(), mTime.currentTimeMillis());
+ final long systemCurrentTime = System.currentTimeMillis();
+ final long trustedCurrentTime = mTime.currentTimeMillis();
+
+ final long currentTime = Math.min(systemCurrentTime, trustedCurrentTime);
final long maxHistory = mSettings.getNetworkMaxHistory();
+
for (NetworkStatsHistory history : input.values()) {
+ final int beforeSize = history.size();
history.removeBucketsBefore(currentTime - maxHistory);
+ final int afterSize = history.size();
+
+ if (beforeSize > 24 && afterSize < beforeSize / 2) {
+ // yikes, dropping more than half of significant history
+ final StringBuilder builder = new StringBuilder();
+ builder.append("yikes, dropping more than half of history").append('\n');
+ builder.append("systemCurrentTime=").append(systemCurrentTime).append('\n');
+ builder.append("trustedCurrentTime=").append(trustedCurrentTime).append('\n');
+ builder.append("maxHistory=").append(maxHistory).append('\n');
+ builder.append("beforeSize=").append(beforeSize).append('\n');
+ builder.append("afterSize=").append(afterSize).append('\n');
+ mDropBox.addText(TAG_NETSTATS_ERROR, builder.toString());
+ }
}
}
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 53502db..61a8358 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -30,10 +30,6 @@
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE
endif
-ifneq (,$(findstring $(TARGET_DEVICE),tuna toro maguro))
- LOCAL_CFLAGS += -DREFRESH_RATE=59
-endif
-
LOCAL_SHARED_LIBRARIES := \
libcutils \
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 0618374..7c61e9a 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -693,12 +693,13 @@
expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
expectMeteredIfacesChanged(TEST_IFACE);
- expectClearNotifications();
+ future = expectClearNotifications();
tagFuture = expectEnqueueNotification();
replay();
mService.snoozePolicy(sTemplateWifi);
assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get());
+ future.get();
verifyAndReset();
}
}
@@ -734,9 +735,11 @@
expectLastCall().atLeastOnce();
}
- private void expectClearNotifications() throws Exception {
+ private Future<Void> expectClearNotifications() throws Exception {
+ final FutureAnswer future = new FutureAnswer();
mNotifManager.cancelNotificationWithTag(isA(String.class), isA(String.class), anyInt());
- expectLastCall().anyTimes();
+ expectLastCall().andAnswer(future).anyTimes();
+ return future;
}
private Future<String> expectEnqueueNotification() throws Exception {
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index f2ccb5b..07afe30 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1575,6 +1575,17 @@
// If the number passed in is null, just return false:
if (number == null) return false;
+ // If the number passed in is a SIP address, return false, since the
+ // concept of "emergency numbers" is only meaningful for calls placed
+ // over the cell network.
+ // (Be sure to do this check *before* calling extractNetworkPortionAlt(),
+ // since the whole point of extractNetworkPortionAlt() is to filter out
+ // any non-dialable characters (which would turn 'abc911def@example.com'
+ // into '911', for example.))
+ if (isUriNumber(number)) {
+ return false;
+ }
+
// Strip the separators from the number before comparing it
// to the list.
number = extractNetworkPortionAlt(number);
@@ -2107,6 +2118,31 @@
}
/**
+ * @return the "username" part of the specified SIP address,
+ * i.e. the part before the "@" character (or "%40").
+ *
+ * @param number SIP address of the form "username@domainname"
+ * (or the URI-escaped equivalent "username%40domainname")
+ * @see isUriNumber
+ *
+ * @hide
+ */
+ public static String getUsernameFromUriNumber(String number) {
+ // The delimiter between username and domain name can be
+ // either "@" or "%40" (the URI-escaped equivalent.)
+ int delimiterIndex = number.indexOf('@');
+ if (delimiterIndex < 0) {
+ delimiterIndex = number.indexOf("%40");
+ }
+ if (delimiterIndex < 0) {
+ Log.w(LOG_TAG,
+ "getUsernameFromUriNumber: no delimiter found in SIP addr '" + number + "'");
+ delimiterIndex = number.length();
+ }
+ return number.substring(0, delimiterIndex);
+ }
+
+ /**
* This function handles the plus code conversion within NANP CDMA network
* If the number format is
* 1)+1NANP,remove +,
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index 6324550..5d1f758 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -288,7 +288,7 @@
String number, CallerInfo previousResult) {
if (!previousResult.contactExists
&& PhoneNumberUtils.isUriNumber(number)) {
- String username = number.substring(0, number.indexOf('@'));
+ String username = PhoneNumberUtils.getUsernameFromUriNumber(number);
if (PhoneNumberUtils.isGlobalPhoneNumber(username)) {
previousResult = getCallerInfo(context,
Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
diff --git a/tests/FrameworkPerf/Android.mk b/tests/FrameworkPerf/Android.mk
index 03893d6..2eb52f0 100644
--- a/tests/FrameworkPerf/Android.mk
+++ b/tests/FrameworkPerf/Android.mk
@@ -7,6 +7,8 @@
LOCAL_PACKAGE_NAME := FrameworkPerf
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
LOCAL_AAPT_FLAGS = -c 120dpi,240dpi,160dpi,161dpi,320dpi,nodpi
include $(BUILD_PACKAGE)
diff --git a/tests/FrameworkPerf/AndroidManifest.xml b/tests/FrameworkPerf/AndroidManifest.xml
index e88f4fb..2591aaf 100644
--- a/tests/FrameworkPerf/AndroidManifest.xml
+++ b/tests/FrameworkPerf/AndroidManifest.xml
@@ -4,6 +4,7 @@
<uses-sdk android:minSdkVersion="5" />
<application android:hardwareAccelerated="false">
+ <uses-library android:name="android.test.runner" />
<activity android:name="FrameworkPerfActivity" android:label="Framework Perf">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -20,4 +21,9 @@
<receiver android:name="Receiver" android:exported="true">
</receiver>
</application>
+
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.frameworkperf"
+ android:label="Framework Perf Runner"
+ />
</manifest>
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
index 175f227..8ee5978 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
@@ -73,6 +73,8 @@
final ArrayList<RunResult> mResults = new ArrayList<RunResult>();
+ Object mResultNotifier = new Object();
+
class TestConnection implements ServiceConnection, IBinder.DeathRecipient {
Messenger mService;
boolean mLinked;
@@ -266,7 +268,9 @@
log(String.format("%s: fg=%d*%gms/op (%dms) / bg=%d*%gms/op (%dms)",
result.name, result.fgOps, result.getFgMsPerOp(), result.fgTime,
result.bgOps, result.getBgMsPerOp(), result.bgTime));
- mResults.add(result);
+ synchronized (mResults) {
+ mResults.add(result);
+ }
if (!mStarted) {
log("Stop");
stopRunning();
@@ -376,7 +380,9 @@
startService(new Intent(this, SchedulerService.class));
mCurOpIndex = 0;
mMaxRunTime = Integer.parseInt(mTestTime.getText().toString());
- mResults.clear();
+ synchronized (mResults) {
+ mResults.clear();
+ }
startCurOp();
}
}
@@ -393,17 +399,22 @@
mBgSpinner.setEnabled(true);
updateWakeLock();
stopService(new Intent(this, SchedulerService.class));
- for (int i=0; i<mResults.size(); i++) {
- RunResult result = mResults.get(i);
- float fgMsPerOp = result.getFgMsPerOp();
- float bgMsPerOp = result.getBgMsPerOp();
- String fgMsPerOpStr = fgMsPerOp != 0 ? Float.toString(fgMsPerOp) : "";
- String bgMsPerOpStr = bgMsPerOp != 0 ? Float.toString(bgMsPerOp) : "";
- Log.i("PerfRes", "\t" + result.name + "\t" + result.fgOps
- + "\t" + result.getFgMsPerOp() + "\t" + result.fgTime
- + "\t" + result.fgLongName + "\t" + result.bgOps
- + "\t" + result.getBgMsPerOp() + "\t" + result.bgTime
- + "\t" + result.bgLongName);
+ synchronized (mResults) {
+ for (int i=0; i<mResults.size(); i++) {
+ RunResult result = mResults.get(i);
+ float fgMsPerOp = result.getFgMsPerOp();
+ float bgMsPerOp = result.getBgMsPerOp();
+ String fgMsPerOpStr = fgMsPerOp != 0 ? Float.toString(fgMsPerOp) : "";
+ String bgMsPerOpStr = bgMsPerOp != 0 ? Float.toString(bgMsPerOp) : "";
+ Log.i("PerfRes", "\t" + result.name + "\t" + result.fgOps
+ + "\t" + result.getFgMsPerOp() + "\t" + result.fgTime
+ + "\t" + result.fgLongName + "\t" + result.bgOps
+ + "\t" + result.getBgMsPerOp() + "\t" + result.bgTime
+ + "\t" + result.bgLongName);
+ }
+ }
+ synchronized (mResultNotifier) {
+ mResultNotifier.notifyAll();
}
}
}
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfTest.java b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfTest.java
new file mode 100644
index 0000000..2a53b06
--- /dev/null
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfTest.java
@@ -0,0 +1,41 @@
+package com.android.frameworkperf;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class FrameworkPerfTest extends ActivityInstrumentationTestCase2<FrameworkPerfActivity> {
+
+ private static final int TEST_TIMEOUT = 15 * 60 * 1000; //15 minutes
+
+ public FrameworkPerfTest() {
+ super("com.android.frameworkperf", FrameworkPerfActivity.class);
+ }
+
+ public void testFrameworkPerf() {
+ final FrameworkPerfActivity activity = getActivity();
+ synchronized (activity.mResultNotifier) {
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ activity.startRunning();
+ }
+ });
+ try {
+ activity.mResultNotifier.wait(TEST_TIMEOUT);
+ } catch (InterruptedException e) {
+ fail("test interrupted.");
+ }
+ }
+ Bundle testResult = new Bundle();
+ synchronized (activity.mResults) {
+ assertTrue("test results were empty.", activity.mResults.size() > 0);
+ for (RunResult result : activity.mResults) {
+ testResult.putString(result.name, String.format("%f,%d,%d,%f,%d,%d",
+ result.getFgMsPerOp(), result.fgOps, result.fgTime,
+ result.getBgMsPerOp(), result.bgOps, result.bgTime));
+ }
+ }
+ getInstrumentation().sendStatus(Activity.RESULT_OK, testResult);
+ }
+}
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java b/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java
index 3d939bd..8cf1ac2 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java
@@ -33,6 +33,7 @@
import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.Paint;
import android.os.Bundle;
import android.os.FileUtils;
import android.os.Handler;
@@ -64,6 +65,9 @@
new MethodCallOp(), new ReadFileOp(),
new SchedulerOp(), new SchedulerOp(),
new GcOp(), new NoOp(),
+ new ObjectGcOp(), new NoOp(),
+ new FinalizingGcOp(), new NoOp(),
+ new PaintGcOp(), new NoOp(),
new IpcOp(), new NoOp(),
new IpcOp(), new CpuOp(),
new IpcOp(), new SchedulerOp(),
@@ -111,6 +115,10 @@
new CpuOp(),
new SchedulerOp(),
new MethodCallOp(),
+ new GcOp(),
+ new ObjectGcOp(),
+ new FinalizingGcOp(),
+ new PaintGcOp(),
new IpcOp(),
new CreateFileOp(),
new CreateWriteFileOp(),
@@ -467,6 +475,47 @@
}
}
+ static class ObjectGcOp extends Op {
+ ObjectGcOp() {
+ super("ObjectGc", "Run garbage collector with simple objects");
+ }
+
+ boolean onRun() {
+ Object obj = new Object();
+ return true;
+ }
+ }
+
+ static class FinalizingGcOp extends Op {
+ class Finalizable {
+ Finalizable() {}
+ @Override
+ protected void finalize() throws Throwable {
+ super.finalize();
+ }
+ }
+
+ FinalizingGcOp() {
+ super("FinalizingGc", "Run garbage collector with finalizable objects");
+ }
+
+ boolean onRun() {
+ Finalizable obj = new Finalizable();
+ return true;
+ }
+ }
+
+ static class PaintGcOp extends Op {
+ PaintGcOp() {
+ super("PaintGc", "Run garbage collector with Paint objects");
+ }
+
+ boolean onRun() {
+ Paint p = new Paint();
+ return true;
+ }
+ }
+
static class MethodCallOp extends Op {
MethodCallOp() {
super("MethodCall", "Method call");
diff --git a/voip/java/com/android/server/sip/SipHelper.java b/voip/java/com/android/server/sip/SipHelper.java
index dc628e0..113f007 100644
--- a/voip/java/com/android/server/sip/SipHelper.java
+++ b/voip/java/com/android/server/sip/SipHelper.java
@@ -73,7 +73,7 @@
*/
class SipHelper {
private static final String TAG = SipHelper.class.getSimpleName();
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
private static final boolean DEBUG_PING = false;
private SipStack mSipStack;
diff --git a/voip/java/com/android/server/sip/SipService.java b/voip/java/com/android/server/sip/SipService.java
index 119ed54..38a683e 100644
--- a/voip/java/com/android/server/sip/SipService.java
+++ b/voip/java/com/android/server/sip/SipService.java
@@ -68,8 +68,7 @@
*/
public final class SipService extends ISipService.Stub {
static final String TAG = "SipService";
- static final boolean DEBUGV = false;
- static final boolean DEBUG = true;
+ static final boolean DEBUG = false;
private static final int EXPIRY_TIME = 3600;
private static final int SHORT_EXPIRY_TIME = 10;
private static final int MIN_EXPIRY_TIME = 60;
@@ -581,7 +580,7 @@
@Override
public void onRinging(ISipSession s, SipProfile caller,
String sessionDescription) {
- if (DEBUGV) Log.d(TAG, "<<<<< onRinging()");
+ if (DEBUG) Log.d(TAG, "<<<<< onRinging()");
SipSessionGroup.SipSessionImpl session =
(SipSessionGroup.SipSessionImpl) s;
synchronized (SipService.this) {
@@ -778,7 +777,6 @@
private void restartLater() {
synchronized (SipService.this) {
int interval = NAT_MEASUREMENT_RETRY_INTERVAL;
- Log.d(TAG, "Retry measurement " + interval + "s later.");
mTimer.cancel(this);
mTimer.set(interval * 1000, this);
}
@@ -788,7 +786,7 @@
private class AutoRegistrationProcess extends SipSessionAdapter
implements Runnable, SipSessionGroup.KeepAliveProcessCallback {
private static final int MIN_KEEPALIVE_SUCCESS_COUNT = 10;
- private String TAG = "SipAudoReg";
+ private String TAG = "SipAutoReg";
private SipSessionGroup.SipSessionImpl mSession;
private SipSessionGroup.SipSessionImpl mKeepAliveSession;
@@ -820,13 +818,12 @@
// in registration to avoid adding duplicate entries to server
mMyWakeLock.acquire(mSession);
mSession.unregister();
- if (DEBUG) TAG = mSession.getLocalProfile().getUriString();
- if (DEBUG) Log.d(TAG, "start AutoRegistrationProcess");
+ TAG = "SipAutoReg:" + mSession.getLocalProfile().getUriString();
}
}
private void startKeepAliveProcess(int interval) {
- Log.d(TAG, "start keepalive w interval=" + interval);
+ if (DEBUG) Log.d(TAG, "start keepalive w interval=" + interval);
if (mKeepAliveSession == null) {
mKeepAliveSession = mSession.duplicate();
} else {
@@ -864,9 +861,11 @@
mKeepAliveSuccessCount = 0;
}
} else {
- Log.i(TAG, "keep keepalive going with interval "
- + interval + ", past success count="
- + mKeepAliveSuccessCount);
+ if (DEBUG) {
+ Log.i(TAG, "keep keepalive going with interval "
+ + interval + ", past success count="
+ + mKeepAliveSuccessCount);
+ }
mKeepAliveSuccessCount /= 2;
}
} else {
@@ -894,7 +893,9 @@
// SipSessionGroup.KeepAliveProcessCallback
@Override
public void onError(int errorCode, String description) {
- Log.e(TAG, "keepalive error: " + description);
+ if (DEBUG) {
+ Log.e(TAG, "keepalive error: " + description);
+ }
onResponse(true); // re-register immediately
}
@@ -917,7 +918,7 @@
public void onKeepAliveIntervalChanged() {
if (mKeepAliveSession != null) {
int newInterval = getKeepAliveInterval();
- if (DEBUGV) {
+ if (DEBUG) {
Log.v(TAG, "restart keepalive w interval=" + newInterval);
}
mKeepAliveSuccessCount = 0;
@@ -987,7 +988,7 @@
}
private void restart(int duration) {
- if (DEBUG) Log.d(TAG, "Refresh registration " + duration + "s later.");
+ Log.d(TAG, "Refresh registration " + duration + "s later.");
mTimer.cancel(this);
mTimer.set(duration * 1000, this);
}
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 06cdaf2..877a0a4 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -89,8 +89,8 @@
*/
class SipSessionGroup implements SipListener {
private static final String TAG = "SipSession";
- private static final boolean DEBUG = true;
- private static final boolean DEBUG_PING = DEBUG && false;
+ private static final boolean DEBUG = false;
+ private static final boolean DEBUG_PING = false;
private static final String ANONYMOUS = "anonymous";
// Limit the size of thread pool to 1 for the order issue when the phone is
// waken up from sleep and there are many packets to be processed in the SIP
@@ -205,7 +205,9 @@
}
synchronized void resetExternalAddress() {
- Log.d(TAG, " reset external addr on " + mSipStack);
+ if (DEBUG) {
+ Log.d(TAG, " reset external addr on " + mSipStack);
+ }
mExternalIp = null;
mExternalPort = 0;
}
@@ -362,7 +364,7 @@
+ SipSession.State.toString(session.mState));
}
} catch (Throwable e) {
- Log.w(TAG, "event process error: " + event, e);
+ Log.w(TAG, "event process error: " + event, getRootCause(e));
session.onError(e);
}
}
@@ -393,11 +395,22 @@
if ((rport > 0) && (externalIp != null)) {
mExternalIp = externalIp;
mExternalPort = rport;
- Log.d(TAG, " got external addr " + externalIp + ":" + rport
- + " on " + mSipStack);
+ if (DEBUG) {
+ Log.d(TAG, " got external addr " + externalIp + ":" + rport
+ + " on " + mSipStack);
+ }
}
}
+ private Throwable getRootCause(Throwable exception) {
+ Throwable cause = exception.getCause();
+ while (cause != null) {
+ exception = cause;
+ cause = exception.getCause();
+ }
+ return exception;
+ }
+
private SipSessionImpl createNewSession(RequestEvent event,
ISipSessionListener listener, ServerTransaction transaction,
int newState) throws SipException {
@@ -890,7 +903,9 @@
if (expires != null && time < expires.getExpires()) {
time = expires.getExpires();
}
- Log.v(TAG, "Expiry time = " + time);
+ if (DEBUG) {
+ Log.v(TAG, "Expiry time = " + time);
+ }
return time;
}
@@ -1409,15 +1424,6 @@
}
}
- private Throwable getRootCause(Throwable exception) {
- Throwable cause = exception.getCause();
- while (cause != null) {
- exception = cause;
- cause = exception.getCause();
- }
- return exception;
- }
-
private int getErrorCode(Throwable exception) {
String message = exception.getMessage();
if (exception instanceof UnknownHostException) {
@@ -1555,8 +1561,10 @@
try {
sendKeepAlive();
} catch (Throwable t) {
- Log.w(TAG, "keepalive error: "
- + mLocalProfile.getUriString(), getRootCause(t));
+ if (DEBUG) {
+ Log.w(TAG, "keepalive error: "
+ + mLocalProfile.getUriString(), getRootCause(t));
+ }
// It's possible that the keepalive process is being stopped
// during session.sendKeepAlive() so need to check mRunning
// again here.
diff --git a/voip/java/com/android/server/sip/SipWakeLock.java b/voip/java/com/android/server/sip/SipWakeLock.java
index 52bc094..0c4d14c 100644
--- a/voip/java/com/android/server/sip/SipWakeLock.java
+++ b/voip/java/com/android/server/sip/SipWakeLock.java
@@ -22,8 +22,8 @@
import java.util.HashSet;
class SipWakeLock {
- private static final boolean DEBUGV = SipService.DEBUGV;
- private static final String TAG = SipService.TAG;
+ private static final boolean DEBUG = false;
+ private static final String TAG = "SipWakeLock";
private PowerManager mPowerManager;
private PowerManager.WakeLock mWakeLock;
private PowerManager.WakeLock mTimerWakeLock;
@@ -34,9 +34,9 @@
}
synchronized void reset() {
+ if (DEBUG) Log.v(TAG, "reset count=" + mHolders.size());
mHolders.clear();
release(null);
- if (DEBUGV) Log.v(TAG, "~~~ hard reset wakelock");
}
synchronized void acquire(long timeout) {
@@ -55,8 +55,7 @@
PowerManager.PARTIAL_WAKE_LOCK, "SipWakeLock");
}
if (!mWakeLock.isHeld()) mWakeLock.acquire();
- if (DEBUGV) Log.v(TAG, "acquire wakelock: holder count="
- + mHolders.size());
+ if (DEBUG) Log.v(TAG, "acquire count=" + mHolders.size());
}
synchronized void release(Object holder) {
@@ -65,7 +64,6 @@
&& mWakeLock.isHeld()) {
mWakeLock.release();
}
- if (DEBUGV) Log.v(TAG, "release wakelock: holder count="
- + mHolders.size());
+ if (DEBUG) Log.v(TAG, "release count=" + mHolders.size());
}
}