Merge "Layout changes to recents" into ics-mr0
diff --git a/Android.mk b/Android.mk
index a38723a..f41130b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -402,8 +402,8 @@
resources/samples/AccelerometerPlay "Accelerometer Play" \
-samplecode $(sample_dir)/ActionBarCompat \
resources/samples/ActionBarCompat "Action Bar Compatibility" \
- -samplecode $(sample_dir)/AndroidBeam \
- resources/samples/AndroidBeam "Android Beam" \
+ -samplecode $(sample_dir)/AndroidBeamDemo \
+ resources/samples/AndroidBeamDemo "Android Beam Demo" \
-samplecode $(sample_dir)/ApiDemos \
resources/samples/ApiDemos "API Demos" \
-samplecode $(sample_dir)/Support4Demos \
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 1e238f0..64a2755 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -32,11 +32,9 @@
* when {@link AccessibilityEvent}s are fired. Such events denote some state transition
* in the user interface, for example, the focus has changed, a button has been clicked,
* etc. Such a service can optionally request the capability for querying the content
- * of the active window. Development of an accessibility service requires extends this
- * class and implements its abstract methods.
- * <p>
- * <strong>Lifecycle</strong>
- * </p>
+ * of the active window. Development of an accessibility service requires extending this
+ * class and implementing its abstract methods.
+ * <h3>Lifecycle</h3>
* <p>
* The lifecycle of an accessibility service is managed exclusively by the system and
* follows the established service life cycle. Additionally, starting or stopping an
@@ -45,30 +43,20 @@
* calls {@link AccessibilityService#onServiceConnected()}. This method can be
* overriden by clients that want to perform post binding setup.
* </p>
- * <p>
- * <strong>Declaration</strong>
- * </p>
+ * <h3>Declaration</h3>
* <p>
* An accessibility is declared as any other service in an AndroidManifest.xml but it
* must also specify that it handles the "android.accessibilityservice.AccessibilityService"
* {@link android.content.Intent}. Failure to declare this intent will cause the system to
* ignore the accessibility service. Following is an example declaration:
* </p>
- * <p>
- * <code>
- * <pre>
- * <service android:name=".MyAccessibilityService">
+ * <pre> <service android:name=".MyAccessibilityService">
* <intent-filter>
- * <action android:name="android.accessibilityservice.AccessibilityService" />
+ * <action android:name="android.accessibilityservice.AccessibilityService" />
* </intent-filter>
* . . .
- * </service>
- * </pre>
- * </code>
- * </p>
- * <p>
- * <strong>Configuration</strong>
- * </p>
+ * </service></pre>
+ * <h3>Configuration</h3>
* <p>
* An accessibility service can be configured to receive specific types of accessibility events,
* listen only to specific packages, get events from each type only once in a given time frame,
@@ -81,30 +69,24 @@
* <li>
* Providing a {@link #SERVICE_META_DATA meta-data} entry in the manifest when declaring
* the service. A service declaration with a meta-data tag is presented below:
- * <p>
- * <code>
- * <pre>
- * <service android:name=".MyAccessibilityService">
+ * <pre> <service android:name=".MyAccessibilityService">
* <intent-filter>
- * <action android:name="android.accessibilityservice.AccessibilityService" />
+ * <action android:name="android.accessibilityservice.AccessibilityService" />
* </intent-filter>
* <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibilityservice" />
- * </service>
- * </pre>
- * </code>
- * </p>
- * <p>
- * <strong>Note:</strong>This approach enables setting all properties.
+ * </service></pre>
+ * <p class="note">
+ * <strong>Note:</strong> This approach enables setting all properties.
* </p>
* <p>
* For more details refer to {@link #SERVICE_META_DATA} and
- * <code><{@link android.R.styleable#AccessibilityService accessibility-service}></code>..
+ * <code><{@link android.R.styleable#AccessibilityService accessibility-service}></code>.
* </p>
* </li>
* <li>
* Calling {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}. Note
* that this method can be called any time to dynamically change the service configuration.
- * <p>
+ * <p class="note">
* <strong>Note:</strong> This approach enables setting only dynamically configurable properties:
* {@link AccessibilityServiceInfo#eventTypes},
* {@link AccessibilityServiceInfo#feedbackType},
@@ -117,9 +99,7 @@
* </p>
* </li>
* </ul>
- * <p>
- * <strong>Retrieving window content</strong>
- * </p>
+ * <h3>Retrieving window content</h3>
* <p>
* An service can specify in its declaration that it can retrieve the active window
* content which is represented as a tree of {@link AccessibilityNodeInfo}. Note that
@@ -144,8 +124,8 @@
* this method will return an {@link AccessibilityNodeInfo} that can be used to traverse the
* window content which represented as a tree of such objects.
* </p>
- * <p>
- * <strong>Note</strong>An accessibility service may have requested to be notified for
+ * <p class="note">
+ * <strong>Note</strong> An accessibility service may have requested to be notified for
* a subset of the event types, thus be unaware that the active window has changed. Therefore
* accessibility service that would like to retrieve window content should:
* <ul>
@@ -158,15 +138,13 @@
* <li>
* Prepare that a retrieval method on {@link AccessibilityNodeInfo} may fail since the
* active window has changed and the service did not get the accessibility event yet. Note
- * that it is possible to have a retrieval method failing event adopting the strategy
+ * that it is possible to have a retrieval method failing even adopting the strategy
* specified in the previous bullet because the accessibility event dispatch is asynchronous
* and crosses process boundaries.
* </li>
* </ul>
* </p>
- * <p>
- * <b>Notification strategy</b>
- * </p>
+ * <h3>Notification strategy</h3>
* <p>
* For each feedback type only one accessibility service is notified. Services are notified
* in the order of registration. Hence, if two services are registered for the same
@@ -178,40 +156,39 @@
* well with most applications to coexist with "polished" ones that are targeted for
* specific applications.
* </p>
- * <p>
- * <b>Event types</b>
- * </p>
- * {@link AccessibilityEvent#TYPE_VIEW_CLICKED}
- * {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED}
- * {@link AccessibilityEvent#TYPE_VIEW_FOCUSED}
- * {@link AccessibilityEvent#TYPE_VIEW_SELECTED}
- * {@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED}
- * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}
- * {@link AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED}
- * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START}
- * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END}
- * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}
- * {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT}
- * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED}
- * {@link AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED}
- * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}
- * <p>
- * <b>Feedback types</b>
- * <p>
- * {@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}
- * {@link AccessibilityServiceInfo#FEEDBACK_HAPTIC}
- * {@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}
- * {@link AccessibilityServiceInfo#FEEDBACK_VISUAL}
- * {@link AccessibilityServiceInfo#FEEDBACK_GENERIC}
- *
- * @see AccessibilityEvent
- * @see AccessibilityServiceInfo
- * @see android.view.accessibility.AccessibilityManager
- *
+ * <p class="note">
* <strong>Note:</strong> The event notification timeout is useful to avoid propagating
* events to the client too frequently since this is accomplished via an expensive
* interprocess call. One can think of the timeout as a criteria to determine when
- * event generation has settled down.
+ * event generation has settled down.</p>
+ * <h3>Event types</h3>
+ * <ul>
+ * <li>{@link AccessibilityEvent#TYPE_VIEW_CLICKED}
+ * <li>{@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED}
+ * <li>{@link AccessibilityEvent#TYPE_VIEW_FOCUSED}
+ * <li>{@link AccessibilityEvent#TYPE_VIEW_SELECTED}
+ * <li>{@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED}
+ * <li>{@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}
+ * <li>{@link AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED}
+ * <li>{@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START}
+ * <li>{@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END}
+ * <li>{@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}
+ * <li>{@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT}
+ * <li>{@link AccessibilityEvent#TYPE_VIEW_SCROLLED}
+ * <li>{@link AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED}
+ * <li>{@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}
+ * </ul>
+ * <h3>Feedback types</h3>
+ * <ul>
+ * <li>{@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}
+ * <li>{@link AccessibilityServiceInfo#FEEDBACK_HAPTIC}
+ * <li>{@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}
+ * <li>{@link AccessibilityServiceInfo#FEEDBACK_VISUAL}
+ * <li>{@link AccessibilityServiceInfo#FEEDBACK_GENERIC}
+ * </ul>
+ * @see AccessibilityEvent
+ * @see AccessibilityServiceInfo
+ * @see android.view.accessibility.AccessibilityManager
*/
public abstract class AccessibilityService extends Service {
/**
@@ -225,10 +202,7 @@
* about itself. This meta-data must reference an XML resource containing an
* <code><{@link android.R.styleable#AccessibilityService accessibility-service}></code>
* tag. This is a a sample XML file configuring an accessibility service:
- * <p>
- * <code>
- * <pre>
- * <accessibility-service
+ * <pre> <accessibility-service
* android:accessibilityEventTypes="typeViewClicked|typeViewFocused"
* android:packageNames="foo.bar, foo.baz"
* android:accessibilityFeedbackType="feedbackSpoken"
@@ -237,10 +211,7 @@
* android:settingsActivity="foo.bar.TestBackActivity"
* android:canRetrieveWindowContent="true"
* . . .
- * />
- * </pre>
- * </code>
- * </p>
+ * /></pre>
*/
public static final String SERVICE_META_DATA = "android.accessibilityservice";
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index c09e87f..e37b3fa 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -54,6 +54,12 @@
* without text editors, so that it will be placed on top of the current
* input method UI. You can modify this behavior by forcing the flag to your
* desired mode after calling {@link #onCreate}.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about creating dialogs, read the
+ * <a href="{@docRoot}guide/topics/ui/dialogs.html">Dialogs</a> developer guide.</p>
+ * </div>
*/
public class AlertDialog extends Dialog implements DialogInterface {
private AlertController mAlert;
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 82186dd..7a69419 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -66,9 +66,14 @@
* your Dialog takes input focus, as it the default) with the following code:
*
* <pre>
- * getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
- * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
- * </pre>
+ * getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+ * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);</pre>
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about creating dialogs, read the
+ * <a href="{@docRoot}guide/topics/ui/dialogs.html">Dialogs</a> developer guide.</p>
+ * </div>
*/
public class Dialog implements DialogInterface, Window.Callback,
KeyEvent.Callback, OnCreateContextMenuListener {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 9490b96..f5add25 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -38,9 +38,12 @@
* <p>The {@link Notification.Builder Notification.Builder} has been added to make it
* easier to construct Notifications.</p>
*
- * <p>For a guide to creating notifications, see the
- * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Creating Status
- * Bar Notifications</a> document in the Dev Guide.</p>
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For a guide to creating notifications, read the
+ * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>
+ * developer guide.</p>
+ * </div>
*/
public class Notification implements Parcelable
{
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 4913e78..bf83f5e 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -55,6 +55,13 @@
* You do not instantiate this class directly; instead, retrieve it through
* {@link android.content.Context#getSystemService}.
*
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For a guide to creating notifications, read the
+ * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>
+ * developer guide.</p>
+ * </div>
+ *
* @see android.app.Notification
* @see android.content.Context#getSystemService
*/
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index e452f1f..092a0c8 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -45,9 +45,6 @@
* multiple applications you can use a database directly via
* {@link android.database.sqlite.SQLiteDatabase}.
*
- * <p>For more information, read <a href="{@docRoot}guide/topics/providers/content-providers.html">Content
- * Providers</a>.</p>
- *
* <p>When a request is made via
* a {@link ContentResolver} the system inspects the authority of the given URI and passes the
* request to the content provider registered with the authority. The content provider can interpret
@@ -73,6 +70,12 @@
* <p>Requests to {@link ContentResolver} are automatically forwarded to the appropriate
* ContentProvider instance, so subclasses don't have to worry about the details of
* cross-process calls.</p>
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about using content providers, read the
+ * <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
+ * developer guide.</p>
*/
public abstract class ContentProvider implements ComponentCallbacks2 {
private static final String TAG = "ContentProvider";
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 0d25926..e923349 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -54,6 +54,12 @@
/**
* This class provides applications access to the content model.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about using a ContentResolver with content providers, read the
+ * <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
+ * developer guide.</p>
*/
public abstract class ContentResolver {
/**
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 7a7e4f4..3eb7647 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2124,6 +2124,9 @@
if (pkg == null) {
return null;
}
+ if ((flags & GET_SIGNATURES) != 0) {
+ packageParser.collectCertificates(pkg, 0);
+ }
return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0);
}
diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java
index da878d4..5fe58e9 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/core/java/android/nfc/NfcActivityManager.java
@@ -162,6 +162,7 @@
synchronized void maybeRemoveState(Activity activity, NfcActivityState state) {
if (state.ndefMessage == null && state.ndefMessageCallback == null &&
state.onNdefPushCompleteCallback == null) {
+ NfcFragment.remove(activity);
mNfcState.remove(activity);
}
}
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index d1dc6e5..0640d7e 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -658,6 +658,24 @@
return _result;
}
+ @Override
+ public int verifyEncryptionPassword(String password) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ int _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(password);
+ mRemote.transact(Stub.TRANSACTION_verifyEncryptionPassword, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
public Parcelable[] getVolumeList() throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
@@ -761,6 +779,8 @@
static final int TRANSACTION_getEncryptionState = IBinder.FIRST_CALL_TRANSACTION + 31;
+ static final int TRANSACTION_verifyEncryptionPassword = IBinder.FIRST_CALL_TRANSACTION + 32;
+
/**
* Cast an IBinder object into an IMountService interface, generating a
* proxy if needed.
@@ -1286,6 +1306,12 @@
public int changeEncryptionPassword(String password) throws RemoteException;
/**
+ * Verify the encryption password against the stored volume. This method
+ * may only be called by the system process.
+ */
+ public int verifyEncryptionPassword(String password) throws RemoteException;
+
+ /**
* Returns list of all mountable volumes.
*/
public Parcelable[] getVolumeList() throws RemoteException;
diff --git a/core/java/android/speech/tts/TtsEngines.java b/core/java/android/speech/tts/TtsEngines.java
index bb72bea..2706bc7 100644
--- a/core/java/android/speech/tts/TtsEngines.java
+++ b/core/java/android/speech/tts/TtsEngines.java
@@ -344,7 +344,10 @@
String v1Locale = lang;
if (!TextUtils.isEmpty(country)) {
v1Locale += LOCALE_DELIMITER + country;
+ } else {
+ return v1Locale;
}
+
if (!TextUtils.isEmpty(variant)) {
v1Locale += LOCALE_DELIMITER + variant;
}
@@ -355,8 +358,28 @@
private String getDefaultLocale() {
final Locale locale = Locale.getDefault();
- return locale.getISO3Language() + LOCALE_DELIMITER + locale.getISO3Country() +
- LOCALE_DELIMITER + locale.getVariant();
+ // Note that the default locale might have an empty variant
+ // or language, and we take care that the construction is
+ // the same as {@link #getV1Locale} i.e no trailing delimiters
+ // or spaces.
+ String defaultLocale = locale.getISO3Language();
+ if (TextUtils.isEmpty(defaultLocale)) {
+ Log.w(TAG, "Default locale is empty.");
+ return "";
+ }
+
+ if (!TextUtils.isEmpty(locale.getISO3Country())) {
+ defaultLocale += LOCALE_DELIMITER + locale.getISO3Country();
+ } else {
+ // Do not allow locales of the form lang--variant with
+ // an empty country.
+ return defaultLocale;
+ }
+ if (!TextUtils.isEmpty(locale.getVariant())) {
+ defaultLocale += LOCALE_DELIMITER + locale.getVariant();
+ }
+
+ return defaultLocale;
}
/**
diff --git a/core/java/android/view/ContextMenu.java b/core/java/android/view/ContextMenu.java
index dd1d7db..decabcb 100644
--- a/core/java/android/view/ContextMenu.java
+++ b/core/java/android/view/ContextMenu.java
@@ -29,6 +29,12 @@
* To show a context menu on long click, most clients will want to call
* {@link Activity#registerForContextMenu} and override
* {@link Activity#onCreateContextMenu}.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For information about creating menus, read the
+ * <a href="{@docRoot}guide/topics/ui/menus.html">Menus</a> developer guide.</p>
+ * </div>
*/
public interface ContextMenu extends Menu {
/**
diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java
index 8f491ef..f559e21 100644
--- a/core/java/android/view/DragEvent.java
+++ b/core/java/android/view/DragEvent.java
@@ -114,6 +114,12 @@
* {@link android.view.DragEvent#writeToParcel(Parcel,int)}, and
* {@link android.view.DragEvent#toString()} methods always return valid data.
* </p>
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For a guide to implementing drag and drop features, read the
+ * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
+ * </div>
*/
public class DragEvent implements Parcelable {
private static final boolean TRACK_RECYCLED_LOCATION = false;
diff --git a/core/java/android/view/Menu.java b/core/java/android/view/Menu.java
index 97825e6..7157bc5 100644
--- a/core/java/android/view/Menu.java
+++ b/core/java/android/view/Menu.java
@@ -41,6 +41,12 @@
* item check marks are discouraged.
* <li><b>Sub menus</b>: Do not support item icons, or nested sub menus.
* </ol>
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about creating menus, read the
+ * <a href="{@docRoot}guide/topics/ui/menus.html">Menus</a> developer guide.</p>
+ * </div>
*/
public interface Menu {
diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java
index ccd8353..2dfbcb5 100644
--- a/core/java/android/view/MenuItem.java
+++ b/core/java/android/view/MenuItem.java
@@ -29,6 +29,12 @@
* methods.
* <p>
* For a feature set of specific menu types, see {@link Menu}.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For information about creating menus, read the
+ * <a href="{@docRoot}guide/topics/ui/menus.html">Menus</a> developer guide.</p>
+ * </div>
*/
public interface MenuItem {
/*
diff --git a/core/java/android/view/SubMenu.java b/core/java/android/view/SubMenu.java
index e981486..196a183 100644
--- a/core/java/android/view/SubMenu.java
+++ b/core/java/android/view/SubMenu.java
@@ -22,6 +22,12 @@
* Subclass of {@link Menu} for sub menus.
* <p>
* Sub menus do not support item icons, or nested sub menus.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For information about creating menus, read the
+ * <a href="{@docRoot}guide/topics/ui/menus.html">Menus</a> developer guide.</p>
+ * </div>
*/
public interface SubMenu extends Menu {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 73e5026..61b13d5 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -418,7 +418,7 @@
* <h3>Drawing</h3>
* <p>
* Drawing is handled by walking the tree and rendering each view that
- * intersects the the invalid region. Because the tree is traversed in-order,
+ * intersects the invalid region. Because the tree is traversed in-order,
* this means that parents will draw before (i.e., behind) their children, with
* siblings drawn in the order they appear in the tree.
* If you set a background drawable for a View, then the View will draw it for you
@@ -3830,7 +3830,10 @@
* responsible for handling this call.
* </p>
*
- * @param eventType The type of the event to send.
+ * @param eventType The type of the event to send, as defined by several types from
+ * {@link android.view.accessibility.AccessibilityEvent}, such as
+ * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
+ * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
*
* @see #onInitializeAccessibilityEvent(AccessibilityEvent)
* @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
@@ -3943,27 +3946,28 @@
/**
* Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
* giving a chance to this View to populate the accessibility event with its
- * text content. While the implementation is free to modify other event
- * attributes this should be performed in
+ * text content. While this method is free to modify event
+ * attributes other than text content, doing so should normally be performed in
* {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
* <p>
* Example: Adding formatted date string to an accessibility event in addition
- * to the text added by the super implementation.
- * </p><p><pre><code>
- * public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ * to the text added by the super implementation:
+ * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
* super.onPopulateAccessibilityEvent(event);
* final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
* String selectedDateUtterance = DateUtils.formatDateTime(mContext,
* mCurrentDate.getTimeInMillis(), flags);
* event.getText().add(selectedDateUtterance);
- * }
- * </code></pre></p>
+ * }</pre>
* <p>
* If an {@link AccessibilityDelegate} has been specified via calling
* {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
* {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
* is responsible for handling this call.
* </p>
+ * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
+ * information to the event, in case the default implementation has basic information to add.
+ * </p>
*
* @param event The accessibility event which to populate.
*
@@ -3994,20 +3998,20 @@
* the event.
* <p>
* Example: Setting the password property of an event in addition
- * to properties set by the super implementation.
- * </p><p><pre><code>
- * public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
- * super.onInitializeAccessibilityEvent(event);
- * event.setPassword(true);
- * }
- * </code></pre></p>
+ * to properties set by the super implementation:
+ * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ * super.onInitializeAccessibilityEvent(event);
+ * event.setPassword(true);
+ * }</pre>
* <p>
* If an {@link AccessibilityDelegate} has been specified via calling
* {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
* {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
* is responsible for handling this call.
* </p>
- *
+ * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
+ * information to the event, in case the default implementation has basic information to add.
+ * </p>
* @param event The event to initialize.
*
* @see #sendAccessibilityEvent(int)
@@ -6179,8 +6183,7 @@
* are delivered to the view under the pointer. All other generic motion events are
* delivered to the focused view.
* </p>
- * <code>
- * public boolean onGenericMotionEvent(MotionEvent event) {
+ * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
* if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
* if (event.getAction() == MotionEvent.ACTION_MOVE) {
* // process the joystick movement...
@@ -6198,8 +6201,7 @@
* }
* }
* return super.onGenericMotionEvent(event);
- * }
- * </code>
+ * }</pre>
*
* @param event The generic motion event being processed.
* @return True if the event was handled, false otherwise.
@@ -8364,7 +8366,7 @@
!((ViewGroup) mParent).isViewTransitioning(this));
}
/**
- * Mark the the area defined by dirty as needing to be drawn. If the view is
+ * Mark the area defined by dirty as needing to be drawn. If the view is
* visible, {@link #onDraw(android.graphics.Canvas)} will be called at some point
* in the future. This must be called from a UI thread. To call from a non-UI
* thread, call {@link #postInvalidate()}.
@@ -8409,7 +8411,7 @@
}
/**
- * Mark the the area defined by the rect (l,t,r,b) as needing to be drawn.
+ * Mark the area defined by the rect (l,t,r,b) as needing to be drawn.
* The coordinates of the dirty rect are relative to the view.
* If the view is visible, {@link #onDraw(android.graphics.Canvas)}
* will be called at some point in the future. This must be called from
@@ -13095,6 +13097,12 @@
* {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
* so that your application can draw the shadow image in the Canvas.
* </p>
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For a guide to implementing drag and drop features, read the
+ * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
+ * </div>
*/
public static class DragShadowBuilder {
private final WeakReference<View> mView;
@@ -14086,6 +14094,12 @@
* to this view. The callback will be invoked before the hosting view's own
* onDrag(event) method. If the listener wants to fall back to the hosting view's
* onDrag(event) behavior, it should return 'false' from this callback.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For a guide to implementing drag and drop features, read the
+ * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
+ * </div>
*/
public interface OnDragListener {
/**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 9266ae2..62b20b3 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -60,6 +60,12 @@
* Also see {@link LayoutParams} for layout attributes.
* </p>
*
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about creating user interface layouts, read the
+ * <a href="{@docRoot}guide/topics/ui/declaring-layout.html">XML Layouts</a> developer
+ * guide.</p></div>
+ *
* @attr ref android.R.styleable#ViewGroup_clipChildren
* @attr ref android.R.styleable#ViewGroup_clipToPadding
* @attr ref android.R.styleable#ViewGroup_layoutAnimation
@@ -5158,7 +5164,13 @@
* </ul>
* There are subclasses of LayoutParams for different subclasses of
* ViewGroup. For example, AbsoluteLayout has its own subclass of
- * LayoutParams which adds an X and Y value.
+ * LayoutParams which adds an X and Y value.</p>
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about creating user interface layouts, read the
+ * <a href="{@docRoot}guide/topics/ui/declaring-layout.html">XML Layouts</a> developer
+ * guide.</p></div>
*
* @attr ref android.R.styleable#ViewGroup_Layout_layout_height
* @attr ref android.R.styleable#ViewGroup_Layout_layout_width
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index 122865e..83df8a5 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -97,6 +97,7 @@
protected AudioService mAudioService;
private boolean mRingIsSilent;
private boolean mShowCombinedVolumes;
+ private boolean mVoiceCapable;
/** Dialog containing all the sliders */
private final Dialog mDialog;
@@ -117,40 +118,62 @@
/** All the slider controls mapped by stream type */
private HashMap<Integer,StreamControl> mStreamControls;
+ private enum StreamResources {
+ BluetoothSCOStream(AudioManager.STREAM_BLUETOOTH_SCO,
+ R.string.volume_icon_description_bluetooth,
+ R.drawable.ic_audio_bt,
+ R.drawable.ic_audio_bt,
+ false),
+ RingerStream(AudioManager.STREAM_RING,
+ R.string.volume_icon_description_ringer,
+ R.drawable.ic_audio_ring_notif,
+ R.drawable.ic_audio_ring_notif_mute,
+ false),
+ VoiceStream(AudioManager.STREAM_VOICE_CALL,
+ R.string.volume_icon_description_incall,
+ R.drawable.ic_audio_phone,
+ R.drawable.ic_audio_phone,
+ false),
+ AlarmStream(AudioManager.STREAM_ALARM,
+ R.string.volume_alarm,
+ R.drawable.ic_audio_alarm,
+ R.drawable.ic_audio_alarm_mute,
+ false),
+ MediaStream(AudioManager.STREAM_MUSIC,
+ R.string.volume_icon_description_media,
+ R.drawable.ic_audio_vol,
+ R.drawable.ic_audio_vol_mute,
+ true),
+ NotificationStream(AudioManager.STREAM_NOTIFICATION,
+ R.string.volume_icon_description_notification,
+ R.drawable.ic_audio_notification,
+ R.drawable.ic_audio_notification_mute,
+ true);
+
+ int streamType;
+ int descRes;
+ int iconRes;
+ int iconMuteRes;
+ // RING, VOICE_CALL & BLUETOOTH_SCO are hidden unless explicitly requested
+ boolean show;
+
+ StreamResources(int streamType, int descRes, int iconRes, int iconMuteRes, boolean show) {
+ this.streamType = streamType;
+ this.descRes = descRes;
+ this.iconRes = iconRes;
+ this.iconMuteRes = iconMuteRes;
+ this.show = show;
+ }
+ };
+
// List of stream types and their order
- // RING, VOICE_CALL & BLUETOOTH_SCO are hidden unless explicitly requested
- private static final int [] STREAM_TYPES = {
- AudioManager.STREAM_BLUETOOTH_SCO,
- AudioManager.STREAM_RING,
- AudioManager.STREAM_VOICE_CALL,
- AudioManager.STREAM_MUSIC,
- AudioManager.STREAM_NOTIFICATION
- };
-
- private static final int [] CONTENT_DESCRIPTIONS = {
- R.string.volume_icon_description_bluetooth,
- R.string.volume_icon_description_ringer,
- R.string.volume_icon_description_incall,
- R.string.volume_icon_description_media,
- R.string.volume_icon_description_notification
- };
-
- // These icons need to correspond to the ones above.
- private static final int [] STREAM_ICONS_NORMAL = {
- R.drawable.ic_audio_bt,
- R.drawable.ic_audio_ring_notif,
- R.drawable.ic_audio_phone,
- R.drawable.ic_audio_vol,
- R.drawable.ic_audio_notification,
- };
-
- // These icons need to correspond to the ones above.
- private static final int [] STREAM_ICONS_MUTED = {
- R.drawable.ic_audio_bt,
- R.drawable.ic_audio_ring_notif_mute,
- R.drawable.ic_audio_phone,
- R.drawable.ic_audio_vol_mute,
- R.drawable.ic_audio_notification_mute,
+ private static final StreamResources[] STREAMS = {
+ StreamResources.BluetoothSCOStream,
+ StreamResources.RingerStream,
+ StreamResources.VoiceStream,
+ StreamResources.MediaStream,
+ StreamResources.NotificationStream,
+ StreamResources.AlarmStream
};
/** Object that contains data for each slider */
@@ -221,7 +244,8 @@
mToneGenerators = new ToneGenerator[AudioSystem.getNumStreamTypes()];
mVibrator = new Vibrator();
- mShowCombinedVolumes = !context.getResources().getBoolean(R.bool.config_voice_capable);
+ mVoiceCapable = context.getResources().getBoolean(R.bool.config_voice_capable);
+ mShowCombinedVolumes = !mVoiceCapable;
// If we don't want to show multiple volumes, hide the settings button and divider
if (!mShowCombinedVolumes) {
mMoreButton.setVisibility(View.GONE);
@@ -260,10 +284,14 @@
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mStreamControls = new HashMap<Integer,StreamControl>(STREAM_TYPES.length);
+ mStreamControls = new HashMap<Integer, StreamControl>(STREAMS.length);
Resources res = mContext.getResources();
- for (int i = 0; i < STREAM_TYPES.length; i++) {
- final int streamType = STREAM_TYPES[i];
+ for (int i = 0; i < STREAMS.length; i++) {
+ StreamResources streamRes = STREAMS[i];
+ int streamType = streamRes.streamType;
+ if (mVoiceCapable && streamRes == StreamResources.NotificationStream) {
+ streamRes = StreamResources.RingerStream;
+ }
StreamControl sc = new StreamControl();
sc.streamType = streamType;
sc.group = (ViewGroup) inflater.inflate(R.layout.volume_adjust_item, null);
@@ -273,9 +301,9 @@
sc.icon.setOnClickListener(this);
}
sc.icon.setTag(sc);
- sc.icon.setContentDescription(res.getString(CONTENT_DESCRIPTIONS[i]));
- sc.iconRes = STREAM_ICONS_NORMAL[i];
- sc.iconMuteRes = STREAM_ICONS_MUTED[i];
+ sc.icon.setContentDescription(res.getString(streamRes.descRes));
+ sc.iconRes = streamRes.iconRes;
+ sc.iconMuteRes = streamRes.iconMuteRes;
sc.icon.setImageResource(sc.iconRes);
sc.seekbarView = (SeekBar) sc.group.findViewById(R.id.seekbar);
int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO ||
@@ -307,13 +335,10 @@
private void addOtherVolumes() {
if (!mShowCombinedVolumes) return;
- for (int i = 0; i < STREAM_TYPES.length; i++) {
+ for (int i = 0; i < STREAMS.length; i++) {
// Skip the phone specific ones and the active one
- final int streamType = STREAM_TYPES[i];
- if (streamType == AudioManager.STREAM_RING
- || streamType == AudioManager.STREAM_VOICE_CALL
- || streamType == AudioManager.STREAM_BLUETOOTH_SCO
- || streamType == mActiveStreamType) {
+ final int streamType = STREAMS[i].streamType;
+ if (!STREAMS[i].show || streamType == mActiveStreamType) {
continue;
}
StreamControl sc = mStreamControls.get(streamType);
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index a80c2a7..e37de6f 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -49,10 +49,8 @@
* </p>
* <p>
* <code>
- * <pre>
- * AccessibilityManager accessibilityManager =
- * (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
- * </pre>
+ * <pre>AccessibilityManager accessibilityManager =
+ * (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);</pre>
* </code>
* </p>
*
@@ -91,7 +89,10 @@
new CopyOnWriteArrayList<AccessibilityStateChangeListener>();
/**
- * Listener for the accessibility state.
+ * Listener for the system accessibility state. To listen for changes to the accessibility
+ * state on the device, implement this interface and register it with the system by
+ * calling {@link AccessibilityManager#addAccessibilityStateChangeListener
+ * addAccessibilityStateChangeListener()}.
*/
public interface AccessibilityStateChangeListener {
diff --git a/core/java/android/webkit/HTML5Audio.java b/core/java/android/webkit/HTML5Audio.java
index 9fc48a1..97d61ba 100644
--- a/core/java/android/webkit/HTML5Audio.java
+++ b/core/java/android/webkit/HTML5Audio.java
@@ -238,24 +238,27 @@
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
// resume playback
- if (mMediaPlayer == null) resetMediaPlayer();
- else if (!mMediaPlayer.isPlaying()) mMediaPlayer.start();
- mState = STARTED;
+ if (mMediaPlayer == null) {
+ resetMediaPlayer();
+ } else if (mState != ERROR && !mMediaPlayer.isPlaying()) {
+ mMediaPlayer.start();
+ mState = STARTED;
+ }
break;
case AudioManager.AUDIOFOCUS_LOSS:
- // Lost focus for an unbounded amount of time: stop playback and release media player
- if (mMediaPlayer.isPlaying()) mMediaPlayer.stop();
- mMediaPlayer.release();
- mMediaPlayer = null;
+ // Lost focus for an unbounded amount of time: stop playback.
+ if (mState != ERROR && mMediaPlayer.isPlaying()) {
+ mMediaPlayer.stop();
+ mState = STOPPED;
+ }
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
// Lost focus for a short time, but we have to stop
- // playback. We don't release the media player because playback
- // is likely to resume
- if (mMediaPlayer.isPlaying()) mMediaPlayer.pause();
+ // playback.
+ if (mState != ERROR && mMediaPlayer.isPlaying()) pause();
break;
}
}
@@ -273,10 +276,7 @@
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);
- if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
- // could not get audio focus.
- teardown();
- } else {
+ if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
mMediaPlayer.start();
mState = STARTED;
}
@@ -299,8 +299,13 @@
}
}
+ /**
+ * Called only over JNI when WebKit is happy to
+ * destroy the media player.
+ */
private void teardown() {
mMediaPlayer.release();
+ mMediaPlayer = null;
mState = ERROR;
mNativePointer = 0;
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 1c22a0b..48615bd 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -4514,7 +4514,7 @@
boolean UIAnimationsRunning = false;
// Currently for each draw we compute the animation values;
// We may in the future decide to do that independently.
- if (mNativeClass != 0 && nativeEvaluateLayersAnimations()) {
+ if (mNativeClass != 0 && nativeEvaluateLayersAnimations(mNativeClass)) {
UIAnimationsRunning = true;
// If we have unfinished (or unstarted) animations,
// we ask for a repaint. We only need to do this in software
@@ -4530,9 +4530,9 @@
extras = DRAW_EXTRAS_FIND;
} else if (mSelectingText && !USE_JAVA_TEXT_SELECTION) {
extras = DRAW_EXTRAS_SELECTION;
- nativeSetSelectionPointer(mDrawSelectionPointer,
- mZoomManager.getInvScale(),
- mSelectX, mSelectY - getTitleHeight());
+ nativeSetSelectionPointer(mNativeClass,
+ mDrawSelectionPointer,
+ mZoomManager.getInvScale(), mSelectX, mSelectY - getTitleHeight());
} else if (drawCursorRing) {
extras = DRAW_EXTRAS_CURSOR_RING;
}
@@ -4546,8 +4546,8 @@
}
if (canvas.isHardwareAccelerated()) {
- int functor = nativeGetDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport,
- mGLViewportEmpty ? null : mViewRectViewport, getScale(), extras);
+ int functor = nativeGetDrawGLFunction(mNativeClass,
+ mGLViewportEmpty ? null : mGLRectViewport, mGLViewportEmpty ? null : mViewRectViewport, getScale(), extras);
((HardwareCanvas) canvas).callDrawGLFunction(functor);
if (mHardwareAccelSkia != getSettings().getHardwareAccelSkiaEnabled()) {
@@ -9416,9 +9416,9 @@
// We never want to change button state if we are hardware accelerated,
// but we DO want to invalidate as necessary so that the GL ring
// can be drawn
- nativeRecordButtons(false, false, inval);
+ nativeRecordButtons(mNativeClass, false, false, inval);
} else {
- nativeRecordButtons(focus, pressed, inval);
+ nativeRecordButtons(mNativeClass, focus, pressed, inval);
}
}
@@ -9453,9 +9453,9 @@
private native int nativeDraw(Canvas canvas, int color, int extra,
boolean splitIfNeeded);
private native void nativeDumpDisplayTree(String urlOrNull);
- private native boolean nativeEvaluateLayersAnimations();
- private native int nativeGetDrawGLFunction(Rect rect, Rect viewRect,
- float scale, int extras);
+ 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);
private native void nativeExtendSelection(int x, int y);
private native int nativeFindAll(String findLower, String findUpper,
@@ -9518,8 +9518,8 @@
private native boolean nativePointInNavCache(int x, int y, int slop);
// Like many other of our native methods, you must make sure that
// mNativeClass is not null before calling this method.
- private native void nativeRecordButtons(boolean focused,
- boolean pressed, boolean invalidate);
+ private native void nativeRecordButtons(int nativeInstance,
+ boolean focused, boolean pressed, boolean invalidate);
private native void nativeResetSelection();
private native Point nativeSelectableText();
private native void nativeSelectAll();
@@ -9540,8 +9540,8 @@
private native void nativeReplaceBaseContent(int content);
private native void nativeCopyBaseContentToPicture(Picture pict);
private native boolean nativeHasContent();
- private native void nativeSetSelectionPointer(boolean set,
- float scale, int x, int y);
+ private native void nativeSetSelectionPointer(int nativeInstance,
+ boolean set, float scale, int x, int y);
private native boolean nativeStartSelection(int x, int y);
private native void nativeStopGL();
private native Rect nativeSubtractLayers(Rect content);
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index a5d6c9a..b24dd69 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -147,6 +147,11 @@
setColorFilter(tint);
}
+ int alpha = a.getInt(com.android.internal.R.styleable.ImageView_drawableAlpha, 255);
+ if (alpha != 255) {
+ setAlpha(alpha);
+ }
+
mCropToPadding = a.getBoolean(
com.android.internal.R.styleable.ImageView_cropToPadding, false);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 041e8a4..a21a087 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -7683,8 +7683,9 @@
}
}
- if (what instanceof UpdateAppearance ||
- what instanceof ParagraphStyle) {
+ if (what instanceof UpdateAppearance || what instanceof ParagraphStyle
+ || (what instanceof SuggestionSpan && (((SuggestionSpan)what).getFlags()
+ & SuggestionSpan.FLAG_AUTO_CORRECTION) != 0)) {
if (ims == null || ims.mBatchEditNesting == 0) {
invalidate();
mHighlightPathBogus = true;
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index bb23173..88d7e05 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -48,6 +48,13 @@
* <p>
* The easiest way to use this class is to call one of the static methods that constructs
* everything you need and returns a new Toast object.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For information about creating Toast notifications, read the
+ * <a href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Toast Notifications</a> developer
+ * guide.</p>
+ * </div>
*/
public class Toast {
static final String TAG = "Toast";
diff --git a/core/java/com/android/internal/policy/IFaceLockCallback.aidl b/core/java/com/android/internal/policy/IFaceLockCallback.aidl
index add3f1c..25adbb6 100644
--- a/core/java/com/android/internal/policy/IFaceLockCallback.aidl
+++ b/core/java/com/android/internal/policy/IFaceLockCallback.aidl
@@ -21,5 +21,6 @@
oneway interface IFaceLockCallback {
void unlock();
void cancel();
+ void reportFailedAttempt();
void pokeWakelock();
}
diff --git a/core/java/com/android/internal/policy/IFaceLockInterface.aidl b/core/java/com/android/internal/policy/IFaceLockInterface.aidl
index 921b8c7..3958cda 100644
--- a/core/java/com/android/internal/policy/IFaceLockInterface.aidl
+++ b/core/java/com/android/internal/policy/IFaceLockInterface.aidl
@@ -23,4 +23,5 @@
void startUi(IBinder containingWindowToken, int x, int y, int width, int height);
void stopUi();
void registerCallback(IFaceLockCallback cb);
+ void unregisterCallback(IFaceLockCallback cb);
}
diff --git a/core/java/com/android/internal/widget/LockScreenWidgetCallback.java b/core/java/com/android/internal/widget/LockScreenWidgetCallback.java
index d6403e9f..d7ad6c0 100644
--- a/core/java/com/android/internal/widget/LockScreenWidgetCallback.java
+++ b/core/java/com/android/internal/widget/LockScreenWidgetCallback.java
@@ -29,6 +29,9 @@
// Sends a message to lock screen requesting the view to be hidden.
public void requestHide(View self);
+ // Whether or not this view is currently visible on LockScreen
+ public boolean isVisible(View self);
+
// Sends a message to lock screen that user has interacted with widget. This should be used
// exclusively in response to user activity, i.e. user hits a button in the view.
public void userActivity(View self);
diff --git a/core/java/com/android/internal/widget/TransportControlView.java b/core/java/com/android/internal/widget/TransportControlView.java
index 73d9f10..63a3aa5 100644
--- a/core/java/com/android/internal/widget/TransportControlView.java
+++ b/core/java/com/android/internal/widget/TransportControlView.java
@@ -34,6 +34,8 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.os.SystemClock;
import android.text.Spannable;
@@ -61,7 +63,7 @@
private static final int MSG_SET_GENERATION_ID = 104;
private static final int MAXDIM = 512;
private static final int DISPLAY_TIMEOUT_MS = 5000; // 5s
- protected static final boolean DEBUG = true;
+ protected static final boolean DEBUG = false;
protected static final String TAG = "TransportControlView";
private ImageView mAlbumArt;
@@ -74,7 +76,7 @@
private boolean mAttached;
private PendingIntent mClientIntent;
private int mTransportControlFlags;
- private int mPlayState;
+ private int mCurrentPlayState;
private AudioManager mAudioManager;
private LockScreenWidgetCallback mWidgetCallbacks;
private IRemoteControlDisplayWeak mIRCD;
@@ -84,6 +86,11 @@
*/
private Bundle mPopulateMetadataWhenAttached = null;
+ /**
+ * Whether to clear the interface next time it is shown (i.e. the generation id changed)
+ */
+ private boolean mClearOnNextShow;
+
// This handler is required to ensure messages from IRCD are handled in sequence and on
// the UI thread.
private Handler mHandler = new Handler() {
@@ -113,15 +120,10 @@
break;
case MSG_SET_GENERATION_ID:
- if (mWidgetCallbacks != null) {
- boolean clearing = msg.arg2 != 0;
- if (DEBUG) Log.v(TAG, "New genId = " + msg.arg1 + ", clearing = " + clearing);
- if (!clearing) {
- mWidgetCallbacks.requestShow(TransportControlView.this);
- } else {
- mWidgetCallbacks.requestHide(TransportControlView.this);
- }
+ if (msg.arg2 != 0) {
+ mClearOnNextShow = true; // TODO: handle this
}
+ if (DEBUG) Log.v(TAG, "New genId = " + msg.arg1 + ", clearing = " + msg.arg2);
mClientGeneration = msg.arg1;
mClientIntent = (PendingIntent) msg.obj;
break;
@@ -195,6 +197,7 @@
super(context, attrs);
Log.v(TAG, "Create TCV " + this);
mAudioManager = new AudioManager(mContext);
+ mCurrentPlayState = RemoteControlClient.PLAYSTATE_NONE; // until we get a callback
mIRCD = new IRemoteControlDisplayWeak(mHandler);
}
@@ -319,7 +322,7 @@
| RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE
| RemoteControlClient.FLAG_KEY_MEDIA_STOP);
- updatePlayPauseState(mPlayState);
+ updatePlayPauseState(mCurrentPlayState);
}
private static void setVisibilityBasedOnFlag(View view, int flags, int flag) {
@@ -332,32 +335,99 @@
private void updatePlayPauseState(int state) {
if (DEBUG) Log.v(TAG,
- "updatePlayPauseState(), old=" + mPlayState + ", state=" + state);
- if (state == mPlayState) {
+ "updatePlayPauseState(), old=" + mCurrentPlayState + ", state=" + state);
+ if (state == mCurrentPlayState) {
return;
}
final int imageResId;
final int imageDescId;
+ boolean showIfHidden = false;
switch (state) {
+ case RemoteControlClient.PLAYSTATE_ERROR:
+ imageResId = com.android.internal.R.drawable.stat_sys_warning;
+ // TODO use more specific image description string for warning, but here the "play"
+ // message is still valid because this button triggers a play command.
+ imageDescId = com.android.internal.R.string.lockscreen_transport_play_description;
+ break;
+
case RemoteControlClient.PLAYSTATE_PLAYING:
imageResId = com.android.internal.R.drawable.ic_media_pause;
imageDescId = com.android.internal.R.string.lockscreen_transport_pause_description;
+ showIfHidden = true;
break;
case RemoteControlClient.PLAYSTATE_BUFFERING:
imageResId = com.android.internal.R.drawable.ic_media_stop;
imageDescId = com.android.internal.R.string.lockscreen_transport_stop_description;
+ showIfHidden = true;
break;
case RemoteControlClient.PLAYSTATE_PAUSED:
default:
imageResId = com.android.internal.R.drawable.ic_media_play;
imageDescId = com.android.internal.R.string.lockscreen_transport_play_description;
+ showIfHidden = false;
break;
}
mBtnPlay.setImageResource(imageResId);
mBtnPlay.setContentDescription(getResources().getString(imageDescId));
- mPlayState = state;
+ if (showIfHidden && mWidgetCallbacks != null && !mWidgetCallbacks.isVisible(this)) {
+ mWidgetCallbacks.requestShow(this);
+ }
+ mCurrentPlayState = state;
+ }
+
+ static class SavedState extends BaseSavedState {
+ boolean wasShowing;
+
+ SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ private SavedState(Parcel in) {
+ super(in);
+ this.wasShowing = in.readInt() != 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ super.writeToParcel(out, flags);
+ out.writeInt(this.wasShowing ? 1 : 0);
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR
+ = new Parcelable.Creator<SavedState>() {
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+
+ @Override
+ public Parcelable onSaveInstanceState() {
+ if (DEBUG) Log.v(TAG, "onSaveInstanceState()");
+ Parcelable superState = super.onSaveInstanceState();
+ SavedState ss = new SavedState(superState);
+ ss.wasShowing = mWidgetCallbacks.isVisible(this);
+ return ss;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ if (DEBUG) Log.v(TAG, "onRestoreInstanceState()");
+ if (!(state instanceof SavedState)) {
+ super.onRestoreInstanceState(state);
+ return;
+ }
+ SavedState ss = (SavedState) state;
+ super.onRestoreInstanceState(ss.getSuperState());
+ if (ss.wasShowing) {
+ mWidgetCallbacks.requestShow(this);
+ }
}
public void onClick(View v) {
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_dark.png
index 52a9800..a7b5cd6 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_light.png
index 49a2aeb..f96d123f 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_dark.png
index e6ebb43..b614b18 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_light.png
index 7069fc5..e4f72f6 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_focused_holo_dark.png
index ec2a7e3..7c1dd9d 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_focused_holo_light.png
index 486334f..0569e08 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_holo.png b/core/res/res/drawable-hdpi/btn_check_on_holo.png
index 1f11a78..3d9afa8 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_holo.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png
index a17100c..206e43f 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_holo_light.png
index 130ab4f..58103c8 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
index 96abcda..2ffe7a6 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
index 0a22f02..7a92c9a 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png b/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png
index 28b2578..e77921c 100644
--- a/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png
+++ b/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_dark.png
index 8906c4d..45a8d86 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_light.png
index 2bcb98e..94a0c12 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_dark.png
index 2e36821..70a6e90 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_light.png b/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_light.png
index 6a50bd8..4b76e28 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_off_focused_holo_dark.png
index 8595dd0..bc2f696 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_star_off_focused_holo_light.png
index 1dda090..6f83c05 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_normal_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_off_normal_holo_dark.png
index 942722e..86d42bb 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_normal_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_normal_holo_light.png b/core/res/res/drawable-hdpi/btn_star_off_normal_holo_light.png
index e46f035..9e3b006 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_normal_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_dark.png
index 5cfe146..1729228 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_light.png
index 20d0eb3..ff78fc5 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_dark.png
index 3b478d6..9a136d9 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_light.png
index 52a9f44..d49952b 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_dark.png
index 9810029..2014422 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_light.png b/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_light.png
index 445af7b..80885d1 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_on_focused_holo_dark.png
index d3884f6..35239da 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_star_on_focused_holo_light.png
index eea174a..09aecf4 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_normal_holo_light.png b/core/res/res/drawable-hdpi/btn_star_on_normal_holo_light.png
index 58b2b09..b667738 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_normal_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_dark.png
index a39a620..392f852 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_light.png
index 1ffe7fe..b36bc53 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/fastscroll_label_left_holo_dark.9.png b/core/res/res/drawable-hdpi/fastscroll_label_left_holo_dark.9.png
index 769cb12..e0f82606 100644
--- a/core/res/res/drawable-hdpi/fastscroll_label_left_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/fastscroll_label_left_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/fastscroll_label_left_holo_light.9.png b/core/res/res/drawable-hdpi/fastscroll_label_left_holo_light.9.png
index c5372a8..5fb6e96 100644
--- a/core/res/res/drawable-hdpi/fastscroll_label_left_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/fastscroll_label_left_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/fastscroll_label_right_holo_dark.9.png b/core/res/res/drawable-hdpi/fastscroll_label_right_holo_dark.9.png
index 1dee51b..8c80ea1 100644
--- a/core/res/res/drawable-hdpi/fastscroll_label_right_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/fastscroll_label_right_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/fastscroll_label_right_holo_light.9.png b/core/res/res/drawable-hdpi/fastscroll_label_right_holo_light.9.png
index 3c1e25a..80e1fba 100644
--- a/core/res/res/drawable-hdpi/fastscroll_label_right_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/fastscroll_label_right_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_bullet_key_permission.png b/core/res/res/drawable-hdpi/ic_bullet_key_permission.png
index a7eaec5..4b9bf53 100644
--- a/core/res/res/drawable-hdpi/ic_bullet_key_permission.png
+++ b/core/res/res/drawable-hdpi/ic_bullet_key_permission.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_answer_active.png b/core/res/res/drawable-hdpi/ic_lockscreen_answer_active.png
index 683a575..d2ced31 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_answer_active.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_answer_active.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_answer_focused.png b/core/res/res/drawable-hdpi/ic_lockscreen_answer_focused.png
index bdece9f..4ec4508 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_answer_focused.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_answer_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_answer_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_answer_normal.png
index 6a8ab24..7b8168c 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_answer_normal.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_answer_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_decline_focused.png b/core/res/res/drawable-hdpi/ic_lockscreen_decline_focused.png
index f2fceaa..22783c9 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_decline_focused.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_decline_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_decline_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_decline_normal.png
index e005ffc..c6a2e17 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_decline_normal.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_decline_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
index f41ad95..5805ce1 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
index 98ab6e9..6429517 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_silent_focused.png b/core/res/res/drawable-hdpi/ic_lockscreen_silent_focused.png
index 651b837..c995c87 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_silent_focused.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_silent_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_silent_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_silent_normal.png
index babab1d..c75363b 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_silent_normal.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_silent_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_soundon_focused.png b/core/res/res/drawable-hdpi/ic_lockscreen_soundon_focused.png
index d000866..69885ea 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_soundon_focused.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_soundon_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_soundon_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_soundon_normal.png
index 82133d0..8cf2b4b 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_soundon_normal.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_soundon_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_text_focusde.png b/core/res/res/drawable-hdpi/ic_lockscreen_text_focusde.png
index 26df6b2..60873dd7 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_text_focusde.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_text_focusde.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_unlock_activated.png b/core/res/res/drawable-hdpi/ic_lockscreen_unlock_activated.png
index 9e36918..374a62a 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_unlock_activated.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_unlock_activated.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_next.png b/core/res/res/drawable-hdpi/ic_media_next.png
index c74703e..f5ba824 100644
--- a/core/res/res/drawable-hdpi/ic_media_next.png
+++ b/core/res/res/drawable-hdpi/ic_media_next.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_previous.png b/core/res/res/drawable-hdpi/ic_media_previous.png
index 15dc390..40ecb00 100644
--- a/core/res/res/drawable-hdpi/ic_media_previous.png
+++ b/core/res/res/drawable-hdpi/ic_media_previous.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_holo.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_holo.png
index 28b2578..e77921c 100644
--- a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_holo.png
+++ b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green_holo.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green_holo.png
index 545cc09..b5e714a 100644
--- a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green_holo.png
+++ b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red_holo.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red_holo.png
index 9176b33..c659d94 100644
--- a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red_holo.png
+++ b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png b/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png
index f8092ea..05b1419 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_dark.png
index fb34a6d..9584649 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_light.png
index 87b2ad67..5c37873 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_dark.png
index 1655fea..b5faf6f 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_light.png
index 61cfe7a..041412b 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_dark.png
index 43e2e89..9ff4cce 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_light.png
index 7d80ff6..a556e00 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_dark.png
index cc21a1c..9353511 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_light.png
index cc21a1c..9353511 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_dark.png
index 3c9c192..2ca591f 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_light.png
index 6511cd2..1275a2f 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_dark.png
index 7b135ea..9c23a18 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_light.png
index 7b135ea..9c23a18 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_dark.png
index b6a85a2..159913c 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_light.png
index 50d979e..cfee4b7 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_dark.png
index 608dd52..e5f0430 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_light.png
index 96ff781..7e4ec4a 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_dark.png
index a48bf2e..df374c4 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_light.png
index b69589b..d6b9c67 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_dark.png
index 5adfb04..69474e3 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_light.png
index 5adfb04..69474e3 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_dark.png
index ff34463..a2fc32a 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_light.png
index 0bcfd67..c4b58b7 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_dark.png
index 00092cc..358a13f 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_light.png
index 00092cc..358a13f 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_away.png b/core/res/res/drawable-hdpi/presence_away.png
index fe5b880..455fec1 100644
--- a/core/res/res/drawable-hdpi/presence_away.png
+++ b/core/res/res/drawable-hdpi/presence_away.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_half_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_big_half_holo_dark.png
index e3131b1..c6d1cd1 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_half_holo_dark.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_half_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_half_holo_light.png b/core/res/res/drawable-hdpi/rate_star_big_half_holo_light.png
index cdc94a1..89afee8 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_half_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_off_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_big_off_holo_dark.png
index d83522a..58a2d40 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_off_holo_dark.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_off_holo_light.png b/core/res/res/drawable-hdpi/rate_star_big_off_holo_light.png
index 2af7814..fdbc011 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_off_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_on_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_big_on_holo_dark.png
index e4b766d..ec3394e 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_on_holo_dark.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_on_holo_light.png b/core/res/res/drawable-hdpi/rate_star_big_on_holo_light.png
index edd264a..3e90f35 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_on_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_half_holo_light.png b/core/res/res/drawable-hdpi/rate_star_med_half_holo_light.png
index 3ff3bbd..ae5e49b 100644
--- a/core/res/res/drawable-hdpi/rate_star_med_half_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_med_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_off_holo_light.png b/core/res/res/drawable-hdpi/rate_star_med_off_holo_light.png
index ce9fc25..73183ad 100644
--- a/core/res/res/drawable-hdpi/rate_star_med_off_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_med_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_on_holo_light.png b/core/res/res/drawable-hdpi/rate_star_med_on_holo_light.png
index a6fdcff..279427b 100644
--- a/core/res/res/drawable-hdpi/rate_star_med_on_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_med_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_half_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_small_half_holo_dark.png
index 4fb14f9..e0edec9 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_half_holo_dark.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_half_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_half_holo_light.png b/core/res/res/drawable-hdpi/rate_star_small_half_holo_light.png
index 667b8e2..d61b613 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_half_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_off_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_small_off_holo_dark.png
index e19cf7a..0bba5ba 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_off_holo_dark.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_off_holo_light.png b/core/res/res/drawable-hdpi/rate_star_small_off_holo_light.png
index 8886006..f8d978a 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_off_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_on_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_small_on_holo_dark.png
index bc5d3db..b7f8e62 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_on_holo_dark.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_on_holo_light.png b/core/res/res/drawable-hdpi/rate_star_small_on_holo_light.png
index 1041008..d8cdd19d7 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_on_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_focused_holo.png b/core/res/res/drawable-hdpi/scrubber_control_focused_holo.png
index 4048260..f830a03 100644
--- a/core/res/res/drawable-hdpi/scrubber_control_focused_holo.png
+++ b/core/res/res/drawable-hdpi/scrubber_control_focused_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_normal_holo.png b/core/res/res/drawable-hdpi/scrubber_control_normal_holo.png
index 90e9c9c..03f030b 100644
--- a/core/res/res/drawable-hdpi/scrubber_control_normal_holo.png
+++ b/core/res/res/drawable-hdpi/scrubber_control_normal_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_16_inner_holo.png b/core/res/res/drawable-hdpi/spinner_16_inner_holo.png
index 0166938..604490d 100644
--- a/core/res/res/drawable-hdpi/spinner_16_inner_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_16_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_20_inner_holo.png b/core/res/res/drawable-hdpi/spinner_20_inner_holo.png
index ffad720..2705a06 100644
--- a/core/res/res/drawable-hdpi/spinner_20_inner_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_20_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_20_outer_holo.png b/core/res/res/drawable-hdpi/spinner_20_outer_holo.png
index f2523f4..1954c8c 100644
--- a/core/res/res/drawable-hdpi/spinner_20_outer_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_20_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_48_inner_holo.png b/core/res/res/drawable-hdpi/spinner_48_inner_holo.png
index f8e3fef..df1573b 100644
--- a/core/res/res/drawable-hdpi/spinner_48_inner_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_48_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_48_outer_holo.png b/core/res/res/drawable-hdpi/spinner_48_outer_holo.png
index 04c5fb5..8dcdc17 100644
--- a/core/res/res/drawable-hdpi/spinner_48_outer_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_48_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_76_inner_holo.png b/core/res/res/drawable-hdpi/spinner_76_inner_holo.png
index a28a6d1..eff7117 100644
--- a/core/res/res/drawable-hdpi/spinner_76_inner_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_76_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_76_outer_holo.png b/core/res/res/drawable-hdpi/spinner_76_outer_holo.png
index 3d5aa46..50461b5 100644
--- a/core/res/res/drawable-hdpi/spinner_76_outer_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_76_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_call_mute.png b/core/res/res/drawable-hdpi/stat_notify_call_mute.png
index 1446fa7..7f87ee7 100644
--- a/core/res/res/drawable-hdpi/stat_notify_call_mute.png
+++ b/core/res/res/drawable-hdpi/stat_notify_call_mute.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim1.png b/core/res/res/drawable-hdpi/stat_sys_download_anim1.png
index 3e27c52..ff29bbf 100644
--- a/core/res/res/drawable-hdpi/stat_sys_download_anim1.png
+++ b/core/res/res/drawable-hdpi/stat_sys_download_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_speakerphone.png b/core/res/res/drawable-hdpi/stat_sys_speakerphone.png
index c63ca94..765be61 100644
--- a/core/res/res/drawable-hdpi/stat_sys_speakerphone.png
+++ b/core/res/res/drawable-hdpi/stat_sys_speakerphone.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_tether_wifi.png b/core/res/res/drawable-hdpi/stat_sys_tether_wifi.png
index 0b8dbf5..e0bd38b 100644
--- a/core/res/res/drawable-hdpi/stat_sys_tether_wifi.png
+++ b/core/res/res/drawable-hdpi/stat_sys_tether_wifi.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png
index 2754428..fff81d7 100644
--- a/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png
+++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim3.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim3.png
index 3590062..cabdc39 100644
--- a/core/res/res/drawable-hdpi/stat_sys_upload_anim3.png
+++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png b/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png
deleted file mode 100644
index ae77fa0..0000000
--- a/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png b/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png
deleted file mode 100644
index c6bdfcc..0000000
--- a/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_left.png b/core/res/res/drawable-hdpi/text_select_handle_left.png
index 5adc2e1..eead92c 100644
--- a/core/res/res/drawable-hdpi/text_select_handle_left.png
+++ b/core/res/res/drawable-hdpi/text_select_handle_left.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_middle.png b/core/res/res/drawable-hdpi/text_select_handle_middle.png
index b7a472a..185d839 100644
--- a/core/res/res/drawable-hdpi/text_select_handle_middle.png
+++ b/core/res/res/drawable-hdpi/text_select_handle_middle.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_right.png b/core/res/res/drawable-hdpi/text_select_handle_right.png
index cf94179..e9fceec 100644
--- a/core/res/res/drawable-hdpi/text_select_handle_right.png
+++ b/core/res/res/drawable-hdpi/text_select_handle_right.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_adb.png b/core/res/res/drawable-ldpi/stat_sys_adb.png
index aec8d90..86b945b 100644
--- a/core/res/res/drawable-ldpi/stat_sys_adb.png
+++ b/core/res/res/drawable-ldpi/stat_sys_adb.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_share_pack_holo_light.9.png b/core/res/res/drawable-mdpi/ab_share_pack_holo_light.9.png
index 1983c68..8f10bd5 100644
--- a/core/res/res/drawable-mdpi/ab_share_pack_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/ab_share_pack_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
index b70db89..9835b0f 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_code_lock_touched.png b/core/res/res/drawable-mdpi/btn_code_lock_touched.png
index 98a3b6d..2dfe0f6 100644
--- a/core/res/res/drawable-mdpi/btn_code_lock_touched.png
+++ b/core/res/res/drawable-mdpi/btn_code_lock_touched.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_focused_holo_light.png
index 816e146..26841bd 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_holo_light.png
index 4f4eff2..4fe7483 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_on_focused_holo_light.png
index afaa8ca..ec3b84d 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_normal_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_on_normal_holo_light.png
index b7d9079..537f4f0 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_normal_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_on_pressed_holo_light.png
index 994eb0c..0409d4b 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/fastscroll_label_left_holo_light.9.png b/core/res/res/drawable-mdpi/fastscroll_label_left_holo_light.9.png
index 987c097..cee85bb 100644
--- a/core/res/res/drawable-mdpi/fastscroll_label_left_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/fastscroll_label_left_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/fastscroll_label_right_holo_dark.9.png b/core/res/res/drawable-mdpi/fastscroll_label_right_holo_dark.9.png
index 8d87032..bd496f8 100644
--- a/core/res/res/drawable-mdpi/fastscroll_label_right_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/fastscroll_label_right_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_bullet_key_permission.png b/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
index 47913f6..22f25ca 100644
--- a/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
+++ b/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_next.png b/core/res/res/drawable-mdpi/ic_media_next.png
index a6feed0..acef506 100644
--- a/core/res/res/drawable-mdpi/ic_media_next.png
+++ b/core/res/res/drawable-mdpi/ic_media_next.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_previous.png b/core/res/res/drawable-mdpi/ic_media_previous.png
index 0163d0945..940d6a4 100644
--- a/core/res/res/drawable-mdpi/ic_media_previous.png
+++ b/core/res/res/drawable-mdpi/ic_media_previous.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_red_holo.png b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_red_holo.png
index 8434741..989e76b 100644
--- a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_red_holo.png
+++ b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_red_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png b/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png
index dbe3953..8ad0b32 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_dark.png
index 1f29da2..7d9637a 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_light.png
index a27f5aa..f7409e4 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_dark.png
index 34268af..9c2b833 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_dark.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_light.png
index 304f800..dcf2fb7 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_light.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_dark.png
index 583542b..b63c510d 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_light.png
index d15bd16..55312a1 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_dark.png
index 9a5d79f..48e300c 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_light.png
index 9a5d79f..48e300c 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_dark.png
index 8051d64..1558d3d 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_dark.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_light.png
index bcd34e9..6b6e7e1 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_light.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_dark.png
index cf4bdb6..081ea4e 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_light.png
index cf4bdb6..081ea4e 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_dark.png
index 0535ff7..739a8d7 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_light.png
index 360284d..bd440f2 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_dark.png
index 1e0e92c..cf856a1 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_dark.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_light.png
index 14bcce9..6665953 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_light.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_dark.png
index 6ed2cf0..d63d797 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_light.png
index 015a8cf..22b6dbd 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_dark.png
index 8bb44f2..4bcce98 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_light.png
index 8bb44f2..4bcce98 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_dark.png
index 6ab5f23..12ba823 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_dark.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_light.png
index 65ec302..d841f5a 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_light.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_dark.png
index 34d3228..0318c5f 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_light.png
index 34d3228..0318c5f 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_pressed_holo.png b/core/res/res/drawable-mdpi/scrubber_control_pressed_holo.png
index ba53c0b..cb99fa3 100644
--- a/core/res/res/drawable-mdpi/scrubber_control_pressed_holo.png
+++ b/core/res/res/drawable-mdpi/scrubber_control_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_call_mute.png b/core/res/res/drawable-mdpi/stat_notify_call_mute.png
index 8797a09..58e0cbc 100644
--- a/core/res/res/drawable-mdpi/stat_notify_call_mute.png
+++ b/core/res/res/drawable-mdpi/stat_notify_call_mute.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_speakerphone.png b/core/res/res/drawable-mdpi/stat_sys_speakerphone.png
index ec7ef0c..d82704e 100644
--- a/core/res/res/drawable-mdpi/stat_sys_speakerphone.png
+++ b/core/res/res/drawable-mdpi/stat_sys_speakerphone.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png b/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png
deleted file mode 100644
index ae77fa0..0000000
--- a/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png b/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png
deleted file mode 100644
index c6bdfcc..0000000
--- a/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-nodpi/indicator_code_lock_drag_direction_red_up.png b/core/res/res/drawable-nodpi/indicator_code_lock_drag_direction_red_up.png
new file mode 100644
index 0000000..cc46f19
--- /dev/null
+++ b/core/res/res/drawable-nodpi/indicator_code_lock_drag_direction_red_up.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/text_cursor_holo_dark.9.png b/core/res/res/drawable-nodpi/text_cursor_holo_dark.9.png
new file mode 100644
index 0000000..450c486
--- /dev/null
+++ b/core/res/res/drawable-nodpi/text_cursor_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/text_cursor_holo_light.9.png b/core/res/res/drawable-nodpi/text_cursor_holo_light.9.png
new file mode 100644
index 0000000..22633eb0
--- /dev/null
+++ b/core/res/res/drawable-nodpi/text_cursor_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-hdpi/stat_notify_call_mute.png b/core/res/res/drawable-sw600dp-hdpi/stat_notify_call_mute.png
new file mode 100644
index 0000000..b753764
--- /dev/null
+++ b/core/res/res/drawable-sw600dp-hdpi/stat_notify_call_mute.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-hdpi/stat_sys_speakerphone.png b/core/res/res/drawable-sw600dp-hdpi/stat_sys_speakerphone.png
new file mode 100644
index 0000000..b47a9f6
--- /dev/null
+++ b/core/res/res/drawable-sw600dp-hdpi/stat_sys_speakerphone.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-mdpi/stat_notify_call_mute.png b/core/res/res/drawable-sw600dp-mdpi/stat_notify_call_mute.png
new file mode 100644
index 0000000..951197c
--- /dev/null
+++ b/core/res/res/drawable-sw600dp-mdpi/stat_notify_call_mute.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-mdpi/stat_sys_speakerphone.png b/core/res/res/drawable-sw600dp-mdpi/stat_sys_speakerphone.png
new file mode 100644
index 0000000..5893db9
--- /dev/null
+++ b/core/res/res/drawable-sw600dp-mdpi/stat_sys_speakerphone.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-mdpi/unlock_halo.png b/core/res/res/drawable-sw600dp-mdpi/unlock_halo.png
index c9ed4c7..5ad26b8 100644
--- a/core/res/res/drawable-sw600dp-mdpi/unlock_halo.png
+++ b/core/res/res/drawable-sw600dp-mdpi/unlock_halo.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-xhdpi/stat_notify_call_mute.png b/core/res/res/drawable-sw600dp-xhdpi/stat_notify_call_mute.png
new file mode 100644
index 0000000..1d72243
--- /dev/null
+++ b/core/res/res/drawable-sw600dp-xhdpi/stat_notify_call_mute.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-xhdpi/stat_sys_speakerphone.png b/core/res/res/drawable-sw600dp-xhdpi/stat_sys_speakerphone.png
new file mode 100644
index 0000000..76dee9e
--- /dev/null
+++ b/core/res/res/drawable-sw600dp-xhdpi/stat_sys_speakerphone.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_dark.9.png b/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_dark.9.png
index 6e0244f..6a82a64 100644
--- a/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_bullet_key_permission.png b/core/res/res/drawable-xhdpi/ic_bullet_key_permission.png
index b2db65c..ccbdcc3 100644
--- a/core/res/res/drawable-xhdpi/ic_bullet_key_permission.png
+++ b/core/res/res/drawable-xhdpi/ic_bullet_key_permission.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_next.png b/core/res/res/drawable-xhdpi/ic_media_next.png
index 9835c63..726fee7 100644
--- a/core/res/res/drawable-xhdpi/ic_media_next.png
+++ b/core/res/res/drawable-xhdpi/ic_media_next.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_previous.png b/core/res/res/drawable-xhdpi/ic_media_previous.png
index 5df5987..59f994d 100644
--- a/core/res/res/drawable-xhdpi/ic_media_previous.png
+++ b/core/res/res/drawable-xhdpi/ic_media_previous.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_background_disabled.9.png b/core/res/res/drawable-xhdpi/list_selector_background_disabled.9.png
index 980bbd7..f039081 100644
--- a/core/res/res/drawable-xhdpi/list_selector_background_disabled.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_background_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_disabled.9.png b/core/res/res/drawable-xhdpi/numberpicker_down_disabled.9.png
index 62b267e..ec92ea5 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_disabled.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused.9.png b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused.9.png
index 5f38c35..03c020d 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused_holo_dark.png
index 1c2f33e..111f57e 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused_holo_light.png
index 4e688bc..d0ef05b 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_holo_dark.png
index dc422f2..ff21941 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_holo_light.png
index afc02db..3e9bdda 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_holo_light.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_focused_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_down_focused_holo_dark.png
index 3604013..0462fca 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_focused_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_down_focused_holo_light.png
index a16cd38..a488e8e 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_longpressed_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_down_longpressed_holo_dark.png
index b975b63..f61b076 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_longpressed_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_longpressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_longpressed_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_down_longpressed_holo_light.png
index b975b63..f61b076 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_longpressed_holo_light.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_longpressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_normal.9.png b/core/res/res/drawable-xhdpi/numberpicker_down_normal.9.png
index b1d3e7b..8637414 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_normal.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_normal_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_down_normal_holo_dark.png
index 39cdb93..211944e 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_normal_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_normal_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_down_normal_holo_light.png
index 2a14ac5..12bc11a 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_normal_holo_light.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_pressed.9.png b/core/res/res/drawable-xhdpi/numberpicker_down_pressed.9.png
index e61c469..bb56365 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_down_pressed_holo_dark.png
index 4827377..635184c 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_pressed_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_pressed_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_down_pressed_holo_light.png
index 4827377..635184c 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_pressed_holo_light.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_selected.9.png b/core/res/res/drawable-xhdpi/numberpicker_down_selected.9.png
index ed0c016..4a076f6 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_selected.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_input_disabled.9.png b/core/res/res/drawable-xhdpi/numberpicker_input_disabled.9.png
index 279087c..d176022 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_input_disabled.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_input_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_input_normal.9.png b/core/res/res/drawable-xhdpi/numberpicker_input_normal.9.png
index 1b3467a..dcacfcf 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_input_normal.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_input_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_input_pressed.9.png b/core/res/res/drawable-xhdpi/numberpicker_input_pressed.9.png
index 930415e..f8cb9e5 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_input_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_input_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_input_selected.9.png b/core/res/res/drawable-xhdpi/numberpicker_input_selected.9.png
index 5240d08..38c429f 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_input_selected.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_input_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_disabled.9.png b/core/res/res/drawable-xhdpi/numberpicker_up_disabled.9.png
index 4b79112..a1d8ae1 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_disabled.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused.9.png b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused.9.png
index 6c2f397..0256f32a 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused_holo_dark.png
index 97ea0b5..470e569 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused_holo_light.png
index e59e2a7..16df74d 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_holo_dark.png
index 3b8fa7f..edd4c04 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_holo_light.png
index 77a1dd4..d8f459a 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_holo_light.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_focused_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_up_focused_holo_dark.png
index 24c2d84..08bf241 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_focused_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_up_focused_holo_light.png
index b2566dc3..b2c40f1 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_longpressed_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_up_longpressed_holo_dark.png
index 7075af7..f4f7331 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_longpressed_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_longpressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_longpressed_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_up_longpressed_holo_light.png
index 7075af7..f4f7331 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_longpressed_holo_light.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_longpressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_normal.9.png b/core/res/res/drawable-xhdpi/numberpicker_up_normal.9.png
index 699a9f5..f6746a6 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_normal.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_normal_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_up_normal_holo_dark.png
index 11b60a9..83650b1 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_normal_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_normal_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_up_normal_holo_light.png
index 074fae5..78085d3 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_normal_holo_light.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_pressed.9.png b/core/res/res/drawable-xhdpi/numberpicker_up_pressed.9.png
index 5504fee..1071c73 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_up_pressed_holo_dark.png
index 2310f83..b8f6849 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_pressed_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_pressed_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_up_pressed_holo_light.png
index 2310f83..b8f6849 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_pressed_holo_light.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_selected.9.png b/core/res/res/drawable-xhdpi/numberpicker_up_selected.9.png
index 585cf30..f446d48 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_selected.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png
index 9afd52f..830aa27 100644
--- a/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png
+++ b/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_call_mute.png b/core/res/res/drawable-xhdpi/stat_notify_call_mute.png
index 4135fea..adbd7b1 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_call_mute.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_call_mute.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_speakerphone.png b/core/res/res/drawable-xhdpi/stat_sys_speakerphone.png
index 6938ab4..51e648c 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_speakerphone.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_speakerphone.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_cursor_holo_dark.9.png b/core/res/res/drawable-xhdpi/text_cursor_holo_dark.9.png
deleted file mode 100644
index e7bb0d4..0000000
--- a/core/res/res/drawable-xhdpi/text_cursor_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_cursor_holo_light.9.png b/core/res/res/drawable-xhdpi/text_cursor_holo_light.9.png
deleted file mode 100644
index f429785..0000000
--- a/core/res/res/drawable-xhdpi/text_cursor_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/layout/keyguard_transport_control.xml b/core/res/res/layout/keyguard_transport_control.xml
index 6e24ce2..c951c45 100644
--- a/core/res/res/layout/keyguard_transport_control.xml
+++ b/core/res/res/layout/keyguard_transport_control.xml
@@ -63,7 +63,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
- android:src="@drawable/ic_media_rew"
+ android:src="@drawable/ic_media_previous"
android:clickable="true"
android:background="?android:attr/selectableItemBackground"
android:padding="10dip"
@@ -94,7 +94,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:clickable="true"
- android:src="@drawable/ic_media_ff"
+ android:src="@drawable/ic_media_next"
android:background="?android:attr/selectableItemBackground"
android:padding="10dip"
android:contentDescription="@string/lockscreen_transport_next_description"/>
diff --git a/core/res/res/layout/status_bar_latest_event_content_large_icon.xml b/core/res/res/layout/status_bar_latest_event_content_large_icon.xml
index f3f1957..6e8c921 100644
--- a/core/res/res/layout/status_bar_latest_event_content_large_icon.xml
+++ b/core/res/res/layout/status_bar_latest_event_content_large_icon.xml
@@ -25,14 +25,12 @@
android:fadingEdge="horizontal"
android:ellipsize="marquee"
android:visibility="gone"
- android:alpha="0.7"
/>
<LinearLayout
android:id="@+id/line3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
- android:alpha="0.7"
>
<TextView android:id="@+id/text"
android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
@@ -62,6 +60,7 @@
android:scaleType="center"
android:paddingLeft="8dp"
android:visibility="gone"
+ android:drawableAlpha="180"
/>
</LinearLayout>
<ProgressBar
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 6c7a981..d7691f7 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2639,6 +2639,9 @@
<!-- The offset of the baseline within this view. See {see android.view.View#getBaseline}
for details -->
<attr name="baseline" format="dimension" />
+ <!-- @hide The alpha value (0-255) set on the ImageView's drawable. Equivalent
+ to calling ImageView.setAlpha(int), not the same as View.setAlpha(float). -->
+ <attr name="drawableAlpha" format="integer" />
</declare-styleable>
<declare-styleable name="ToggleButton">
<!-- The text for the button when it is checked. -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 20af731..e60e8b2 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -230,10 +230,11 @@
<style name="TextAppearance.StatusBar.Icon">
</style>
<style name="TextAppearance.StatusBar.EventContent">
- <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
<item name="android:textSize">13sp</item>
</style>
<style name="TextAppearance.StatusBar.EventContent.Title">
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:textSize">16sp</item>
<item name="android:textStyle">bold</item>
</style>
diff --git a/docs/html/index.jd b/docs/html/index.jd
index a8b61bf..d412993 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -129,15 +129,14 @@
'sdk': {
'layout':"imgLeft",
'icon':"sdk-small.png",
- 'name':"Android 3.2",
- 'img':"honeycomb-android.png",
- 'title':"Android 3.2 is here!",
- 'desc': "<p>Android 3.2 is a minor feature update that includes new APIs that allow you to "
-+ "better target your layouts for specific screen sizes and other miscellaneous new APIs.</p>"
+ 'name':"Android 4.0",
+ 'img':"ics-android.png",
+ 'title':"Ice Cream Sandwich!",
+ 'desc': "<br/><br/><br/><p>Oh my goodness, that looks tasty!</p>"
+/*
+ "<p>For more information about all the changes in Android 3.2, read the "
+ "<a href='{@docRoot}sdk/android-3.2.html'>version notes</a> and <a "
+ "href='{@docRoot}sdk/api_diff/13/changes.html'>diff report</a>.</p>"
-/*
+ "<p>If you have an existing SDK, add Android 3.0 as an "
+ "<a href='{@docRoot}sdk/adding-components.html'>SDK "
+ "component</a>. If you're new to Android, install the "
diff --git a/docs/html/offline.jd b/docs/html/offline.jd
index 1064a99..5f8e37ce 100644
--- a/docs/html/offline.jd
+++ b/docs/html/offline.jd
@@ -29,7 +29,7 @@
especially <a href="{@docRoot}resources/samples/ApiDemos/index.html">API Demos</a></li>
<li>Read the <a href="{@docRoot}guide/topics/fundamentals/index.html">Application
Fundamentals</a></li>
- <li>Read the <a href="{@docRoot}guide/developing/index.html">Overview</a> for using the SDK
+ <li>Read the <a href="{@docRoot}guide/developing/index.html">Introduction</a> for using the SDK
tools</li>
</ul>
</div>
@@ -44,9 +44,6 @@
<p>There's no additional setup.</p>
-<p>New Android platforms are saved in the <code><sdk>/platforms/</code> directory of
-your existing SDK and new add-ons are saved in the <code><sdk>/add-ons/</code> directory.</p>
-
<div class="note">
<p><strong>Note:</strong> You are currently viewing the offline version of the Android developer
diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js
index 3e673a5..310310e 100644
--- a/docs/html/resources/resources-data.js
+++ b/docs/html/resources/resources-data.js
@@ -419,16 +419,16 @@
},
{
tags: ['sample', 'new'],
- path: 'samples/AndroidBeam/index.html',
+ path: 'samples/AndroidBeamDemo/index.html',
title: {
- en: 'Android Beam'
+ en: 'Android Beam Demo'
},
description: {
en: 'An example of how to use the Android Beam feature to send messages between two Android-powered devices (API level 14 or later) that support NFC.'
}
},
{
- tags: ['sample', 'layout', 'ui'],
+ tags: ['sample', 'layout', 'ui', 'updated'],
path: 'samples/ApiDemos/index.html',
title: {
en: 'API Demos'
@@ -608,7 +608,7 @@
}
},
{
- tags: ['sample', 'accountsync'],
+ tags: ['sample', 'accountsync', 'updated'],
path: 'samples/SampleSyncAdapter/index.html',
title: {
en: 'SampleSyncAdapter'
diff --git a/docs/html/resources/samples/images/hcgallery-phone1.png b/docs/html/resources/samples/images/hcgallery-phone1.png
new file mode 100644
index 0000000..9f0c280
--- /dev/null
+++ b/docs/html/resources/samples/images/hcgallery-phone1.png
Binary files differ
diff --git a/docs/html/resources/samples/images/hcgallery-phone2.png b/docs/html/resources/samples/images/hcgallery-phone2.png
new file mode 100644
index 0000000..b049a65
--- /dev/null
+++ b/docs/html/resources/samples/images/hcgallery-phone2.png
Binary files differ
diff --git a/docs/html/sdk/android-4.0.jd b/docs/html/sdk/android-4.0.jd
index 619c907..9a9f02a 100644
--- a/docs/html/sdk/android-4.0.jd
+++ b/docs/html/sdk/android-4.0.jd
@@ -10,6 +10,7 @@
<ol>
<li><a href="#relnotes">Revisions</a></li>
<li><a href="#api">API Overview</a></li>
+ <li><a href="#Honeycomb">Previous APIs</a></li>
<li><a href="#api-diff">API Differences Report</a></li>
<li><a href="#api-level">API Level</a></li>
<li><a href="#apps">Built-in Applications</a></li>
@@ -45,14 +46,14 @@
Components</a>. If you are new to Android, <a
href="{@docRoot}sdk/index.html">download the SDK Starter Package</a> first.</p>
-<p>For a high-level introduction to the new user and developer features in Android 4.0, see the
-<a href="http://developer.android.com/sdk/android-4.0-highlights.html">Platform Highlights</a>.</p>
-
<p class="note"><strong>Reminder:</strong> If you've already published an
Android application, please test your application on Android {@sdkPlatformVersion} as
soon as possible to be sure your application provides the best
experience possible on the latest Android-powered devices.</p>
+<p>For a high-level introduction to the new user and developer features in Android 4.0, see the
+<a href="http://developer.android.com/sdk/android-4.0-highlights.html">Platform Highlights</a>.</p>
+
<h2 id="relnotes">Revisions</h2>
@@ -71,12 +72,7 @@
<div class="toggle-content-toggleme" style="padding-left:2em;">
<dl>
-<dt>Initial release. SDK Tools r14 or higher is required.
-<p class="note"><strong>Important:</strong> To download the new Android
-4.0 system components from the Android SDK Manager, you must first update the
-SDK tools to revision 14 and restart the Android SDK Manager. If you do not,
-the Android 4.0 system components will not be available for download.</p>
-</dt>
+<dt>Initial release. SDK Tools r14 or higher is recommended.</dt>
</dl>
</div>
@@ -97,21 +93,21 @@
<div class="toggle-content-toggleme" style="padding-left:2em;">
<ol class="toc" style="margin-left:-1em">
- <li><a href="#Contacts">Contacts</a></li>
- <li><a href="#Calendar">Calendar</a></li>
+ <li><a href="#Contacts">Contact Provider</a></li>
+ <li><a href="#Calendar">Calendar Provider</a></li>
+ <li><a href="#Voicemail">Voicemail Provider</a></li>
<li><a href="#Camera">Camera</a></li>
<li><a href="#Multimedia">Multimedia</a></li>
<li><a href="#Bluetooth">Bluetooth</a></li>
<li><a href="#AndroidBeam">Android Beam (NDEF Push with NFC)</a></li>
- <li><a href="#P2pWiFi">Peer-to-peer Wi-Fi</a></li>
- <li><a href="#NetworkData">Network Data</a></li>
- <li><a href="#Sensors">Device Sensors</a></li>
- <li><a href="#Renderscript">Renderscript</a></li>
+ <li><a href="#WiFiDirect">Wi-Fi Direct</a></li>
+ <li><a href="#NetworkUsage">Network Usage</a></li>
+ <li><a href="#RenderScript">RenderScript</a></li>
<li><a href="#A11y">Accessibility</a></li>
<li><a href="#Enterprise">Enterprise</a></li>
- <li><a href="#Voicemail">Voicemail</a></li>
- <li><a href="#SpellChecker">Spell Checker Services</a></li>
+ <li><a href="#Sensors">Device Sensors</a></li>
<li><a href="#TTS">Text-to-speech Engines</a></li>
+ <li><a href="#SpellChecker">Spell Checker Services</a></li>
<li><a href="#ActionBar">Action Bar</a></li>
<li><a href="#UI">User Interface and Views</a></li>
<li><a href="#Properties">Properties</a></li>
@@ -128,86 +124,95 @@
-<h3 id="Contacts">Contacts</h3>
+<h3 id="Contacts">Contact Provider</h3>
-<p>The Contact APIs that are defined by the {@link android.provider.ContactsContract} provider have
-been extended to support new features such as a personal profile for the device owner, large contact
-photos, and the ability for users to invite individual contacts to social networks that are
-installed on the device.</p>
+<p>The contact APIs that are defined by the {@link android.provider.ContactsContract} provider have
+been extended to support new features such as a personal profile for the device owner, high
+resolution contact photos, and the ability for users to invite individual contacts to social
+networks that are installed on the device.</p>
<h4>User Profile</h4>
<p>Android now includes a personal profile that represents the device owner, as defined by the
-{@link
-android.provider.ContactsContract.Profile} table. Social apps that maintain a user identity can
-contribute to the user's profile data by creating a new {@link
+{@link android.provider.ContactsContract.Profile} table. Social apps that maintain a user identity
+can contribute to the user's profile data by creating a new {@link
android.provider.ContactsContract.RawContacts} entry within the {@link
android.provider.ContactsContract.Profile}. That is, raw contacts that represent the device user do
not belong in the traditional raw contacts table defined by the {@link
android.provider.ContactsContract.RawContacts} Uri; instead, you must add a profile raw contact in
the table at {@link android.provider.ContactsContract.Profile#CONTENT_RAW_CONTACTS_URI}. Raw
-contacts in this table are then aggregated into the single user-visible profile information.</p>
+contacts in this table are then aggregated into the single user-visible profile labeled "Me".</p>
<p>Adding a new raw contact for the profile requires the {@link
android.Manifest.permission#WRITE_PROFILE} permission. Likewise, in order to read from the profile
table, you must request the {@link android.Manifest.permission#READ_PROFILE} permission. However,
-reading the user profile should not be required by most apps, even when contributing data to the
-profile. Reading the user profile is a sensitive permission and users will be very skeptical of apps
-that request reading their profile information.</p>
+most apps should need to read the user profile, even when contributing data to the
+profile. Reading the user profile is a sensitive permission and you should expect users to be
+skeptical of apps that request it.</p>
+
<h4>Large photos</h4>
<p>Android now supports high resolution photos for contacts. Now, when you push a photo into a
-contact
-record, the system processes it into both a 96x96 thumbnail (as it has previously) and a 256x256
-"display photo" stored in a new file-based photo store (the exact dimensions that the system chooses
-may vary in the future). You can add a large photo to a contact by putting a large photo in the
-usual {@link android.provider.ContactsContract.CommonDataKinds.Photo#PHOTO} column of a data row,
-which the system will then process into the appropriate thumbnail and display photo records.</p>
+contact record, the system processes it into both a 96x96 thumbnail (as it has previously) and a
+256x256 "display photo" that's stored in a new file-based photo store (the exact dimensions that the
+system chooses may vary in the future). You can add a large photo to a contact by putting a large
+photo in the usual {@link android.provider.ContactsContract.CommonDataKinds.Photo#PHOTO} column of a
+data row, which the system will then process into the appropriate thumbnail and display photo
+records.</p>
+
<h4>Invite Intent</h4>
-<p>The {@link android.provider.ContactsContract.Intents#INVITE_CONTACT} intent action allows you to
-invoke an action that indicates the user wants to add a contact to a social network that understand
-this intent and use it to invite the contact specified in the contact to that social network.</p>
+<p>The {@link android.provider.ContactsContract.Intents#INVITE_CONTACT} intent action allows an app
+to invoke an action that indicates the user wants to add a contact to a social network. The app
+receiving the app uses it to invite the specified contact to that
+social network. Most apps will be on the receiving-end of this operation. For example, the
+built-in People app invokes the invite intent when the user selects "Add connection" for a specific
+social app that's listed in a person's contact details.</p>
-<p>Apps that use a sync adapter to provide information about contacts can register with the system
-to
-receive the invite intent when there’s an opportunity for the user to “invite” a contact to the
-app’s social network (such as from a contact card in the People app). To receive the invite intent,
-you simply need to add the {@code inviteContactActivity} attribute to your app’s XML sync
-configuration file, providing a fully-qualified name of the activity that the system should start
-when the user wants to “invite” a contact in your social network. The activity that starts can then
-retrieve the URI for the contact in question from the intent’s data and perform the necessary work
-to
-invite that contact to the network or add the person to the user’s connections.</p>
+<p>To make your app visible as in the "Add connection" list, your app must provide a sync adapter to
+sync contact information from your social network. You must then indicate to the system that your
+app responds to the {@link android.provider.ContactsContract.Intents#INVITE_CONTACT} intent by
+adding the {@code inviteContactActivity} attribute to your app’s sync configuration file, with a
+fully-qualified name of the activity that the system should start when sending the invite intent.
+The activity that starts can then retrieve the URI for the contact in question from the intent’s
+data and perform the necessary work to invite that contact to the network or add the person to the
+user’s connections.</p>
+
+<p>See the <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">Sample Sync
+Adapter</a> app for an example (specifically, see the <a
+href="{@docRoot}resources/samples/SampleSyncAdapter/res/xml-v14/contacts.html">contacts.xml</a>
+file).</p>
+
<h4>Contact Usage Feedback</h4>
<p>The new {@link android.provider.ContactsContract.DataUsageFeedback} APIs allow you to help track
how often the user uses particular methods of contacting people, such as how often the user uses
each phone number or e-mail address. This information helps improve the ranking for each contact
-method associated with each person and provide such contact methods as suggestions.</p>
+method associated with each person and provide better suggestions for contacting each person.</p>
-<h3 id="Calendar">Calendar</h3>
+<h3 id="Calendar">Calendar Provider</h3>
-<p>The new calendar API allows you to access and modify the user’s calendars and events. The
-calendar
-APIs are provided with the {@link android.provider.CalendarContract} provider. Using the calendar
-provider, you can:</p>
-<ul>
-<li>Read, write, and modify calendars.</li>
-<li>Add and modify events, attendees, reminders, and alarms.</li>
-</ul>
+<p>The new calendar APIs allow you to read, add, modify and delete calendars, events, attendees,
+reminders and alerts, which are stored in the Calendar Provider.</p>
-<p>{@link android.provider.CalendarContract} defines the data model of calendar and event-related
-information. All of the user’s calendar data is stored in a number of tables defined by subclasses
-of {@link android.provider.CalendarContract}:</p>
+<p>A variety of apps and widgets can use these APIs to read and modify calendar events. However,
+some of the most compelling use cases are sync adapters that synchronize the user's calendar from
+other calendar services with the Calendar Provider, in order to offer a unified location for all the
+user's events. Google Calendar events, for example, are synchronized with the Calendar Provider by
+the Google Calendar Sync Adapter, allowing these events to be viewed with Android's built-in
+Calendar app.</p>
+
+<p>The data model for calendars and event-related information in the Calendar Provider is
+defined by {@link android.provider.CalendarContract}. All the user’s calendar data is stored in a
+number of tables defined by various subclasses of {@link android.provider.CalendarContract}:</p>
<ul>
<li>The {@link android.provider.CalendarContract.Calendars} table holds the calendar-specific
@@ -215,11 +220,10 @@
color, sync information, and so on.</li>
<li>The {@link android.provider.CalendarContract.Events} table holds event-specific information.
-Each
-row in this table has the information for a single event. It contains information such as event
-title, location, start time, end time, and so on. The event can occur one-time or can recur multiple
-times. Attendees, reminders, and extended properties are stored in separate tables and reference the
-event’s _ID to link them with the event.</li>
+Each row in this table contains the information for a single event, such as the
+event title, location, start time, end time, and so on. The event can occur one time or recur
+multiple times. Attendees, reminders, and extended properties are stored in separate tables and
+use the event’s {@code _ID} to link them with the event.</li>
<li>The {@link android.provider.CalendarContract.Instances} table holds the start and end time for
occurrences of an event. Each row in this table represents a single occurrence. For one-time events
@@ -228,47 +232,93 @@
<li>The {@link android.provider.CalendarContract.Attendees} table holds the event attendee or guest
information. Each row represents a single guest of an event. It specifies the type of guest the
-person is and the person’s attendance response for the event.</li>
+person is and the person’s response for the event.</li>
<li>The {@link android.provider.CalendarContract.Reminders} table holds the alert/notification data.
Each row represents a single alert for an event. An event can have multiple reminders. The number of
-reminders per event is specified in MAX_REMINDERS, which is set by the Sync Adapter that owns the
-given calendar. Reminders are specified in minutes before the event and have a type.</li>
+reminders per event is specified in {@code MAX_REMINDERS}, which is set by the sync adapter that
+owns the given calendar. Reminders are specified in number-of-minutes before the event is
+scheduled and specify an alarm method such as to use an alert, email, or SMS to remind
+the user.</li>
<li>The {@link android.provider.CalendarContract.ExtendedProperties} table hold opaque data fields
-used
-by the sync adapter. The provider takes no action with items in this table except to delete them
-when their related events are deleted.</li>
+used by the sync adapter. The provider takes no action with items in this table except to delete
+them when their related events are deleted.</li>
</ul>
-<p>To access a user’s calendar data with the calendar provider, your application must request
-permission from the user by declaring <uses-permission
-android:name="android.permission.READ_CALENDAR" /> (for read access) and <uses-permission
-android:name="android.permission.WRITE_CALENDAR" /> (for write access) in their manifest files.</p>
+<p>To access a user’s calendar data with the Calendar Provider, your application must request
+the {@link android.Manifest.permission#READ_CALENDAR} permission (for read access) and
+{@link android.Manifest.permission#WRITE_CALENDAR} (for write access).</p>
-<p>However, if all you want to do is add an event to the user’s calendar, you can instead use an
-INSERT
-{@link android.content.Intent} to start an activity in the Calendar app that creates new events.
-Using the intent does not require the WRITE_CALENDAR permission and you can specify the {@link
-android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME} and {@link
-android.provider.CalendarContract#EXTRA_EVENT_END_TIME} extra fields to pre-populate the form with
-the time of the event. The values for these times must be in milliseconds from the epoch. You must
-also specify {@code “vnd.android.cursor.item/event”} as the intent type.</p>
+<h4>Event intent</h4>
+
+<p>If all you want to do is add an event to the user’s calendar, you can use an
+{@link android.content.Intent#ACTION_INSERT} intent with a {@code "vnd.android.cursor.item/event"}
+MIME type to start an activity in the Calendar app that creates new events. Using the intent does
+not require any permission and you can specify event details with the following extras:</p>
+
+<ul>
+ <li>{@link android.provider.CalendarContract.EventsColumns#TITLE Events.TITLE}: Name for the
+event</li>
+ <li>{@link
+android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME}:
+Event begin time in milliseconds from the
+epoch</li>
+ <li>{@link
+android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME}: Event
+end time in milliseconds from the epoch</li>
+ <li>{@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION Events.EVENT_LOCATION}:
+Location of the event</li>
+ <li>{@link android.provider.CalendarContract.EventsColumns#DESCRIPTION Events.DESCRIPTION}: Event
+description</li>
+ <li>{@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL}: Email addresses of those to
+invite</li>
+ <li>{@link android.provider.CalendarContract.EventsColumns#RRULE Events.RRULE}: The recurrence
+rule for the event</li>
+ <li>{@link android.provider.CalendarContract.EventsColumns#ACCESS_LEVEL Events.ACCESS_LEVEL}:
+Whether the event is private or public</li>
+ <li>{@link android.provider.CalendarContract.EventsColumns#AVAILABILITY Events.AVAILABILITY}:
+Whether the time period of this event allows for other events to be scheduled at the same time</li>
+</ul>
+
+
+
+
+<h3 id="Voicemail">Voicemail Provider</h3>
+
+<p>The new voicemail APIs allows applications to add voicemails to a content provider on the device.
+Because the APIs currently do not allow third party apps to read all the voicemails from the system,
+the only third-party apps that should use the voicemail APIs are those that have voicemail to
+deliver to the user. For instance, it’s possible that a user has multiple voicemail sources, such as
+one provided by the phone’s service provider and others from VoIP or other alternative voice
+services. These apps can use the APIs to add their voicemails to the system for quick playback. The
+built-in Phone application presents all voicemails from the Voicemail Provider with a single list.
+Although the system’s Phone application is the only application that can read all the voicemails,
+each application that provides voicemails can read those that it has added to the system (but cannot
+read voicemails from other services).</p>
+
+<p>The {@link android.provider.VoicemailContract} class defines the content provider for the
+voicemail APIs. The subclasses {@link android.provider.VoicemailContract.Voicemails} and {@link
+android.provider.VoicemailContract.Status} provide tables in which the Voicemail Providers can
+insert voicemail data for storage on the device. For an example of a voicemail provider app, see the
+<a href="{@docRoot}resources/samples/VoicemailProviderDemo/index.html">Voicemail Provider
+Demo</a>.</p>
<h3 id="Camera">Camera</h3>
-<p>The {@link android.hardware.Camera} APIs now support face detection and control for metering and
-focus areas.</p>
+<p>The {@link android.hardware.Camera} class now includes APIs for detecting faces and controlling
+focus and metering areas.</p>
-<h4>Face Detection</h4>
-<p>Camera apps can now enhance their abilities with Android’s face detection software, which not
-only
-detects the face of a subject, but also specific facial features, such as the eyes and mouth. </p>
+<h4>Face detection</h4>
+
+<p>Camera apps can now enhance their abilities with Android’s face detection APIs, which not
+only detect the face of a subject, but also specific facial features, such as the eyes and mouth.
+</p>
<p>To detect faces in your camera application, you must register a {@link
android.hardware.Camera.FaceDetectionListener} by calling {@link
@@ -276,41 +326,44 @@
your camera surface and start detecting faces by calling {@link
android.hardware.Camera#startFaceDetection}.</p>
-<p>When the system detects a face, it calls the {@link
+<p>When the system detects one or more faces in the camera scene, it calls the {@link
android.hardware.Camera.FaceDetectionListener#onFaceDetection onFaceDetection()} callback in your
implementation of {@link android.hardware.Camera.FaceDetectionListener}, including an array of
{@link android.hardware.Camera.Face} objects.</p>
<p>An instance of the {@link android.hardware.Camera.Face} class provides various information about
-the
-face detected by the camera, including:</p>
+the face detected, including:</p>
<ul>
<li>A {@link android.graphics.Rect} that specifies the bounds of the face, relative to the camera's
current field of view</li>
-<li>An integer betwen 0 and 100 that indicates how confident the system is that the object is a
-human
-face</li>
+<li>An integer betwen 1 and 100 that indicates how confident the system is that the object is a
+human face</li>
<li>A unique ID so you can track multiple faces</li>
<li>Several {@link android.graphics.Point} objects that indicate where the eyes and mouth are
located</li>
</ul>
+<p class="note"><strong>Note:</strong> Face detection may not be supported on some
+devices, so you should check by calling {@link
+android.hardware.Camera.Parameters#getMaxNumDetectedFaces()} and ensure the return
+value is greater than zero. Also, some devices may not support identification of eyes and mouth,
+in which case, those fields in the {@link android.hardware.Camera.Face} object will be null.</p>
-<h4>Focus and Metering Areas</h4>
+
+<h4>Focus and metering areas</h4>
-<p>Camera apps can now control the areas that the camera uses for focus and when metering white
+<p>Camera apps can now control the areas that the camera uses for focus and for metering white
balance
-and auto-exposure (when supported by the hardware). Both features use the new {@link
-android.hardware.Camera.Area} class to specify the region of the camera’s current view that should
-be focused or metered. An instance of the {@link android.hardware.Camera.Area} class defines the
-bounds of the area with a {@link android.graphics.Rect} and the weight of the
-area—representing the level of importance of that area, relative to other areas in
-consideration—with an integer.</p>
+and auto-exposure. Both features use the new {@link android.hardware.Camera.Area} class to specify
+the region of the camera’s current view that should be focused or metered. An instance of the {@link
+android.hardware.Camera.Area} class defines the bounds of the area with a {@link
+android.graphics.Rect} and the area's weight—representing the level of importance of that
+area, relative to other areas in consideration—with an integer.</p>
<p>Before setting either a focus area or metering area, you should first call {@link
android.hardware.Camera.Parameters#getMaxNumFocusAreas} or {@link
android.hardware.Camera.Parameters#getMaxNumMeteringAreas}, respectively. If these return zero, then
-the device does not support the respective feature. </p>
+the device does not support the corresponding feature.</p>
<p>To specify the focus or metering areas to use, simply call {@link
android.hardware.Camera.Parameters#setFocusAreas setFocusAreas()} or {@link
@@ -318,33 +371,53 @@
java.util.List} of {@link android.hardware.Camera.Area} objects that indicate the areas to consider
for focus or metering. For example, you might implement a feature that allows the user to set the
focus area by touching an area of the preview, which you then translate to an {@link
-android.hardware.Camera.Area} object and set the focus to that spot. The focus or exposure in that
-area will continually update as the scene in the area changes.</p>
+android.hardware.Camera.Area} object and request that the camera focus on that area of the scene.
+The focus or exposure in that area will continually update as the scene in the area changes.</p>
-<h4>Other Camera Features</h4>
-<ul>
-<li>Capture photos during video recording
-While recording video, you can now call {@link android.hardware.Camera#takePicture takePicture()} to
-save a photo without interrupting the video session. Before doing so, you should call {@link
-android.hardware.Camera.Parameters#isVideoSnapshotSupported} to be sure the hardware supports
-it.</li>
+<h4>Continuous auto focus for photos</h4>
-<li>Lock auto exposure and white balance with {@link
+<p>You can now enable continuous auto focusing (CAF) when taking photos. To enable CAF in your
+camera app, pass {@link android.hardware.Camera.Parameters#FOCUS_MODE_CONTINUOUS_PICTURE}
+to {@link android.hardware.Camera.Parameters#setFocusMode setFocusMode()}. When ready to capture
+a photo, call {@link android.hardware.Camera#autoFocus autoFocus()}. Your {@link
+android.hardware.Camera.AutoFocusCallback} immediately receives a callback to indicate whether
+focus was acheived. To resume CAF after receiving the callback, you must call {@link
+android.hardware.Camera#cancelAutoFocus()}.</p>
+
+<p class="note"><strong>Note:</strong> Continuous auto focus is also supported when capturing
+video, using {@link android.hardware.Camera.Parameters#FOCUS_MODE_CONTINUOUS_VIDEO}, which was
+added in API level 9.</p>
+
+
+<h4>Other camera features</h4>
+
+<ul>
+<li>While recording video, you can now call {@link android.hardware.Camera#takePicture
+takePicture()} to save a photo without interrupting the video session. Before doing so, you should
+call {@link android.hardware.Camera.Parameters#isVideoSnapshotSupported} to be sure the hardware
+supports it.</li>
+
+<li>You can now lock auto exposure and white balance with {@link
android.hardware.Camera.Parameters#setAutoExposureLock setAutoExposureLock()} and {@link
-android.hardware.Camera.Parameters#setAutoWhiteBalanceLock setAutoWhiteBalanceLock()}, to prevent
+android.hardware.Camera.Parameters#setAutoWhiteBalanceLock setAutoWhiteBalanceLock()} to prevent
these properties from changing.</li>
+
+<li>You can now call {@link android.hardware.Camera#setDisplayOrientation
+setDisplayOrientation()} while the camera preview is running. Previously, you could call this
+only before beginning the preview, but you can now change the orientation at any time.</li>
</ul>
-<h4>Camera Broadcast Intents</h4>
+
+<h4>Camera broadcast intents</h4>
<ul>
-<li>{@link android.hardware.Camera#ACTION_NEW_PICTURE Camera.ACTION_NEW_PICTURE}
-This indicates that the user has captured a new photo. The built-in camera app invokes this
+<li>{@link android.hardware.Camera#ACTION_NEW_PICTURE Camera.ACTION_NEW_PICTURE}:
+This indicates that the user has captured a new photo. The built-in Camera app invokes this
broadcast after a photo is captured and third-party camera apps should also broadcast this intent
after capturing a photo.</li>
-<li>{@link android.hardware.Camera#ACTION_NEW_VIDEO Camera.ACTION_NEW_VIDEO}
-This indicates that the user has captured a new video. The built-in camera app invokes this
+<li>{@link android.hardware.Camera#ACTION_NEW_VIDEO Camera.ACTION_NEW_VIDEO}:
+This indicates that the user has captured a new video. The built-in Camera app invokes this
broadcast after a video is recorded and third-party camera apps should also broadcast this intent
after capturing a video.</li>
</ul>
@@ -356,25 +429,29 @@
<h3 id="Multimedia">Multimedia</h3>
<p>Android 4.0 adds several new APIs for applications that interact with media such as photos,
-videos,
-and music.</p>
+videos, and music.</p>
-<h4>Media Player</h4>
+<h4>Media player</h4>
<ul>
-<li>Streaming online media from {@link android.media.MediaPlayer} now requires {@link
+<li>Streaming online media from {@link android.media.MediaPlayer} now requires the {@link
android.Manifest.permission#INTERNET} permission. If you use {@link android.media.MediaPlayer} to
-play content from the internet, be sure to add the {@link android.Manifest.permission#INTERNET}
-permission or else your media playback will not work beginning with Android 4.0.</li>
+play content from the Internet, be sure to add the {@link android.Manifest.permission#INTERNET}
+permission to your manifest or else your media playback will not work beginning with Android
+4.0.</li>
+
<li>{@link android.media.MediaPlayer#setSurface(Surface) setSurface()} allows you define a {@link
android.view.Surface} to behave as the video sink.</li>
+
<li>{@link android.media.MediaPlayer#setDataSource(Context,Uri,Map) setDataSource()} allows you to
send additional HTTP headers with your request, which can be useful for HTTP(S) live streaming</li>
+
<li>HTTP(S) live streaming now respects HTTP cookies across requests</li>
</ul>
-<h4>Media Type Support</h4>
+
+<h4>Media types</h4>
<p>Android 4.0 adds support for:</p>
<ul>
@@ -383,20 +460,21 @@
<li>WEBP images</li>
<li>Matroska video</li>
</ul>
-<p>For more info, see <a href=”{@docRoot}guide/appendix/media-formats.html”>Supported Media
+<p>For more info, see <a href="{@docRoot}guide/appendix/media-formats.html">Supported Media
Formats</a>.</p>
-<h4>Remote Control Client</h4>
+
+<h4>Remote control client</h4>
<p>The new {@link android.media.RemoteControlClient} allows media players to enable playback
-controls
-from remote control clients such as the device lock screen. Media players can also expose
+controls from remote control clients such as the device lock screen. Media players can also expose
information about the media currently playing for display on the remote control, such as track
information and album art.</p>
<p>To enable remote control clients for your media player, instantiate a {@link
-android.media.RemoteControlClient} with a {@link android.app.PendingIntent} that broadcasts {@link
+android.media.RemoteControlClient} with its constructor, passing it a {@link
+android.app.PendingIntent} that broadcasts {@link
android.content.Intent#ACTION_MEDIA_BUTTON}. The intent must also declare the explicit {@link
android.content.BroadcastReceiver} component in your app that handles the {@link
android.content.Intent#ACTION_MEDIA_BUTTON} event.</p>
@@ -423,22 +501,20 @@
android.media.MediaMetadataRetriever}.</p>
<p>For a sample implementation, see the <a
-href=”{@docRoot}resources/samples/RandomMusicPlayer/index.html”>Random Music Player</a>, which
-provides compatibility logic such that it enables the remote control client while continuing to
-support Android 2.1 devices.</p>
+href="{@docRoot}resources/samples/RandomMusicPlayer/index.html">Random Music Player</a>, which
+provides compatibility logic such that it enables the remote control client on Android 4.0
+devices while continuing to support devices back to Android 2.1.</p>
<h4>Media Effects</h4>
<p>A new media effects framework allows you to apply a variety of visual effects to images and
-videos.
-The system performs all effects processing on the GPU to obtain maximum performance. Applications in
-Android 4.0 such as Google Talk or the Gallery editor make use of the effects API to apply real-time
-effects to video and photos.</p>
+videos. For example, image effects allow you to easily fix red-eye, convert an image to grayscale,
+adjust brightness, adjust saturation, rotate an image, apply a fisheye effect, and much more. The
+system performs all effects processing on the GPU to obtain maximum performance.</p>
<p>For maximum performance, effects are applied directly to OpenGL textures, so your application
-must
-have a valid OpenGL context before it can use the effects APIs. The textures to which you apply
+must have a valid OpenGL context before it can use the effects APIs. The textures to which you apply
effects may be from bitmaps, videos or even the camera. However, there are certain restrictions that
textures must meet:</p>
<ol>
@@ -447,8 +523,7 @@
</ol>
<p>An {@link android.media.effect.Effect} object defines a single media effect that you can apply to
-an
-image frame. The basic workflow to create an {@link android.media.effect.Effect} is:</p>
+an image frame. The basic workflow to create an {@link android.media.effect.Effect} is:</p>
<ol>
<li>Call {@link android.media.effect.EffectContext#createWithCurrentGlContext
@@ -457,17 +532,15 @@
android.media.effect.EffectContext#getFactory EffectContext.getFactory()}, which returns an instance
of {@link android.media.effect.EffectFactory}.</li>
<li>Call {@link android.media.effect.EffectFactory#createEffect createEffect()}, passing it an
-effect
-name from @link android.media.effect.EffectFactory}, such as {@link
+effect name from @link android.media.effect.EffectFactory}, such as {@link
android.media.effect.EffectFactory#EFFECT_FISHEYE} or {@link
android.media.effect.EffectFactory#EFFECT_VIGNETTE}.</li>
</ol>
<p>Not all devices support all effects, so you must first check if the desired effect is supported
-by
-calling {@link android.media.effect.EffectFactory#isEffectSupported isEffectSupported()}.</p>
+by calling {@link android.media.effect.EffectFactory#isEffectSupported isEffectSupported()}.</p>
-<p>You can adjust the effect’s parameters by calling {@link android.media.effect.Effect#setParameter
+<p>You can adjust an effect’s parameters by calling {@link android.media.effect.Effect#setParameter
setParameter()} and passing a parameter name and parameter value. Each type of effect accepts
different parameters, which are documented with the effect name. For example, {@link
android.media.effect.EffectFactory#EFFECT_FISHEYE} has one parameter for the {@code scale} of the
@@ -480,8 +553,8 @@
image (usually done by calling the {@link android.opengl.GLES20#glTexImage2D glTexImage2D()}
function). You may provide multiple mipmap levels. If the output texture has not been bound to a
texture image, it will be automatically bound by the effect as a {@link
-android.opengl.GLES20#GL_TEXTURE_2D}. It will contain one mipmap level (0), which will have the same
-size as the input.</p>
+android.opengl.GLES20#GL_TEXTURE_2D} and with one mipmap level (0), which will have the same
+size as the input.</p>
@@ -501,7 +574,7 @@
android.bluetooth.BluetoothProfile#HEALTH} profile type to establish a connection with the profile
proxy object.</p>
-<p>Once you’ve acquired the Health profile proxy (the {@link android.bluetooth.BluetoothHealth}
+<p>Once you’ve acquired the Health Profile proxy (the {@link android.bluetooth.BluetoothHealth}
object), connecting to and communicating with paired health devices involves the following new
Bluetooth classes:</p>
<ul>
@@ -515,15 +588,15 @@
android.bluetooth.BluetoothHealth} APIs.</li>
</ul>
-<p>For more information about using the Bluetooth Health profile, see the documentation for {@link
+<p>For more information about using the Bluetooth Health Profile, see the documentation for {@link
android.bluetooth.BluetoothHealth}.</p>
+
<h3 id="AndroidBeam">Android Beam (NDEF Push with NFC)</h3>
-<p>Android Beam allows you to send NDEF messages (an NFC standard for data stored on NFC tags) from
-one
-device to another (a process also known as “NDEF Push”). The data transfer is initiated when two
+<p>Android Beam is a new NFC feature that allows you to send NDEF messages from one device to
+another (a process also known as “NDEF Push"). The data transfer is initiated when two
Android-powered devices that support Android Beam are in close proximity (about 4 cm), usually with
their backs touching. The data inside the NDEF message can contain any data that you wish to share
between devices. For example, the People app shares contacts, YouTube shares videos, and Browser
@@ -531,29 +604,30 @@
<p>To transmit data between devices using Android Beam, you need to create an {@link
android.nfc.NdefMessage} that contains the information you want to share while your activity is in
-the foreground. You must then pass the
-{@link android.nfc.NdefMessage} to the system in one of two ways:</p>
+the foreground. You must then pass the {@link android.nfc.NdefMessage} to the system in one of two
+ways:</p>
<ul>
-<li>Define a single {@link android.nfc.NdefMessage} to use from the activity:
+<li>Define a single {@link android.nfc.NdefMessage} to push while in the activity:
<p>Call {@link android.nfc.NfcAdapter#setNdefPushMessage setNdefPushMessage()} at any time to set
-the
-message you want to send. For instance, you might call this method and pass it your {@link
+the message you want to send. For instance, you might call this method and pass it your {@link
android.nfc.NdefMessage} during your activity’s {@link android.app.Activity#onCreate onCreate()}
-method. Then, whenever Android Beam is activated with another device while your activity is in the
-foreground, the system sends that {@link android.nfc.NdefMessage} to the other device.</p></li>
+method. Then, whenever Android Beam is activated with another device while the activity is in the
+foreground, the system sends the {@link android.nfc.NdefMessage} to the other device.</p></li>
-<li>Define the {@link android.nfc.NdefMessage} depending on the current context:
-<p>Implement {@link android.nfc.NfcAdapter.CreateNdefMessageCallback}, in which the {@link
-android.nfc.NfcAdapter.CreateNdefMessageCallback#createNdefMessage createNdefMessage()} callback
+<li>Define the {@link android.nfc.NdefMessage} to push at the time that Android Beam is initiated:
+<p>Implement {@link android.nfc.NfcAdapter.CreateNdefMessageCallback}, in which your
+implementation of the {@link
+android.nfc.NfcAdapter.CreateNdefMessageCallback#createNdefMessage createNdefMessage()}
method returns the {@link android.nfc.NdefMessage} you want to send. Then pass the {@link
-android.nfc.NfcAdapter.CreateNdefMessageCallback} to {@link
-android.nfc.NfcAdapter#setNdefPushMessageCallback setNdefPushMessageCallback()}. In this case, when
-Android Beam is activated with another device while your activity is in the foreground, the system
-calls {@link android.nfc.NfcAdapter.CreateNdefMessageCallback#createNdefMessage createNdefMessage()}
-to retrieve the {@link android.nfc.NdefMessage} you want to send. This allows you to create a
-different {@link android.nfc.NdefMessage} for each occurrence, depending on the user context (such
-as which contact in the People app is currently visible).</p></li>
+android.nfc.NfcAdapter.CreateNdefMessageCallback} implementation to {@link
+android.nfc.NfcAdapter#setNdefPushMessageCallback setNdefPushMessageCallback()}.</p>
+<p>In this case, when Android Beam is activated with another device while your activity is in the
+foreground, the system calls {@link
+android.nfc.NfcAdapter.CreateNdefMessageCallback#createNdefMessage createNdefMessage()} to retrieve
+the {@link android.nfc.NdefMessage} you want to send. This allows you to define the {@link
+android.nfc.NdefMessage} to deliver only once Android Beam is initiated, in case the contents
+of the message might vary throughout the life of the activity.</p></li>
</ul>
<p>In case you want to run some specific code once the system has successfully delivered your NDEF
@@ -567,9 +641,9 @@
tags. The system invokes an intent with the {@link android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED}
action to start an activity, with either a URL or a MIME type set according to the first {@link
android.nfc.NdefRecord} in the {@link android.nfc.NdefMessage}. For the activity you want to
-respond, you can set intent filters for the URLs or MIME types your app cares about. For more
+respond, you can declare intent filters for the URLs or MIME types your app cares about. For more
information about Tag Dispatch see the <a
-href=”{@docRoot}guide/topics/nfc/index.html#dispatch”>NFC</a> developer guide.</p>
+href="{@docRoot}guide/topics/nfc/index.html#dispatch">NFC</a> developer guide.</p>
<p>If you want your {@link android.nfc.NdefMessage} to carry a URI, you can now use the convenience
method {@link android.nfc.NdefRecord#createUri createUri} to construct a new {@link
@@ -578,46 +652,51 @@
should create an intent filter for your activity using the same URI scheme in order to receive the
incoming NDEF message.</p>
-<p>You may also want to pass an “Android application record” with your {@link
-android.nfc.NdefMessage}
-in order to guarantee a specific application handles an NDEF message, regardless of whether other
-applications filter for the same intent. You can create an Android application record by calling
-{@link android.nfc.NdefRecord#createApplicationRecord createApplicationRecord()}, passing it the
-application’s package name. When the other device receives the NDEF message with this record, the
-system automatically starts the application matching the package name. If the target device does not
-currently have the application installed, the system uses the Android application record to launch
-Android Market and take the user to the application to install it.</p>
+<p>You should also pass an “Android application record" with your {@link android.nfc.NdefMessage} in
+order to guarantee that your application handles the incoming NDEF message, even if other
+applications filter for the same intent action. You can create an Android application record by
+calling {@link android.nfc.NdefRecord#createApplicationRecord createApplicationRecord()}, passing it
+your application’s package name. When the other device receives the NDEF message with the
+application record and multiple applications contain activities that handle the specified intent,
+the system always delivers the message to the activity in your application (based on the matching
+application record). If the target device does not currently have your application installed, the
+system uses the Android application record to launch Android Market and take the user to the
+application in order to install it.</p>
<p>If your application doesn’t use NFC APIs to perform NDEF Push messaging, then Android provides a
default behavior: When your application is in the foreground on one device and Android Beam is
invoked with another Android-powered device, then the other device receives an NDEF message with an
Android application record that identifies your application. If the receiving device has the
application installed, the system launches it; if it’s not installed, Android Market opens and takes
-the user to your application so they can install it.</p>
+the user to your application in order to install it.</p>
+
+<p>For some example code, see the <a
+href="{@docRoot}resources/samples/AndroidBeamDemo/src/com/example/android/beam/Beam.html">Android
+Beam Demo</a> sample app.</p>
+<h3 id="WiFiDirect">Wi-Fi Direct</h3>
-<h3 id="P2pWiFi">Peer-to-peer Wi-Fi</h3>
-
-<p>Android now supports Wi-Fi Direct™ for peer-to-peer (P2P) connections between
-Android-powered
+<p>Android now supports Wi-Fi Direct for peer-to-peer (P2P) connections between Android-powered
devices and other device types without a hotspot or Internet connection. The Android framework
provides a set of Wi-Fi P2P APIs that allow you to discover and connect to other devices when each
-device supports Wi-Fi Direct™, then communicate over a speedy connection across distances much
-longer than a Bluetooth connection.</p>
+device supports Wi-Fi Direct, then communicate over a speedy connection across distances much longer
+than a Bluetooth connection.</p>
<p>A new package, {@link android.net.wifi.p2p}, contains all the APIs for performing peer-to-peer
connections with Wi-Fi. The primary class you need to work with is {@link
-android.net.wifi.p2p.WifiP2pManager}, for which you can get an instance by calling {@link
+android.net.wifi.p2p.WifiP2pManager}, which you can acquire by calling {@link
android.app.Activity#getSystemService getSystemService(WIFI_P2P_SERVICE)}. The {@link
-android.net.wifi.p2p.WifiP2pManager} provides methods that allow you to:</p>
+android.net.wifi.p2p.WifiP2pManager} includes APIs that allow you to:</p>
<ul>
<li>Initialize your application for P2P connections by calling {@link
android.net.wifi.p2p.WifiP2pManager#initialize initialize()}</li>
+
<li>Discover nearby devices by calling {@link android.net.wifi.p2p.WifiP2pManager#discoverPeers
discoverPeers()}</li>
+
<li>Start a P2P connection by calling {@link android.net.wifi.p2p.WifiP2pManager#connect
connect()}</li>
<li>And more</li>
@@ -627,18 +706,20 @@
<ul>
<li>The {@link android.net.wifi.p2p.WifiP2pManager.ActionListener} interface allows you to receive
callbacks when an operation such as discovering peers or connecting to them succeeds or fails.</li>
+
<li>{@link android.net.wifi.p2p.WifiP2pManager.PeerListListener} interface allows you to receive
information about discovered peers. The callback provides a {@link
android.net.wifi.p2p.WifiP2pDeviceList}, from which you can retrieve a {@link
android.net.wifi.p2p.WifiP2pDevice} object for each device within range and get information such as
the device name, address, device type, the WPS configurations the device supports, and more.</li>
+
<li>The {@link android.net.wifi.p2p.WifiP2pManager.GroupInfoListener} interface allows you to
-receive
-information about a P2P group. The callback provides a {@link android.net.wifi.p2p.WifiP2pGroup}
-object, which provides group information such as the owner, the network name, and passphrase.</li>
+receive information about a P2P group. The callback provides a {@link
+android.net.wifi.p2p.WifiP2pGroup} object, which provides group information such as the owner, the
+network name, and passphrase.</li>
+
<li>{@link android.net.wifi.p2p.WifiP2pManager.ConnectionInfoListener} interface allows you to
-receive
-information about the current connection. The callback provides a {@link
+receive information about the current connection. The callback provides a {@link
android.net.wifi.p2p.WifiP2pInfo} object, which has information such as whether a group has been
formed and who is the group owner.</li>
</ul>
@@ -647,58 +728,57 @@
<ul>
<li>{@link android.Manifest.permission#ACCESS_WIFI_STATE}</li>
<li>{@link android.Manifest.permission#CHANGE_WIFI_STATE}</li>
-<li>{@link android.Manifest.permission#INTERNET} (even though your app doesn’t technically connect
-to
-the Internet, the WiFi Direct implementation uses traditional sockets that do require Internet
-permission to work).</li>
+<li>{@link android.Manifest.permission#INTERNET} (although your app doesn’t technically connect
+to the Internet, communicating to Wi-Fi Direct peers with standard java sockets requires Internet
+permission).</li>
</ul>
<p>The Android system also broadcasts several different actions during certain Wi-Fi P2P events:</p>
<ul>
<li>{@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_CONNECTION_CHANGED_ACTION}: The P2P
-connection
-state has changed. This carries {@link android.net.wifi.p2p.WifiP2pManager#EXTRA_WIFI_P2P_INFO} with
-a {@link android.net.wifi.p2p.WifiP2pInfo} object and {@link
+connection state has changed. This carries {@link
+android.net.wifi.p2p.WifiP2pManager#EXTRA_WIFI_P2P_INFO} with a {@link
+android.net.wifi.p2p.WifiP2pInfo} object and {@link
android.net.wifi.p2p.WifiP2pManager#EXTRA_NETWORK_INFO} with a {@link android.net.NetworkInfo}
object.</li>
+
<li>{@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_STATE_CHANGED_ACTION}: The P2P state has
-changed
-between enabled and disabled. It carries {@link
+changed between enabled and disabled. It carries {@link
android.net.wifi.p2p.WifiP2pManager#EXTRA_WIFI_STATE} with either {@link
android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_STATE_DISABLED} or {@link
android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_STATE_ENABLED}</li>
+
<li>{@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_PEERS_CHANGED_ACTION}: The list of peer
-devices
-has changed.</li>
+devices has changed.</li>
+
<li>{@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_THIS_DEVICE_CHANGED_ACTION}: The details for
this device have changed.</li>
</ul>
<p>See the {@link android.net.wifi.p2p.WifiP2pManager} documentation for more information. Also
-look
-at the <a href=”{@docRoot}resources/samples/WiFiDirectDemo/index.html”>Wi-Fi Direct</a> sample
-application for example code.</p>
+look at the <a href="{@docRoot}resources/samples/WiFiDirectDemo/index.html">Wi-Fi Direct Demo</a>
+sample application.</p>
-<h3 id="NetworkData">Network Data</h3>
+<h3 id="NetworkUsage">Network Usage</h3>
-<p>Android 4.0 gives users precise visibility of how much network data applications are using. The
-Settings app provides controls that allow users to manage set limits for network data usage and even
-disable the use of background data for individual apps. In order to avoid users disabling your app’s
-access to data from the background, you should develop strategies to use use the data connection
-efficiently and vary your usage depending on the type of connection available.</p>
+<p>Android 4.0 gives users precise visibility of how much network data their applications are using.
+The Settings app provides controls that allow users to manage set limits for network data usage and
+even disable the use of background data for individual apps. In order to avoid users disabling your
+app’s access to data from the background, you should develop strategies to use use the data
+connection efficiently and adjust your usage depending on the type of connection available.</p>
<p>If your application performs a lot of network transactions, you should provide user settings that
allow users to control your app’s data habits, such as how often your app syncs data, whether to
perform uploads/downloads only when on Wi-Fi, whether to use data while roaming, etc. With these
controls available to them, users are much less likely to disable your app’s access to data when
they approach their limits, because they can instead precisely control how much data your app uses.
-When you provide an activity with these settings, you should include in its manifest declaration an
-intent filter for the {@link android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} action. For
-example:</p>
+If you provide a preference activity with these settings, you should include in its manifest
+declaration an intent filter for the {@link android.content.Intent#ACTION_MANAGE_NETWORK_USAGE}
+action. For example:</p>
<pre>
<activity android:name="DataPreferences" android:label="@string/title_preferences">
@@ -709,10 +789,10 @@
</activity>
</pre>
-<p>This intent filter indicates to the system that this is the application that controls your
+<p>This intent filter indicates to the system that this is the activity that controls your
application’s data usage. Thus, when the user inspects how much data your app is using from the
-Settings app, a “View application settings” button is available that launches your activity so the
-user can refine how much data your app uses.</p>
+Settings app, a “View application settings" button is available that launches your
+preference activity so the user can refine how much data your app uses.</p>
<p>Also beware that {@link android.net.ConnectivityManager#getBackgroundDataSetting()} is now
deprecated and always returns true—use {@link
@@ -720,7 +800,7 @@
transactions, you should always call {@link android.net.ConnectivityManager#getActiveNetworkInfo()}
to get the {@link android.net.NetworkInfo} that represents the current network and query {@link
android.net.NetworkInfo#isConnected()} to check whether the device has a
-connection. You can then check various other connection properties, such as whether the device is
+connection. You can then check other connection properties, such as whether the device is
roaming or connected to Wi-Fi.</p>
@@ -729,43 +809,10 @@
-<h3 id="Sensors">Device Sensors</h3>
-<p>Two new sensor types have been added in Android 4.0: {@link
-android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE} and {@link
-android.hardware.Sensor#TYPE_RELATIVE_HUMIDITY}. </p>
+<h3 id="RenderScript">RenderScript</h3>
-<p>{@link android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE} is a temperature sensor that provides
-the ambient (room) temperature near a device. This sensor reports data in degrees Celsius. {@link
-android.hardware.Sensor#TYPE_RELATIVE_HUMIDITY} is a humidity sensor that provides the relative
-ambient (room) humidity. The sensor reports data as a percentage. If a device has both {@link
-android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE} and {@link
-android.hardware.Sensor#TYPE_RELATIVE_HUMIDITY} sensors, you can use them to calculate the dew point
-and the absolute humidity.</p>
-
-<p>The existing temperature sensor ({@link android.hardware.Sensor#TYPE_TEMPERATURE}) has been
-deprecated. You should use the {@link android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE} sensor
-instead.</p>
-
-<p>Additionally, Android’s three synthetic sensors have been improved so they now have lower latency
-and smoother output. These sensors include the gravity sensor ({@link
-android.hardware.Sensor#TYPE_GRAVITY}), rotation vector sensor ({@link
-android.hardware.Sensor#TYPE_ROTATION_VECTOR}), and linear acceleration sensor ({@link
-android.hardware.Sensor#TYPE_LINEAR_ACCELERATION}). The improved sensors rely on the gyroscope
-sensor to improve their output so the sensors appear only on devices that have a gyroscope. If a
-device already provides one of the sensors, then that sensor appears as a second sensor on the
-device. The three improved sensors have a version number of 2.</p>
-
-
-
-
-
-
-
-
-<h3 id="Renderscript">Renderscript</h3>
-
-<p>Three major features have been added to Renderscript:</p>
+<p>Three major features have been added to RenderScript:</p>
<ul>
<li>Off-screen rendering to a framebuffer object</li>
@@ -776,24 +823,24 @@
<p>The {@link android.renderscript.Allocation} class now supports a {@link
android.renderscript.Allocation#USAGE_GRAPHICS_RENDER_TARGET} memory space, which allows you to
render things directly into the {@link android.renderscript.Allocation} and use it as a framebuffer
-object. </p>
+object.</p>
-<p>{@link android.renderscript.RSTextureView} provides a means to display Renderscript graphics
-inside
-of a normal View, unlike {@link android.renderscript.RSSurfaceView}, which creates a separate
-window. This key difference allows you to do things such as move, transform, or animate an {@link
-android.renderscript.RSTextureView} as well as draw Renderscript graphics inside the View alongside
-other traditional View widgets.</p>
+<p>{@link android.renderscript.RSTextureView} provides a means to display RenderScript graphics
+inside of a {@link android.view.View}, unlike {@link android.renderscript.RSSurfaceView}, which
+creates a separate window. This key difference allows you to do things such as move, transform, or
+animate an {@link android.renderscript.RSTextureView} as well as draw RenderScript graphics inside
+a view that lies within an activity layout.</p>
-<p>The {@link android.renderscript.Script#forEach forEach()} method allows you to call Renderscript
-compute scripts from the VM level and have them automatically delegated to available cores on the
-device. You do not use this method directly, but any compute Renderscript that you write will have a
-{@link android.renderscript.Script#forEach forEach()} method that you can call in the reflected
-Renderscript class. You can call the reflected {@link android.renderscript.Script#forEach forEach()}
-method by passing in an input {@link android.renderscript.Allocation} to process, an output {@link
-android.renderscript.Allocation} to write the result to, and a data structure if the Renderscript
-needs more information in addition to the {@link android.renderscript.Allocation}s to. Only one of
-the {@link android.renderscript.Allocation}s is necessary and the data structure is optional.</p>
+<p>The {@link android.renderscript.Script#forEach Script.forEach()} method allows you to call
+RenderScript compute scripts from the VM level and have them automatically delegated to available
+cores on the device. You do not use this method directly, but any compute RenderScript that you
+write will have a {@link android.renderscript.Script#forEach forEach()} method that you can call in
+the reflected RenderScript class. You can call the reflected {@link
+android.renderscript.Script#forEach forEach()} method by passing in an input {@link
+android.renderscript.Allocation} to process, an output {@link android.renderscript.Allocation} to
+write the result to, and a {@link android.renderscript.FieldPacker} data structure in case the
+RenderScript needs more information. Only one of the {@link android.renderscript.Allocation}s is
+necessary and the data structure is optional.</p>
@@ -802,118 +849,154 @@
<h3 id="A11y">Accessibility</h3>
-<p>Android 4.0 improves accessibility for users with disabilities with the Touch Exploration service
-and provides extended APIs for developers of new accessibility services.</p>
-
-<h4>Touch Exploration</h4>
-
-<p>Users with vision loss can now explore applications by touching areas of the screen and hearing
-voice descriptions of the content. The “Explore by Touch” feature works like a virtual cursor as the
-user drags a finger across the screen.</p>
-
-<p>You don’t have to use any new APIs to enhance touch exploration in your application, because the
-existing {@link android.R.attr#contentDescription android:contentDescription}
-attribute and {@link android.view.View#setContentDescription setContentDescription()} method is all
-you need. Because touch exploration works like a virtual cursor, it allows screen readers to
-identify the descriptive the same way that screen readers can when navigating with a d-pad or
-trackball. So this is a reminder to provide descriptive text for the views in your application,
-especially for {@link android.widget.ImageButton}, {@link android.widget.EditText}, {@link
-android.widget.CheckBox} and other interactive widgets that might not contain text information by
-default.</p>
-
-<h4>Accessibility for Custom Views</h4>
-
-<p>Developers of custom Views, ViewGroups and widgets can make their components compatible with
-accessibility services like Touch Exploration. For custom views and widgets targeted for Android 4.0
-and later, developers should implement the following accessibility API methods in their classes:</p>
-<ul>
-<li>These two methods initiate the accessibility event generation process and must be implemented by
-your custom view class.
- <ul>
- <li>{@link android.view.View#sendAccessibilityEvent(int) sendAccessibilityEvent()} If
-accessibility
- is
- not enabled, this call has no effect.</li>
- <li>{@link
- android.view.View#sendAccessibilityEventUnchecked(android.view.accessibility.AccessibilityEvent)
- sendAccessibilityEventUnchecked()} - This method executes regardless of whether accessibility is
- enabled or not.</li>
- </ul>
-</li>
-
-<li>These methods are called in order by the sendAccessibilityEvent methods listed above to collect
-accessibility information about the view, and its child views.
- <ul>
- <li>{@link
- android.view.View#onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent)
- onInitializeAccessibilityEvent()} - This method collects information about the view. If your
- application has specific requirements for accessibility, you should extend this method to add that
- information to the {@link android.view.accessibility.AccessibilityEvent}.</li>
-
- <li>{@link
-
-android.view.View#dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent)
- dispatchPopulateAccessibilityEvent()} is called by the framework to request text information for
- this view and its children. This method calls {@link
- android.view.View#onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent)
- onPopulateAccessibilityEvent()} first on the current view and then on its children.</li>
- </ul>
-</li>
-
-<li>The {@link
-android.view.View#onInitializeAccessibilityNodeInfo onInitializeAccessibilityNodeInfo()} method
-provides additional context information for
-accessibility services. You should implement or override this method to provide improved information
-for accessibility services investigating your custom view.</li>
-
-<li>Custom {@link android.view.ViewGroup} classes should also implement {@link
-android.view.ViewGroup#onRequestSendAccessibilityEvent(android.view.View,
-android.view.accessibility.AccessibilityEvent) onRequestSendAccessibilityEvent()} </li>
-</ul>
-
-<p>Developers who want to maintain compatibility with Android versions prior to 4.0, while still
-providing support for new the accessibility APIs, can use the {@link
-android.view.View#setAccessibilityDelegate(android.view.View.AccessibilityDelegate)
-setAccessibilityDelegate()} method to provide an {@link android.view.View.AccessibilityDelegate}
-containing implementations of the new accessibility API methods while maintaining compatibility with
-prior releases.</p>
+<p>Android 4.0 improves accessibility for sight-impaired users with new explore-by-touch mode
+and extended APIs that allow you to provide more information about view content or
+develop advanced accessibility services.</p>
+<h4>Explore-by-touch mode</h4>
-<h4>Accessibility Service APIs</h4>
+<p>Users with vision loss can now explore the screen by touching and dragging a finger across the
+screen to hear voice descriptions of the content. Because the explore-by-touch mode works like a
+virtual cursor, it allows screen readers to identify the descriptive text the same way that screen
+readers can when the user navigates with a d-pad or trackball—by reading information provided
+by {@link android.R.attr#contentDescription android:contentDescription} and {@link
+android.view.View#setContentDescription setContentDescription()} upon a simulated "hover" event. So,
+consider this is a reminder that you should provide descriptive text for the views in your
+application, especially for {@link android.widget.ImageButton}, {@link android.widget.EditText},
+{@link android.widget.ImageView} and other widgets that might not naturally contain descriptive
+text.</p>
-<p>Accessibility events have been significantly improved to provide better information for
-accessibility services. In particular, events are generated based on view composition, providing
-better context information and allowing accessibility service developers to traverse view
-hierarchies to get additional view information and deal with special cases.</p>
-<p>To access additional content information and traverse view hierarchies, accessibility service
-application developers should use the following procedure.</p>
+<h4>Accessibility for views</h4>
+
+<p>To enhance the information available to accessibility services such as screen readers, you can
+implement new callback methods for accessibility events in your custom {@link
+android.view.View} components.</p>
+
+<p>It's important to first note that the behavior of the {@link
+android.view.View#sendAccessibilityEvent sendAccessibilityEvent()} method has changed in Android
+4.0. As with previous version of Android, when the user enables accessibility services on the device
+and an input event such as a click or hover occurs, the respective view is notified with a call to
+{@link android.view.View#sendAccessibilityEvent sendAccessibilityEvent()}. Previously, the
+implementation of {@link android.view.View#sendAccessibilityEvent sendAccessibilityEvent()} would
+initialize an {@link android.view.accessibility.AccessibilityEvent} and send it to {@link
+android.view.accessibility.AccessibilityManager}. The new behavior involves some additional callback
+methods that allow the view and its parents to add more contextual information to the event:
<ol>
-<li>Upon receiving an {@link android.view.accessibility.AccessibilityEvent} from an application,
-call
-the {@link android.view.accessibility.AccessibilityEvent#getRecord(int)
-AccessibilityEvent.getRecord()} to retrieve new accessibility information about the state of the
-view.</li>
-<li>From the {@link android.view.accessibility.AccessibilityRecord}, call {@link
-android.view.accessibility.AccessibilityRecord#getSource() getSource()} to retrieve a {@link
-android.view.accessibility.AccessibilityNodeInfo} object.</li>
-<li>With the {@link android.view.accessibility.AccessibilityNodeInfo}, call {@link
-android.view.accessibility.AccessibilityNodeInfo#getParent getParent()} or {@link
-android.view.accessibility.AccessibilityNodeInfo#getChild getChild()} to traverse the view
-hierarchy and get additional context information.</li>
+ <li>When invoked, the {@link
+android.view.View#sendAccessibilityEvent sendAccessibilityEvent()} and {@link
+android.view.View#sendAccessibilityEventUnchecked sendAccessibilityEventUnchecked()} methods defer
+to {@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()}.
+ <p>Custom implementations of {@link android.view.View} might want to implement {@link
+android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()} to
+attach additional accessibility information to the {@link
+android.view.accessibility.AccessibilityEvent}, but should also call the super implementation to
+provide default information such as the standard content description, item index, and more.
+However, you should not add additional text content in this callback—that happens
+next.</p></li>
+ <li>Once initialized, if the event is one of several types that should be populated with text
+information, the view then receives a call to {@link
+android.view.View#dispatchPopulateAccessibilityEvent dispatchPopulateAccessibilityEvent()}, which
+defers to the {@link android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()}
+callback.
+ <p>Custom implementations of {@link android.view.View} should usually implement {@link
+android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} to add additional
+text content to the {@link android.view.accessibility.AccessibilityEvent} if the {@link
+android.R.attr#contentDescription android:contentDescription} text is missing or
+insufficient. To add more text description to the
+{@link android.view.accessibility.AccessibilityEvent}, call {@link
+android.view.accessibility.AccessibilityEvent#getText()}.{@link java.util.List#add add()}.</p>
+</li>
+ <li>At this point, the {@link android.view.View} passes the event up the view hierarchy by calling
+{@link android.view.ViewGroup#requestSendAccessibilityEvent requestSendAccessibilityEvent()} on the
+parent view. Each parent view then has the chance to augment the accessibility information by
+adding an {@link android.view.accessibility.AccessibilityRecord}, until it
+ultimately reaches the root view, which sends the event to the {@link
+android.view.accessibility.AccessibilityManager} with {@link
+android.view.accessibility.AccessibilityManager#sendAccessibilityEvent
+sendAccessibilityEvent()}.</li>
</ol>
-<p>In order to retrieve {@link android.view.accessibility.AccessibilityNodeInfo} information, your
-application must request permission to retrieve application window content through a manifest
-declaration that includes a new, separate xml configuration file, which supercedes {@link
-android.accessibilityservice.AccessibilityServiceInfo}. For more information, see {@link
+<p>In addition to the new methods above, which are useful when extending the {@link
+android.view.View} class, you can also intercept these event callbacks on any {@link
+android.view.View} by extending {@link
+android.view.View.AccessibilityDelegate AccessibilityDelegate} and setting it on the view with
+{@link android.view.View#setAccessibilityDelegate setAccessibilityDelegate()}.
+When you do, each accessibility method in the view defers the call to the corresponding method in
+the delegate. For example, when the view receives a call to {@link
+android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()}, it passes it to the
+same method in the {@link android.view.View.AccessibilityDelegate}. Any methods not handled by
+the delegate are given right back to the view for default behavior. This allows you to override only
+the methods necessary for any given view without extending the {@link android.view.View} class.</p>
+
+
+<p>If you want to maintain compatibility with Android versions prior to 4.0, while also supporting
+the new the accessibility APIs, you can do so with the latest version of the <em>v4 support
+library</em> (in <a href="{@docRoot}sdk/compatibility-library.html">Compatibility Package, r4</a>)
+using a set of utility classes that provide the new accessibility APIs in a backward-compatible
+design.</p>
+
+
+
+<h4>Accessibility services</h4>
+
+<p>If you're developing an accessibility service, the information about various accessibility events
+has been significantly expanded to enable more advanced accessibility feedback for users. In
+particular, events are generated based on view composition, providing better context information and
+allowing accessibility services to traverse view hierarchies to get additional view information and
+deal with special cases.</p>
+
+<p>If you're developing an accessibility service (such as a screen reader), you can access
+additional content information and traverse view hierarchies with the following procedure:</p>
+<ol>
+<li>Upon receiving an {@link android.view.accessibility.AccessibilityEvent} from an application,
+call the {@link android.view.accessibility.AccessibilityEvent#getRecord(int)
+AccessibilityEvent.getRecord()} to retrieve a specific {@link
+android.view.accessibility.AccessibilityRecord} (there may be several records attached to the
+event).</li>
+
+<li>From either {@link android.view.accessibility.AccessibilityEvent} or an individual {@link
+android.view.accessibility.AccessibilityRecord}, you can call {@link
+android.view.accessibility.AccessibilityRecord#getSource() getSource()} to retrieve a {@link
+android.view.accessibility.AccessibilityNodeInfo} object.
+ <p>An {@link android.view.accessibility.AccessibilityNodeInfo} represents a single node
+of the window content in a format that allows you to query accessibility information about that
+node. The {@link android.view.accessibility.AccessibilityNodeInfo} object returned from {@link
+android.view.accessibility.AccessibilityEvent} describes the event source, whereas the source from
+an {@link android.view.accessibility.AccessibilityRecord} describes the predecessor of the event
+source.</p></li>
+
+<li>With the {@link android.view.accessibility.AccessibilityNodeInfo}, you can query information
+about it, call {@link
+android.view.accessibility.AccessibilityNodeInfo#getParent getParent()} or {@link
+android.view.accessibility.AccessibilityNodeInfo#getChild getChild()} to traverse the view
+hierarchy, and even add child views to the node.</li>
+</ol>
+
+<p>In order for your application to publish itself to the system as an accessibility service, it
+must declare an XML configuration file that corresponds to {@link
+android.accessibilityservice.AccessibilityServiceInfo}. For more information about creating an
+accessibility service, see {@link
android.accessibilityservice.AccessibilityService} and {@link
android.accessibilityservice.AccessibilityService#SERVICE_META_DATA
-AccessibilityService.SERVICE_META_DATA}.</p>
+SERVICE_META_DATA} for information about the XML configuration.</p>
+<h4>Other accessibility APIs</h4>
+<p>If you're interested in the device's accessibility state, the {@link
+android.view.accessibility.AccessibilityManager} has some new APIs such as:</p>
+<ul>
+ <li>{@link android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener}
+is an interface that allows you to receive a callback whenever accessibility is enabled or
+disabled.</li>
+ <li>{@link android.view.accessibility.AccessibilityManager#getEnabledAccessibilityServiceList
+ getEnabledAccessibilityServiceList()} provides information about which accessibility services
+ are currently enabled.</li>
+ <li>{@link android.view.accessibility.AccessibilityManager#isTouchExplorationEnabled()} tells
+ you whether the explore-by-touch mode is enabled.</li>
+</ul>
@@ -921,13 +1004,12 @@
<p>Android 4.0 expands the capabilities for enterprise application with the following features.</p>
-<h4>VPN Services</h4>
+<h4>VPN services</h4>
<p>The new {@link android.net.VpnService} allows applications to build their own VPN (Virtual
-Private
-Network), running as a {@link android.app.Service}. A VPN service creates an interface for a virtual
-network with its own address and routing rules and performs all reading and writing with a file
-descriptor.</p>
+Private Network), running as a {@link android.app.Service}. A VPN service creates an interface for a
+virtual network with its own address and routing rules and performs all reading and writing with a
+file descriptor.</p>
<p>To create a VPN service, use {@link android.net.VpnService.Builder}, which allows you to specify
the network address, DNS server, network route, and more. When complete, you can establish the
@@ -941,7 +1023,7 @@
users must manually enable it in the system settings.</p>
-<h4>Device Restrictions</h4>
+<h4>Device restrictions</h4>
<p>Applications that manage the device restrictions can now disable the camera using {@link
android.app.admin.DevicePolicyManager#setCameraDisabled setCameraDisabled()} and the {@link
@@ -949,54 +1031,46 @@
<disable-camera />} element in the policy configuration file).</p>
-<h4>Certificate Management</h4>
+<h4>Certificate management</h4>
<p>The new {@link android.security.KeyChain} class provides APIs that allow you to import and access
-certificates and key stores in credential storage. See the {@link android.security.KeyChain}
+certificates in the system key store. Certificates streamline the installation of both client
+certificates (to validate the identity of the user) and certificate authority certificates (to
+verify server identity). Applications such as web browsers or email clients can access the installed
+certificates to authenticate users to servers. See the {@link android.security.KeyChain}
documentation for more information.</p>
-<h3 id="Voicemail">Voicemail</h3>
-
-<p>A new voicemail APIs allows applications to add voicemails to the system. Because the APIs
-currently
-do not allow third party apps to read all the voicemails from the system, the only third-party apps
-that should use the voicemail APIs are those that have voicemail to deliver to the user. For
-instance, it’s possible that a users have multiple voicemail sources, such as one provided by their
-phone’s service provider and others from VoIP or other alternative services. These kinds of apps can
-use the APIs to add voicemail to the system. The built-in Phone application can then present all
-voicemails to the user with a single list. Although the system’s Phone application is the only
-application that can read all the voicemails, each application that provides voicemails can read
-those that it has added to the system.</p>
-
-<p>The {@link android.provider.VoicemailContract} class defines the content provider for the
-voicemail
-APIs. The subclasses {@link android.provider.VoicemailContract.Voicemails} and {@link
-android.provider.VoicemailContract.Status} provide tables in which the voicemail providers can
-insert voicemail data for storage on the device. For an example of a voicemail provider app, see the
-<a href=”{@docRoot}resources/samples/VoicemailProviderDemo/index.html”>Voicemail Provider
-Demo</a>.</p>
+<h3 id="Sensors">Device Sensors</h3>
-<h3 id="SpellChecker">Spell Checker Services</h3>
+<p>Two new sensor types have been added in Android 4.0:</p>
-<p>The new spell checker framework allows apps to create spell checkers in a manner similar to the
-input method framework. To create a new spell checker, you must override the {@link
-android.service.textservice.SpellCheckerService.Session} class to provide spelling suggestions based
-on text provided by the interface callback methods, returning suggestions as a {@link
-android.view.textservice.SuggestionsInfo} object. </p>
+<ul>
+ <li>{@link android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE}: A temperature sensor that provides
+the ambient (room) temperature in degrees Celsius.</li>
+ <li>{@link android.hardware.Sensor#TYPE_RELATIVE_HUMIDITY}: A humidity sensor that provides the
+relative ambient (room) humidity as a percentage.</li>
+</ul>
-<p>Applications with a spell checker service must declare the {@link
-android.Manifest.permission#BIND_TEXT_SERVICE} permission as required by the service, such that
-other services must have this permission in order for them to bind with the spell checker service.
-The service must also declare an intent filter with <action
-android:name="android.service.textservice.SpellCheckerService" /> as the intent’s action and should
-include a {@code <meta-data>} element that declares configuration information for the spell
-checker. </p>
+<p>If a device has both {@link android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE} and {@link
+android.hardware.Sensor#TYPE_RELATIVE_HUMIDITY} sensors, you can use them to calculate the dew point
+and the absolute humidity.</p>
+
+<p>The previous temperature sensor, {@link android.hardware.Sensor#TYPE_TEMPERATURE}, has been
+deprecated. You should use the {@link android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE} sensor
+instead.</p>
+
+<p>Additionally, Android’s three synthetic sensors have been improved so they now have lower latency
+and smoother output. These sensors include the gravity sensor ({@link
+android.hardware.Sensor#TYPE_GRAVITY}), rotation vector sensor ({@link
+android.hardware.Sensor#TYPE_ROTATION_VECTOR}), and linear acceleration sensor ({@link
+android.hardware.Sensor#TYPE_LINEAR_ACCELERATION}). The improved sensors rely on the gyroscope
+sensor to improve their output, so the sensors appear only on devices that have a gyroscope.</p>
@@ -1004,22 +1078,20 @@
<h3 id="TTS">Text-to-speech Engines</h3>
-<p>Android’s text-to-speech (TTS) APIs have been greatly extended to allow applications to more
-easily
-implement custom TTS engines, while applications that want to use a TTS engine have a couple new
-APIs for selecting the engine.</p>
+<p>Android’s text-to-speech (TTS) APIs have been significantly extended to allow applications to
+more easily implement custom TTS engines, while applications that want to use a TTS engine have a
+couple new APIs for selecting an engine.</p>
<h4>Using text-to-speech engines</h4>
<p>In previous versions of Android, you could use the {@link android.speech.tts.TextToSpeech} class
-to
-perform text-to-speech (TTS) operations using the TTS engine provided by the system or set a custom
-engine using {@link android.speech.tts.TextToSpeech#setEngineByPackageName
-setEngineByPackageName()}.
-In Android 4.0, the {@link android.speech.tts.TextToSpeech#setEngineByPackageName
-setEngineByPackageName()} method has been deprecated and you can now specify the engine to use with
-a new {@link android.speech.tts.TextToSpeech} that accepts the package name of a TTS engine.</p>
+to perform text-to-speech (TTS) operations using the TTS engine provided by the system or set a
+custom engine using {@link android.speech.tts.TextToSpeech#setEngineByPackageName
+setEngineByPackageName()}. In Android 4.0, the {@link
+android.speech.tts.TextToSpeech#setEngineByPackageName setEngineByPackageName()} method has been
+deprecated and you can now specify the engine to use with a new {@link
+android.speech.tts.TextToSpeech} constructor that accepts the package name of a TTS engine.</p>
<p>You can also query the available TTS engines with {@link
android.speech.tts.TextToSpeech#getEngines()}. This method returns a list of {@link
@@ -1029,39 +1101,59 @@
<h4>Building text-to-speech engines</h4>
-<p>Previously, custom engines required that the engine be built using native code, based on a TTS
-engine header file. In Android 4.0, there is a framework API for building TTS engines. </p>
+<p>Previously, custom engines required that the engine be built using an undocumented native header
+file. In Android 4.0, there is a complete set of framework APIs for building TTS engines. </p>
<p>The basic setup requires an implementation of {@link android.speech.tts.TextToSpeechService} that
responds to the {@link android.speech.tts.TextToSpeech.Engine#INTENT_ACTION_TTS_SERVICE} intent. The
primary work for a TTS engine happens during the {@link
-android.speech.tts.TextToSpeechService#onSynthesizeText onSynthesizeText()} callback in the {@link
-android.speech.tts.TextToSpeechService}. The system delivers this method two objects:</p>
+android.speech.tts.TextToSpeechService#onSynthesizeText onSynthesizeText()} callback in a service
+that extends {@link android.speech.tts.TextToSpeechService}. The system delivers this method two
+objects:</p>
<ul>
<li>{@link android.speech.tts.SynthesisRequest}: This contains various data including the text to
synthesize, the locale, the speech rate, and voice pitch.</li>
<li>{@link android.speech.tts.SynthesisCallback}: This is the interface by which your TTS engine
-delivers the resulting speech data as streaming audio, by calling {@link
+delivers the resulting speech data as streaming audio. First the engine must call {@link
android.speech.tts.SynthesisCallback#start start()} to indicate that the engine is ready to deliver
-the
-audio, then call {@link android.speech.tts.SynthesisCallback#audioAvailable audioAvailable()},
-passing it the audio
-data in a byte buffer. Once your engine has passed all audio through the buffer, call {@link
-android.speech.tts.SynthesisCallback#done()}.</li>
+the audio, then call {@link android.speech.tts.SynthesisCallback#audioAvailable audioAvailable()},
+passing it the audio data in a byte buffer. Once your engine has passed all audio through the
+buffer, call {@link android.speech.tts.SynthesisCallback#done()}.</li>
</ul>
-<p>Now that the framework supports a true API for creating TTS engines, support for the previous
-technique using native code has been removed. Watch for a blog post about the compatibility layer
-that you can use to convert TTS engines built using the previous technique to the new framework.</p>
+<p>Now that the framework supports a true API for creating TTS engines, support for the native code
+implementation has been removed. Look for a blog post about a compatibility layer
+that you can use to convert your old TTS engines to the new framework.</p>
<p>For an example TTS engine using the new APIs, see the <a
-href=”{@docRoot}resources/samples/TtsEngine/index.html”>Text To Speech Engine</a> sample app.</p>
+href="{@docRoot}resources/samples/TtsEngine/index.html">Text To Speech Engine</a> sample app.</p>
+<h3 id="SpellChecker">Spell Checker Services</h3>
+
+<p>A new spell checker framework allows apps to create spell checkers in a manner similar to the
+input method framework. To create a new spell checker, you must implement a service that extends
+{@link android.service.textservice.SpellCheckerService} and extend the {@link
+android.service.textservice.SpellCheckerService.Session} class to provide spelling suggestions based
+on text provided by interface callback methods. In the {@link
+android.service.textservice.SpellCheckerService.Session} callback methods, you must return the
+spelling suggestions as {@link android.view.textservice.SuggestionsInfo} objects. </p>
+
+<p>Applications with a spell checker service must declare the {@link
+android.Manifest.permission#BIND_TEXT_SERVICE} permission as required by the service, such that
+other services must have this permission in order for them to bind with the spell checker service.
+The service must also declare an intent filter with {@code <action
+android:name="android.service.textservice.SpellCheckerService" />} as the intent’s action and should
+include a {@code <meta-data>} element that declares configuration information for the spell
+checker. </p>
+
+
+
+
@@ -1071,34 +1163,36 @@
<p>The {@link android.app.ActionBar} has been updated to support several new behaviors. Most
importantly, the system gracefully manages the action bar’s size and configuration when running on
-smaller screens in order to provide an optimal user experience. For example, when the screen is
-narrow (such as when a handset is in portrait orientation), the action bar’s navigation tabs appear
-in a “stacked bar,” which appears directly below the main action bar. You can also opt-in to a
-“split action bar,” which will place all action items in a separate bar at the bottom of the screen
-when the screen is narrow.</p>
+smaller screens in order to provide an optimal user experience on all screen sizes. For example,
+when the screen is narrow (such as when a handset is in portrait orientation), the action bar’s
+navigation tabs appear in a “stacked bar," which appears directly below the main action bar. You can
+also opt-in to a “split action bar," which places all action items in a separate bar at the bottom
+of the screen when the screen is narrow.</p>
-<h4>Split Action Bar</h4>
+<h4>Split action bar</h4>
-<p>If your action bar includes several action items, not all of them will fit into the action bar
-when on a narrow screen, so the system will place them into the overflow menu. However, Android 4.0
-allows you to enable “split action bar” so that more action items can appear on the screen in a
+<p>If your action bar includes several action items, not all of them will fit into the action bar on
+a narrow screen, so the system will place more of them into the overflow menu. However, Android 4.0
+allows you to enable “split action bar" so that more action items can appear on the screen in a
separate bar at the bottom of the screen. To enable split action bar, add {@link
-android.R.attr#uiOptions android:uiOptions} with {@code ”splitActionBarWhenNarrow”} to either your
-{@code <application>} tag or individual {@code <activity>} tags in your manifest file.
-When enabled, the system will enable the additional bar for action items when the screen is narrow
-and add all action items to the new bar (no action items will appear in the primary action bar).</p>
+android.R.attr#uiOptions android:uiOptions} with {@code "splitActionBarWhenNarrow"} to either your
+<a href="guide/topics/manifest/application-element.html">{@code <application>}</a> tag or
+individual <a href="guide/topics/manifest/activity-element.html">{@code <activity>}</a> tags
+in your manifest file. When enabled, the system will add an additional bar at the bottom of the
+screen for all action items when the screen is narrow (no action items will appear in the primary
+action bar).</p>
<p>If you want to use the navigation tabs provided by the {@link android.app.ActionBar.Tab} APIs,
-but
-don’t want the stacked bar—you want only the tabs to appear, then enable the split action bar
-as described above and also call {@link android.app.ActionBar#setDisplayShowHomeEnabled
-setDisplayShowHomeEnabled(false)} to disable the application icon in the action bar. With nothing
-left in the main action bar, it disappears—all that’s left are the navigation tabs at the top
-and the action items at the bottom of the screen.</p>
+but don’t need the main action bar on top (you want only the tabs to appear at the top), then enable
+the split action bar as described above and also call {@link
+android.app.ActionBar#setDisplayShowHomeEnabled setDisplayShowHomeEnabled(false)} to disable the
+application icon in the action bar. With nothing left in the main action bar, it
+disappears—all that’s left are the navigation tabs at the top and the action items at the
+bottom of the screen.</p>
-<h4>Action Bar Styles</h4>
+<h4>Action bar styles</h4>
<p>If you want to apply custom styling to the action bar, you can use new style properties {@link
android.R.attr#backgroundStacked} and {@link android.R.attr#backgroundSplit} to apply a background
@@ -1108,31 +1202,38 @@
setSplitBackgroundDrawable()}.</p>
-<h4>Action Provider</h4>
+<h4>Action provider</h4>
-<p>The new {@link android.view.ActionProvider} class facilitates user actions to which several
-different applications may respond. For example, a “share” action in your application might invoke
-several different apps that can handle the {@link android.content.Intent#ACTION_SEND} intent and the
-associated data. In this case, you can use the {@link android.widget.ShareActionProvider} (an
-extension of {@link android.view.ActionProvider}) in your action bar, instead of a traditional menu
-item that invokes the intent. The {@link android.widget.ShareActionProvider} populates a drop-down
-menu with all the available apps that can handle the intent.</p>
+<p>The new {@link android.view.ActionProvider} class allows you to create a specialized handler for
+action items. An action provider can define an action view, a default action behavior, and a submenu
+for each action item to which it is associated. When you want to create an action item that has
+dynamic behaviors (such as a variable action view, default action, or submenu), extending {@link
+android.view.ActionProvider} is a good solution in order to create a reusable component, rather than
+handling the various action item transformations in your fragment or activity.</p>
+
+<p>For example, the {@link android.widget.ShareActionProvider} is an extension of {@link
+android.view.ActionProvider} that facilitates a “share" action from the action bar. Instead of using
+traditional action item that invokes the {@link android.content.Intent#ACTION_SEND} intent, you can
+use this action provider to present an action view with a drop-down list of applications that handle
+the {@link android.content.Intent#ACTION_SEND} intent. When the user selects an application to use
+for the action, {@link android.widget.ShareActionProvider} remembers that selection and provides it
+in the action view for faster access to sharing with that app.</p>
<p>To declare an action provider for an action item, include the {@code android:actionProviderClass}
-attribute in the {@code <item>} element for your activity’s options menu, with the class name
-of the action provider as the attribute value. For example:</p>
+attribute in the <a href="{@docRoot}guide/topics/resources/menu-resource.html#item-element">{@code
+<item>}</a> element for your activity’s options menu, with the class name of the action
+provider as the value. For example:</p>
<pre>
<item android:id="@+id/menu_share"
android:title="Share"
- android:icon="@drawable/ic_share"
android:showAsAction="ifRoom"
android:actionProviderClass="android.widget.ShareActionProvider" />
</pre>
<p>In your activity’s {@link android.app.Activity#onCreateOptionsMenu onCreateOptionsMenu()}
-callback
-method, retrieve an instance of the action provider from the menu item and set the intent:</p>
+callback method, retrieve an instance of the action provider from the menu item and set the
+intent:</p>
<pre>
public boolean onCreateOptionsMenu(Menu menu) {
@@ -1147,21 +1248,23 @@
</pre>
<p>For an example using the {@link android.widget.ShareActionProvider}, see the <a
-href=”{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ActionBarActionProviderActivity.html”>ActionBarActionProviderActivity</a>
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/
+ActionBarActionProviderActivity.html">ActionBarActionProviderActivity</a>
class in ApiDemos.</p>
-<h4>Collapsible Action Views</h4>
+<h4>Collapsible action views</h4>
-<p>Menu items that appear as action items can now toggle between their action view state and
+<p>Action items that provide an action view can now toggle between their action view state and
traditional action item state. Previously only the {@link android.widget.SearchView} supported
collapsing when used as an action view, but now you can add an action view for any action item and
switch between the expanded state (action view is visible) and collapsed state (action item is
visible).</p>
<p>To declare that an action item that contains an action view be collapsible, include the {@code
-“collapseActionView”} flag in the {@code android:showAsAction} attribute for the {@code
-<item>} element in the menu’s XML file.</p>
+“collapseActionView"} flag in the {@code android:showAsAction} attribute for the <a
+href="{@docRoot}guide/topics/resources/menu-resource.html#item-element">{@code
+<item>}</a> element in the menu’s XML file.</p>
<p>To receive callbacks when an action view switches between expanded and collapsed, register an
instance of {@link android.view.MenuItem.OnActionExpandListener} with the respective {@link
@@ -1178,20 +1281,20 @@
collapsed.</p>
-<h4>Other APIs for Action Bar</h4>
+<h4>Other APIs for action bar</h4>
<ul>
-<li>{@link android.app.ActionBar#setHomeButtonEnabled setHomeButtonEnabled()} allows you to disable
-the
-default behavior in which the application icon/logo behaves as a button (pass “false” to disable it
-as a button).</li>
+<li>{@link android.app.ActionBar#setHomeButtonEnabled setHomeButtonEnabled()} allows you to specify
+whether the icon/logo behaves as a button to navigate home or “up" (pass “true" to make it behave as
+a button).</li>
+
<li>{@link android.app.ActionBar#setIcon setIcon()} and {@link android.app.ActionBar#setLogo
-setLogo()}
-to define the action bar icon or logo at runtime.</li>
+setLogo()} allow you to define the action bar icon or logo at runtime.</li>
+
<li>{@link android.app.Fragment#setMenuVisibility Fragment.setMenuVisibility()} allows you to enable
-or
-disable the visibility of the options menu items declared by the fragment. This is useful if the
+or disable the visibility of the options menu items declared by the fragment. This is useful if the
fragment has been added to the activity, but is not visible, so the menu items should be
hidden.</li>
+
<li>{@link android.app.FragmentManager#invalidateOptionsMenu
FragmentManager.invalidateOptionsMenu()}
allows you to invalidate the activity options menu during various states of the fragment lifecycle
@@ -1209,6 +1312,7 @@
<p>Android 4.0 introduces a variety of new views and other UI components.</p>
+
<h4>System UI</h4>
<p>Since the early days of Android, the system has managed a UI component known as the <em>status
@@ -1219,8 +1323,8 @@
Android 4.0, the system provides a new type of system UI called the <em>navigation bar</em>. The
navigation bar shares some qualities with the system bar, because it provides navigation controls
for devices that don’t have hardware counterparts for navigating the system, but the navigation
-controls is all that it provides (a device with the navigation bar, thus, also includes the status
-bar at the top of the screen).</p>
+controls is all that the navigation bar offers (a device with the navigation bar, thus, also
+includes the status bar at the top of the screen).</p>
<p>To this day, you can hide the status bar on handsets using the {@link
android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN} flag. In Android 4.0, the APIs that control
@@ -1228,43 +1332,41 @@
and navigation bar:</p>
<ul>
<li>The {@link android.view.View#SYSTEM_UI_FLAG_LOW_PROFILE} flag replaces View.STATUS_BAR_HIDDEN
-flag
-(now deprecated). When set, this flag enables “low profile” mode for the system bar or navigation
-bar. Navigation buttons dim and other elements in the system bar also hide.</li>
+flag. When set, this flag enables “low profile" mode for the system bar or
+navigation bar. Navigation buttons dim and other elements in the system bar also hide.</li>
+
<li>The {@link android.view.View#SYSTEM_UI_FLAG_VISIBLE} flag replaces the {@code
-STATUS_BAR_VISIBLE}
-flag to request the system bar or navigation bar be visible.</li>
+STATUS_BAR_VISIBLE} flag to request the system bar or navigation bar be visible.</li>
+
<li>The {@link android.view.View#SYSTEM_UI_FLAG_HIDE_NAVIGATION} is a new flag that requests that
-the
-navigation bar hide completely. Take note that this works only for the <em>navigation bar</em> used
-by some handsets (it does <strong>not</strong> hide the system bar on tablets). The navigation bar
-returns as soon as the system receives user input. As such, this mode is generally used for video
-playback or other cases in which user input is not required.</li>
+the navigation bar hide completely. Take note that this works only for the <em>navigation bar</em>
+used by some handsets (it does <strong>not</strong> hide the system bar on tablets). The navigation
+bar returns as soon as the system receives user input. As such, this mode is generally used for
+video playback or other cases in which the whole screen is needed but user input is not
+required.</li>
</ul>
-<p>You can set each of these flags for the system bar by calling {@link
-android.view.View#setSystemUiVisibility setSystemUiVisibility()} on any view in your activity
-window. The window manager will combine (OR-together) all flags from all views in your window and
+<p>You can set each of these flags for the system bar and navigation bar by calling {@link
+android.view.View#setSystemUiVisibility setSystemUiVisibility()} on any view in your activity. The
+window manager will combine (OR-together) all flags from all views in your window and
apply them to the system UI as long as your window has input focus. When your window loses input
focus (the user navigates away from your app, or a dialog appears), your flags cease to have effect.
Similarly, if you remove those views from the view hierarchy their flags no longer apply.</p>
<p>To synchronize other events in your activity with visibility changes to the system UI (for
-example,
-hide the action bar or other UI controls when the system UI hides), you can register a {@link
-android.view.View.OnSystemUiVisibilityChangeListener} to get a callback when the visibility
-changes.</p>
+example, hide the action bar or other UI controls when the system UI hides), you should register a
+{@link android.view.View.OnSystemUiVisibilityChangeListener} to be notified when the visibility
+of the system bar or navigation bar changes.</p>
<p>See the <a
-href=”{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/OverscanActivity.html”>
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/OverscanActivity.html">
OverscanActivity</a> class for a demonstration of different system UI options.</p>
<h4>GridLayout</h4>
<p>{@link android.widget.GridLayout} is a new view group that places child views in a rectangular
-grid.
-Unlike {@link android.widget.TableLayout}, {@link android.widget.GridLayout} relies on a flat
+grid. Unlike {@link android.widget.TableLayout}, {@link android.widget.GridLayout} relies on a flat
hierarchy and does not make use of intermediate views such as table rows for providing structure.
Instead, children specify which row(s) and column(s) they should occupy (cells can span multiple
rows and/or columns), and by default are laid out sequentially across the grid’s rows and columns.
@@ -1274,7 +1376,8 @@
on children.</p>
<p>See <a
-href=”{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/index.html”>ApiDemos</a>
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/index.html">ApiDemos</a
+>
for samples using {@link android.widget.GridLayout}.</p>
@@ -1282,11 +1385,10 @@
<h4>TextureView</h4>
<p>{@link android.view.TextureView} is a new view that allows you to display a content stream, such
-as
-a video or an OpenGL scene. Although similar to {@link android.view.SurfaceView}, {@link
+as a video or an OpenGL scene. Although similar to {@link android.view.SurfaceView}, {@link
android.view.TextureView} is unique in that it behaves like a regular view, rather than creating a
separate window, so you can treat it like any other {@link android.view.View} object. For example,
-you can apply transforms, animate it using {@link android.view.ViewPropertyAnimator}, or easily
+you can apply transforms, animate it using {@link android.view.ViewPropertyAnimator}, or
adjust its opacity with {@link android.view.View#setAlpha setAlpha()}.</p>
<p>Beware that {@link android.view.TextureView} works only within a hardware accelerated window.</p>
@@ -1294,38 +1396,36 @@
<p>For more information, see the {@link android.view.TextureView} documentation.</p>
-<h4>Switch Widget</h4>
+<h4>Switch widget</h4>
<p>The new {@link android.widget.Switch} widget is a two-state toggle that users can drag to one
-side
-or the other (or simply tap) to toggle an option between two states.</p>
+side or the other (or simply tap) to toggle an option between two states.</p>
-<p>You can declare a switch in your layout with the {@code <Switch>} element. You can use the
-{@code android:textOn} and {@code android:textOff} attributes to specify the text to appear on the
-switch when in the on and off setting. The {@code android:text} attribute also allows you to place a
-label alongside the switch.</p>
+<p>You can use the {@code android:textOn} and {@code android:textOff} attributes to specify the text
+to appear on the switch when in the on and off setting. The {@code android:text} attribute also
+allows you to place a label alongside the switch.</p>
<p>For a sample using switches, see the <a
-href=”{@docRoot}resources/samples/ApiDemos/res/layout/switches.html”>switches.xml</a> layout file
+href="{@docRoot}resources/samples/ApiDemos/res/layout/switches.html">switches.xml</a> layout file
and respective <a
-href=”{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/Switches.html”>Switches
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/Switches.html">Switches
</a> activity.</p>
-<h4>Popup Menus</h4>
+<h4>Popup menus</h4>
<p>Android 3.0 introduced {@link android.widget.PopupMenu} to create short contextual menus that pop
-up
-at an anchor point you specify (usually at the point of the item selected). Android 4.0 extends the
-{@link android.widget.PopupMenu} with a couple useful features:</p>
+up at an anchor point you specify (usually at the point of the item selected). Android 4.0 extends
+the {@link android.widget.PopupMenu} with a couple useful features:</p>
<ul>
<li>You can now easily inflate the contents of a popup menu from an XML <a
-href=”{@docRoot}guide/topics/resources/menu-resource.html”>menu resource</a> with {@link
+href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a> with {@link
android.widget.PopupMenu#inflate inflate()}, passing it the menu resource ID.</li>
<li>You can also now create a {@link android.widget.PopupMenu.OnDismissListener} that receives a
callback when the menu is dismissed.</li>
</ul>
+
<h4>Preferences</h4>
<p>A new {@link android.preference.TwoStatePreference} abstract class serves as the basis for
@@ -1337,10 +1437,10 @@
android.preference.SwitchPreference} for the Wi-Fi and Bluetooth settings.</p>
-<h4>Hover Events</h4>
+<h4>Hover events</h4>
-<p>The {@link android.view.View} class now supports “hover” events to enable richer interactions
-through the use of pointer devices (such as a mouse or other device that drives an on-screen
+<p>The {@link android.view.View} class now supports “hover" events to enable richer interactions
+through the use of pointer devices (such as a mouse or other devices that drive an on-screen
cursor).</p>
<p>To receive hover events on a view, implement the {@link android.view.View.OnHoverListener} and
@@ -1360,21 +1460,19 @@
listener returns false, then the hover event will be dispatched to the parent view as usual.</p>
<p>If your application uses buttons or other widgets that change their appearance based on the
-current
-state, you can now use the {@code android:state_hovered} attribute in a <a
-href=”{@docRoot}guide/topics/resources/drawable-resource.html#StateList”>state list drawable</a> to
+current state, you can now use the {@code android:state_hovered} attribute in a <a
+href="{@docRoot}guide/topics/resources/drawable-resource.html#StateList">state list drawable</a> to
provide a different background drawable when a cursor hovers over the view.</p>
<p>For a demonstration of the new hover events, see the <a
-href=”{@docRoot}samples/ApiDemos/src/com/example/android/apis/view/Hover.html”>Hover</a> class in
+href="{@docRoot}samples/ApiDemos/src/com/example/android/apis/view/Hover.html">Hover</a> class in
ApiDemos.</p>
-<h4>Stylus and Mouse Button Input Events</h4>
+<h4>Stylus and mouse button events</h4>
<p>Android now provides APIs for receiving input from a stylus input device such as a digitizer
-tablet
-peripheral or a stylus-enabled touch screen.</p>
+tablet peripheral or a stylus-enabled touch screen.</p>
<p>Stylus input operates in a similar manner to touch or mouse input. When the stylus is in contact
with the digitizer, applications receive touch events just like they would when a finger is used to
@@ -1383,7 +1481,7 @@
are pressed.</p>
<p>Your application can distinguish between finger, mouse, stylus and eraser input by querying the
-“tool type” associated with each pointer in a {@link android.view.MotionEvent} using {@link
+“tool type" associated with each pointer in a {@link android.view.MotionEvent} using {@link
android.view.MotionEvent#getToolType getToolType()}. The currently defined tool types are: {@link
android.view.MotionEvent#TOOL_TYPE_UNKNOWN}, {@link android.view.MotionEvent#TOOL_TYPE_FINGER},
{@link android.view.MotionEvent#TOOL_TYPE_MOUSE}, {@link android.view.MotionEvent#TOOL_TYPE_STYLUS},
@@ -1391,26 +1489,24 @@
can choose to handle stylus input in different ways from finger or mouse input.</p>
<p>Your application can also query which mouse or stylus buttons are pressed by querying the “button
-state” of a {@link android.view.MotionEvent} using {@link android.view.MotionEvent#getButtonState
+state" of a {@link android.view.MotionEvent} using {@link android.view.MotionEvent#getButtonState
getButtonState()}. The currently defined button states are: {@link
-android.view.MotionEvent#BUTTON_PRIMARY}, {@link
-android.view.MotionEvent#BUTTON_SECONDARY}, {@link
-android.view.MotionEvent#BUTTON_TERTIARY}, {@link android.view.MotionEvent#BUTTON_BACK},
-and {@link android.view.MotionEvent#BUTTON_FORWARD}.
-For convenience, the back and forward mouse buttons are automatically mapped to the {@link
-android.view.KeyEvent#KEYCODE_BACK} and {@link android.view.KeyEvent#KEYCODE_FORWARD} keys. Your
-application can handle these keys to support mouse button based back and forward navigation.</p>
+android.view.MotionEvent#BUTTON_PRIMARY}, {@link android.view.MotionEvent#BUTTON_SECONDARY}, {@link
+android.view.MotionEvent#BUTTON_TERTIARY}, {@link android.view.MotionEvent#BUTTON_BACK}, and {@link
+android.view.MotionEvent#BUTTON_FORWARD}. For convenience, the back and forward mouse buttons are
+automatically mapped to the {@link android.view.KeyEvent#KEYCODE_BACK} and {@link
+android.view.KeyEvent#KEYCODE_FORWARD} keys. Your application can handle these keys to support
+mouse button based back and forward navigation.</p>
<p>In addition to precisely measuring the position and pressure of a contact, some stylus input
-devices
-also report the distance between the stylus tip and the digitizer, the stylus tilt angle, and the
-stylus orientation angle. Your application can query this information using {@link
+devices also report the distance between the stylus tip and the digitizer, the stylus tilt angle,
+and the stylus orientation angle. Your application can query this information using {@link
android.view.MotionEvent#getAxisValue getAxisValue()} with the axis codes {@link
android.view.MotionEvent#AXIS_DISTANCE}, {@link android.view.MotionEvent#AXIS_TILT}, and {@link
android.view.MotionEvent#AXIS_ORIENTATION}.</p>
<p>For a demonstration of tool types, button states and the new axis codes, see the <a
-href=”{@docRoot}samples/ApiDemos/src/com/example/android/apis/graphics/TouchPaint.html”>TouchPaint
+href="{@docRoot}samples/ApiDemos/src/com/example/android/apis/graphics/TouchPaint.html">TouchPaint
</a> class in ApiDemos.</p>
@@ -1468,40 +1564,42 @@
application has set either <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> to
-{@code “14”} or higher. Hardware acceleration generally results in smoother animations, smoother
+{@code “14"} or higher. Hardware acceleration generally results in smoother animations, smoother
scrolling, and overall better performance and response to user interaction.</p>
<p>If necessary, you can manually disable hardware acceleration with the <a
-href=”{@docRoot}guide/topics/manifest/activity-element.html#hwaccel”>{@code hardwareAccelerated}</a>
+href="{@docRoot}guide/topics/manifest/activity-element.html#hwaccel">{@code hardwareAccelerated}</a>
attribute for individual <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
<activity>}</a> elements or the <a
href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>
element. You can alternatively disable hardware acceleration for individual views by calling {@link
android.view.View#setLayerType setLayerType(LAYER_TYPE_SOFTWARE)}.</p>
+<p>For more information about hardware acceleration, including a list of unsupported drawing
+operations, see the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html">Hardware
+Acceleration</a> document.</p>
+
+
<h3 id="Jni">JNI Changes</h3>
-<p>In previous versions of Android, JNI local references weren’t indirect handles; we used direct
-pointers. This didn’t seem like a problem as long as we didn’t have a garbage collector that moves
-objects, but it was because it meant that it was possible to write buggy code that still seemed to
-work. In Android 4.0, we’ve moved to using indirect references so we can detect these bugs before we
-need third-party native code to be correct.</p>
+<p>In previous versions of Android, JNI local references weren’t indirect handles; Android used
+direct pointers. This wasn't a problem as long as the garbage collector didn't move objects, but it
+seemed to work because it made it possible to write buggy code. In Android 4.0, the system now uses
+indirect references in order to detect these bugs.</p>
-<p>The ins and outs of JNI local references are described in “Local and Global References” in
-<a href="{@docRoot}guide/practices/design/jni.html">JNI Tips</a>. In Android 4.0, <a
-href="http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html">CheckJNI</a>
-has been
-enhanced to detect these errors. Watch the <a href=”http://android-developers.blogspot.com/”>Android
-Developers Blog</a> for an upcoming post about common errors with JNI references and how you can fix
-them.</p>
+<p>The ins and outs of JNI local references are described in “Local and Global References" in <a
+href="{@docRoot}guide/practices/design/jni.html">JNI Tips</a>. In Android 4.0, <a
+href="http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html">
+CheckJNI</a> has been enhanced to detect these errors. Watch the <a
+href="http://android-developers.blogspot.com/">Android Developers Blog</a> for an upcoming post
+about common errors with JNI references and how you can fix them.</p>
<p>This change in the JNI implementation only affects apps that target Android 4.0 by setting 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> to
-{@code “14”} or higher. If you’ve set these attributes to any lower
-value, then JNI local references will behave the same as in previous versions.</p>
+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> to {@code “14"} or higher. If you’ve set these attributes to any lower value,
+then JNI local references behave the same as in previous versions.</p>
@@ -1526,7 +1624,7 @@
<ul>
<li>Updated V8 JavaScript compiler for faster performance</li>
<li>Plus other notable enhancements carried over from <a
-href=”{@docRoot}sdk/android-3.0.html”>Android
+href="{@docRoot}sdk/android-3.0.html">Android
3.0</a> are now available for handsets:
<ul>
<li>Support for fixed position elements on all pages</li>
@@ -1569,8 +1667,115 @@
+<h2 id="Honeycomb">Previous APIs</h2>
+<p>In addition to everything above, Android 4.0 naturally supports all APIs from previous releases.
+Because the Android 3.x (Honeycomb) platform is available only for large-screen devices, if you've
+been developing primarily for handsets, then you might not be aware of all the APIs added to Android
+in these recent releases.</p>
+<p>Here's a look at some of the most notable APIs you might have missed that are now available
+on handsets as well:</p>
+
+<dl>
+ <dt><a href="android-3.0.html">Android 3.0</a></dt>
+ <dd>
+ <ul>
+ <li>{@link android.app.Fragment}: A framework component that allows you to separate distinct
+elements of an activity into self-contained modules that define their own UI and lifecycle. See the
+<a href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> developer guide.</li>
+ <li>{@link android.app.ActionBar}: A replacement for the traditional title bar at the top of
+the activity window. It includes the application logo in the left corner and provides a new
+interface for menu items. See the
+<a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> developer guide.</li>
+ <li>{@link android.content.Loader}: A framework component that facilitates asynchronour
+loading of data in combination with UI components to dynamically load data without blocking the
+main thread. See the
+<a href="{@docRoot}guide/topics/fundamentals/loaders.html">Loaders</a> developer guide.</li>
+ <li>System clipboard: Applications can copy and paste data (beyond mere text) to and from
+the system-wide clipboard. Clipped data can be plain text, a URI, or an intent. See the
+<a href="{@docRoot}guide/topics/clipboard/copy-paste.html">Copy and Paste</a> developer guide.</li>
+ <li>Drag and drop: A set of APIs built into the view framework that facilitates drag and drop
+operations. See the
+<a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</li>
+ <li>An all new flexible animation framework allows you to animate arbitrary properties of any
+object (View, Drawable, Fragment, Object, or anything else) and define animation aspects such
+as duration, interpolation, repeat and more. The new framework makes Animations in Android
+simpler than ever. See the
+<a href="{@docRoot}guide/topics/graphics/property-animation.html">Property Animation</a> developer
+guide.</li>
+ <li>RenderScript graphics and compute engine: RenderScript offers a high performance 3D
+graphics rendering and compute API at the native level, which you write in the C (C99 standard),
+providing the type of performance you expect from a native environment while remaining portable
+across various CPUs and GPUs. See the
+<a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer
+guide.</li>
+ <li>Hardware accelerated 2D graphics: You can now enable the OpenGL renderer for your
+application by setting {android:hardwareAccelerated="true"} in your manifest element's <a
+href="{@docRoot}guide/topics/manifest/application-element.html"><code><application></code></a>
+element or for individual <a
+href="{@docRoot}guide/topics/manifest/activity-element.html"><code><activity></code></a>
+elements. This results
+in smoother animations, smoother scrolling, and overall better performance and response to user
+interaction.
+ <p class="note"><strong>Note:</strong> If you set your application's <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> or <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> to
+{@code "14"} or higher, hardware acceleration is enabled by default.</p></li>
+ <li>And much, much more. See the <a href="android-3.0.html">Android 3.0 Platform</a>
+notes for more information.</li>
+ </ul>
+ </dd>
+
+ <dt><a href="android-3.1.html">Android 3.1</a></dt>
+ <dd>
+ <ul>
+ <li>USB APIs: Powerful new APIs for integrating connected peripherals with
+Android applications. The APIs are based on a USB stack and services that are
+built into the platform, including support for both USB host and device interactions. See the <a
+href="{@docRoot}guide/topics/usb/index.html">USB Host and Accessory</a> developer guide.</li>
+ <li>MTP/PTP APIs: Applications can interact directly with connected cameras and other PTP
+devices to receive notifications when devices are attached and removed, manage files and storage on
+those devices, and transfer files and metadata to and from them. The MTP API implements the PTP
+(Picture Transfer Protocol) subset of the MTP (Media Transfer Protocol) specification. See the
+{@link android.mtp} documentation.</li>
+ <li>RTP APIs: Android exposes an API to its built-in RTP (Real-time Transport Protocol) stack,
+which applications can use to manage on-demand or interactive data streaming. In particular, apps
+that provide VOIP, push-to-talk, conferencing, and audio streaming can use the API to initiate
+sessions and transmit or receive data streams over any available network. See the {@link
+android.net.rtp} documentation.</li>
+ <li>Support for joysticks and other generic motion inputs.</li>
+ <li>See the <a href="android-3.1.html">Android 3.1 Platform</a>
+notes for many more new APIs.</li>
+ </ul>
+ </dd>
+
+ <dt><a href="android-3.2.html">Android 3.2</a></dt>
+ <dd>
+ <ul>
+ <li>New screens support APIs that give you more control over how your applications are
+displayed across different screen sizes. The API extends the existing screen support model with the
+ability to precisely target specific screen size ranges by dimensions, measured in
+density-independent pixel units (such as 600dp or 720dp wide), rather than by their generalized
+screen sizes (such as large or xlarge). For example, this is important in order to help you
+distinguish between a 5" device and a 7" device, which would both traditionally be bucketed as
+"large" screens. See the blog post, <a
+href="http://android-developers.blogspot.com/2011/07/new-tools-for-managing-screen-sizes.html">
+New Tools for Managing Screen Sizes</a>.</li>
+ <li>New constants for <a
+href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code <uses-feature>}</a> to
+declare landscape or portrait screen orientation requirements.</li>
+ <li>The device "screen size" configuration now changes during a screen orientation
+change. If your app targets API level 13 or higher, you must handle the {@code "screenSize"}
+configuration change if you also want to handle the {@code "orientation"} configuration change. See
+<a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
+android:configChanges}</a> for more information.</li>
+ <li>See the <a href="android-3.2.html">Android 3.2 Platform</a>
+notes for other new APIs.</li>
+ </ul>
+ </dd>
+
+</dl>
@@ -1579,32 +1784,28 @@
<h2 id="api-diff">API Differences Report</h2>
-<p>For a detailed view of all API changes in Android {@sdkPlatformVersion} (API
-Level
+<p>For a detailed view of all API changes in Android {@sdkPlatformVersion} (API Level
{@sdkPlatformApiLevel}), see the <a
-href="{@docRoot}sdk/api_diff/{@sdkPlatformApiLevel}/changes.html">API
-Differences Report</a>.</p>
-
-
+href="{@docRoot}sdk/api_diff/{@sdkPlatformApiLevel}/changes.html">API Differences Report</a>.</p>
<h2 id="api-level">API Level</h2>
-<p>The Android {@sdkPlatformVersion} platform delivers an updated version of the framework API. The
-Android {@sdkPlatformVersion} API is assigned an integer identifier —
-<strong>{@sdkPlatformApiLevel}</strong> — that is stored in the system itself. This
-identifier, called the "API Level", allows the system to correctly determine whether an application
-is compatible with the system, prior to installing the application. </p>
+<p>The Android {@sdkPlatformVersion} API is assigned an integer
+identifier—<strong>{@sdkPlatformApiLevel}</strong>—that is stored in the system itself.
+This identifier, called the "API level", allows the system to correctly determine whether an
+application is compatible with the system, prior to installing the application. </p>
<p>To use APIs introduced in Android {@sdkPlatformVersion} in your application, you need compile the
-application against the Android library that is provided in the Android {@sdkPlatformVersion} SDK
-platform. Depending on your needs, you might also need to add an
+application against an Android platform that supports API level {@sdkPlatformApiLevel} or
+higher. Depending on your needs, you might also need to add an
<code>android:minSdkVersion="{@sdkPlatformApiLevel}"</code> attribute to the
-<code><uses-sdk></code> element in the application's manifest.</p>
+<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code <uses-sdk>}</a>
+element.</p>
-<p>For more information about how to use API Level, see the <a
-href="{@docRoot}guide/appendix/api-levels.html">API Levels</a> document. </p>
+<p>For more information, see the <a href="{@docRoot}guide/appendix/api-levels.html">API Levels</a>
+document. </p>
<h2 id="apps">Built-in Applications</h2>
@@ -1619,6 +1820,7 @@
<li>API Demos</li>
<li>Browser</li>
<li>Calculator</li>
+<li>Calendar</li>
<li>Camera</li>
<li>Clock</li>
<li>Custom Locale</li>
@@ -1637,7 +1839,7 @@
<li>Phone</li>
<li>Search</li>
<li>Settings</li>
-<li>Spare Parts</li>
+<li>Speech Recorder</li>
<li>Speech Recorder</li>
<li>Widget Preview</li>
</ul>
@@ -1648,13 +1850,10 @@
<h2 id="locs" style="margin-top:.75em;">Locales</h2>
-<p>The system image included in the downloadable SDK platform provides a variety
-of
-built-in locales. In some cases, region-specific strings are available for the
-locales. In other cases, a default version of the language is used. The
-languages that are available in the Android 3.0 system
-image are listed below (with <em>language</em>_<em>country/region</em> locale
-descriptor).</p>
+<p>The system image included in the downloadable SDK platform provides a variety of built-in
+locales. In some cases, region-specific strings are available for the locales. In other cases, a
+default version of the language is used. The languages that are available in the Android 3.0 system
+image are listed below (with <em>language</em>_<em>country/region</em> locale descriptor).</p>
<table style="border:0;padding-bottom:0;margin-bottom:0;">
<tr>
@@ -1731,15 +1930,45 @@
<h2 id="skins">Emulator Skins</h2>
-<p>The downloadable platform includes the following emulator skin:</p>
+<p>The downloadable platform includes the following emulator skins:</p>
<ul>
<li>
- WVGA800 (1280x800, extra high density, normal screen)
+ QVGA (240x320, low density, small screen)
+ </li>
+ <li>
+ WQVGA400 (240x400, low density, normal screen)
+ </li>
+ <li>
+ WQVGA432 (240x432, low density, normal screen)
+ </li>
+ <li>
+ HVGA (320x480, medium density, normal screen)
+ </li>
+ <li>
+ WVGA800 (480x800, high density, normal screen)
+ </li>
+ <li>
+ WVGA854 (480x854 high density, normal screen)
+ </li>
+ <li>
+ WXGA720 (1280x720, extra-high density, normal screen) <span class="new">new</span>
+ </li>
+ <li>
+ WSVGA (1024x600, medium density, large screen) <span class="new">new</span>
+ </li>
+ <li>
+ WXGA (1280x800, medium density, xlarge screen)
</li>
</ul>
-<p>For more information about how to develop an application that displays
-and functions properly on all Android-powered devices, see <a
-href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
-Screens</a>.</p>
+<p>To test your application on an emulator that represents the latest Android device, you can create
+an AVD with the new WXGA720 skin (it's an xhdpi, normal screen device). Note that the emulator
+currently doesn't support the new on-screen navigation bar for devices without hardware navigation
+buttons, so when using this skin, you must use keyboard keys <em>Home</em> for the Home button,
+<em>ESC</em> for the Back button, and <em>F2</em> or <em>Page-up</em> for the Menu button.</p>
+
+<p>However, due to performance issues in the emulator when running high-resolution screens such as
+the one for the WXGA720 skin, we recommend that you primarily use the traditional WVGA800 skin
+(hdpi, normal screen) to test your application.</p>
+
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index dab5b29..0d14f79 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -66,6 +66,9 @@
<p>The sections below provide notes about successive releases of
the ADT Plugin, as denoted by revision number. </p>
+<p>For a summary of all known issues in ADT, see <a
+href="http://tools.android.com/release/knownissues">http://tools.android.com/release/knownissues</a>.</p>
+
<script type="text/javascript">
function toggleDiv(link) {
var toggleable = $(link).parent();
diff --git a/docs/html/sdk/tools-notes.jd b/docs/html/sdk/tools-notes.jd
index 6cb246c..f5b61ee 100644
--- a/docs/html/sdk/tools-notes.jd
+++ b/docs/html/sdk/tools-notes.jd
@@ -23,6 +23,9 @@
Tools you are using, refer to the "Installed Packages" listing in the Android SDK
and AVD Manager. </p>
+<p>For a summary of all known issues in SDK Tools, see <a
+href="http://tools.android.com/release/knownissues">http://tools.android.com/release/knownissues</a>.</p>
+
<script type="text/javascript">
function toggleDiv(link) {
var toggleable = $(link).parent();
diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp
index babd2c0..d2e5627 100644
--- a/libs/gui/ISurfaceTexture.cpp
+++ b/libs/gui/ISurfaceTexture.cpp
@@ -58,13 +58,16 @@
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(bufferIdx);
- remote()->transact(REQUEST_BUFFER, data, &reply);
+ status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
bool nonNull = reply.readInt32();
if (nonNull) {
*buf = new GraphicBuffer();
reply.read(**buf);
}
- status_t result = reply.readInt32();
+ result = reply.readInt32();
return result;
}
@@ -73,9 +76,12 @@
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(bufferCount);
- remote()->transact(SET_BUFFER_COUNT, data, &reply);
- status_t err = reply.readInt32();
- return err;
+ status_t result =remote()->transact(SET_BUFFER_COUNT, data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ result = reply.readInt32();
+ return result;
}
virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
@@ -86,9 +92,12 @@
data.writeInt32(h);
data.writeInt32(format);
data.writeInt32(usage);
- remote()->transact(DEQUEUE_BUFFER, data, &reply);
+ status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
*buf = reply.readInt32();
- int result = reply.readInt32();
+ result = reply.readInt32();
return result;
}
@@ -98,11 +107,14 @@
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(buf);
data.writeInt64(timestamp);
- remote()->transact(QUEUE_BUFFER, data, &reply);
+ status_t result = remote()->transact(QUEUE_BUFFER, data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
*outWidth = reply.readInt32();
*outHeight = reply.readInt32();
*outTransform = reply.readInt32();
- status_t result = reply.readInt32();
+ result = reply.readInt32();
return result;
}
@@ -120,8 +132,11 @@
data.writeFloat(reg.top);
data.writeFloat(reg.right);
data.writeFloat(reg.bottom);
- remote()->transact(SET_CROP, data, &reply);
- status_t result = reply.readInt32();
+ status_t result = remote()->transact(SET_CROP, data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ result = reply.readInt32();
return result;
}
@@ -129,8 +144,11 @@
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(transform);
- remote()->transact(SET_TRANSFORM, data, &reply);
- status_t result = reply.readInt32();
+ status_t result = remote()->transact(SET_TRANSFORM, data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ result = reply.readInt32();
return result;
}
@@ -138,8 +156,11 @@
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(mode);
- remote()->transact(SET_SCALING_MODE, data, &reply);
- status_t result = reply.readInt32();
+ status_t result = remote()->transact(SET_SCALING_MODE, data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ result = reply.readInt32();
return result;
}
@@ -147,9 +168,12 @@
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(what);
- remote()->transact(QUERY, data, &reply);
+ status_t result = remote()->transact(QUERY, data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
value[0] = reply.readInt32();
- status_t result = reply.readInt32();
+ result = reply.readInt32();
return result;
}
@@ -157,8 +181,11 @@
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(enabled);
- remote()->transact(SET_SYNCHRONOUS_MODE, data, &reply);
- status_t result = reply.readInt32();
+ status_t result = remote()->transact(SET_SYNCHRONOUS_MODE, data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ result = reply.readInt32();
return result;
}
@@ -167,11 +194,14 @@
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(api);
- remote()->transact(CONNECT, data, &reply);
+ status_t result = remote()->transact(CONNECT, data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
*outWidth = reply.readInt32();
*outHeight = reply.readInt32();
*outTransform = reply.readInt32();
- status_t result = reply.readInt32();
+ result = reply.readInt32();
return result;
}
@@ -179,8 +209,11 @@
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(api);
- remote()->transact(DISCONNECT, data, &reply);
- status_t result = reply.readInt32();
+ status_t result =remote()->transact(DISCONNECT, data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ result = reply.readInt32();
return result;
}
};
diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp
index d719efb..4774a58 100644
--- a/libs/gui/SensorManager.cpp
+++ b/libs/gui/SensorManager.cpp
@@ -78,9 +78,23 @@
sp<SensorEventQueue> SensorManager::createEventQueue()
{
- sp<SensorEventQueue> result = new SensorEventQueue(
- mSensorServer->createSensorEventConnection());
- return result;
+ sp<SensorEventQueue> queue;
+
+ if (mSensorServer == NULL) {
+ LOGE("createEventQueue: mSensorSever is NULL");
+ return queue;
+ }
+
+ sp<ISensorEventConnection> connection =
+ mSensorServer->createSensorEventConnection();
+ if (connection == NULL) {
+ LOGE("createEventQueue: connection is NULL");
+ return queue;
+ }
+
+ queue = new SensorEventQueue(connection);
+
+ return queue;
}
// ----------------------------------------------------------------------------
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index ce587b3..693b7b8 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -75,7 +75,7 @@
}
// This test probably doesn't belong here.
-TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersFail) {
+TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) {
sp<ANativeWindow> anw(mSurface);
// Verify the screenshot works with no protected buffers.
@@ -114,31 +114,8 @@
}
heap = 0;
w = h = fmt = 0;
- ASSERT_EQ(INVALID_OPERATION, sf->captureScreen(0, &heap, &w, &h, &fmt,
+ ASSERT_EQ(NO_ERROR, sf->captureScreen(0, &heap, &w, &h, &fmt,
64, 64, 0, 0x7fffffff));
- ASSERT_TRUE(heap == NULL);
-
- // XXX: This should not be needed, but it seems that the new buffers don't
- // correctly show up after the upcoming dequeue/lock/queue loop without it.
- // We should look into this at some point.
- ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(anw.get(), 3));
-
- // Un-set the PROTECTED usage bit and verify that the screenshot works
- // again. Note that we have to change the buffers geometry to ensure that
- // the buffers get reallocated, as the new usage bits are a subset of the
- // old.
- ASSERT_EQ(NO_ERROR, native_window_set_usage(anw.get(), 0));
- ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(anw.get(), 32, 32, 0));
- for (int i = 0; i < 4; i++) {
- // Loop to make sure SurfaceFlinger has retired a protected buffer.
- ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &buf));
- ASSERT_EQ(NO_ERROR, anw->lockBuffer(anw.get(), buf));
- ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf));
- }
- heap = 0;
- w = h = fmt = 0;
- ASSERT_EQ(NO_ERROR, sf->captureScreen(0, &heap, &w, &h, &fmt, 64, 64, 0,
- 0x7fffffff));
ASSERT_TRUE(heap != NULL);
}
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 4f4f929..e0c2b3b 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -85,8 +85,7 @@
private static final String TAG = "AudioService";
/** Debug remote control client/display feature */
- // TODO set to false before release
- protected static final boolean DEBUG_RC = true;
+ protected static final boolean DEBUG_RC = false;
/** How long to delay before persisting a change in volume/ringer mode. */
private static final int PERSIST_DELAY = 3000;
@@ -369,6 +368,8 @@
intentFilter.addAction(Intent.ACTION_USB_DGTL_HEADSET_PLUG);
intentFilter.addAction(Intent.ACTION_HDMI_AUDIO_PLUG);
intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
+ intentFilter.addAction(Intent.ACTION_SCREEN_ON);
+ intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
context.registerReceiver(mReceiver, intentFilter);
// Register for package removal intent broadcasts for media button receiver persistence
@@ -2566,6 +2567,10 @@
removeMediaButtonReceiverForPackage(packageName);
}
}
+ } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
+ AudioSystem.setParameters("screen_state=on");
+ } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+ AudioSystem.setParameters("screen_state=off");
}
}
}
diff --git a/packages/BackupRestoreConfirmation/res/values/strings.xml b/packages/BackupRestoreConfirmation/res/values/strings.xml
index e91c6e2..5c90fd0 100644
--- a/packages/BackupRestoreConfirmation/res/values/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values/strings.xml
@@ -35,8 +35,12 @@
<!-- Text for message to user that they must enter their predefined backup password in order to perform this operation. -->
<string name="current_password_text">Please enter your current backup password below:</string>
+ <!-- Text for message to user that they must enter their device encryption password in order to perform this restore operation. -->
+ <string name="device_encryption_restore_text">Please enter your device encryption password below.</string>
+ <!-- Text for message to user that they must enter their device encryption password in order to perform this backup operation. -->
+ <string name="device_encryption_backup_text">Please enter your device encryption password below. This will also be used to encrypt the backup archive.</string>
- <!-- Text for message to user that they can must enter an encryption password to use for the full backup operation. -->
+ <!-- Text for message to user that they must enter an encryption password to use for the full backup operation. -->
<string name="backup_enc_password_text">Please enter a password to use for encrypting the full backup data. If this is left blank, your current backup password will be used:</string>
<!-- Text for message to user that they may optionally supply an encryption password to use for a full backup operation. -->
<string name="backup_enc_password_optional">If you wish to encrypt the full backup data, enter a password below:</string>
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index fbdf3cc..7f1d059 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -27,6 +27,8 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.storage.IMountService;
+import android.util.Log;
import android.util.Slog;
import android.view.View;
import android.widget.Button;
@@ -60,8 +62,10 @@
Handler mHandler;
IBackupManager mBackupManager;
+ IMountService mMountService;
FullObserver mObserver;
int mToken;
+ boolean mIsEncrypted;
boolean mDidAcknowledge;
TextView mStatusView;
@@ -152,6 +156,7 @@
}
mBackupManager = IBackupManager.Stub.asInterface(ServiceManager.getService(Context.BACKUP_SERVICE));
+ mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
mHandler = new ObserverHandler(getApplicationContext());
final Object oldObserver = getLastNonConfigurationInstance();
@@ -174,8 +179,23 @@
mEncPassword = (TextView) findViewById(R.id.enc_password);
TextView curPwDesc = (TextView) findViewById(R.id.password_desc);
- // We vary the password prompt depending on whether one is predefined
- if (!haveBackupPassword()) {
+ // We vary the password prompt depending on whether one is predefined, and whether
+ // the device is encrypted.
+ mIsEncrypted = deviceIsEncrypted();
+ if (mIsEncrypted) {
+ Log.d(TAG, "Device is encrypted: requiring encryption pw");
+ TextView pwPrompt = (TextView) findViewById(R.id.password_desc);
+ // this password is mandatory; we hide the other options during backup
+ if (layoutId == R.layout.confirm_backup) {
+ pwPrompt.setText(R.string.device_encryption_backup_text);
+ TextView tv = (TextView) findViewById(R.id.enc_password);
+ tv.setVisibility(View.GONE);
+ tv = (TextView) findViewById(R.id.enc_password_desc);
+ tv.setVisibility(View.GONE);
+ } else {
+ pwPrompt.setText(R.string.device_encryption_restore_text);
+ }
+ } else if (!haveBackupPassword()) {
curPwDesc.setVisibility(View.GONE);
mCurPassword.setVisibility(View.GONE);
if (layoutId == R.layout.confirm_backup) {
@@ -226,10 +246,12 @@
mDidAcknowledge = true;
try {
+ CharSequence encPassword = (mIsEncrypted)
+ ? mCurPassword.getText() : mEncPassword.getText();
mBackupManager.acknowledgeFullBackupOrRestore(mToken,
allow,
String.valueOf(mCurPassword.getText()),
- String.valueOf(mEncPassword.getText()),
+ String.valueOf(encPassword),
mObserver);
} catch (RemoteException e) {
// TODO: bail gracefully if we can't contact the backup manager
@@ -237,6 +259,16 @@
}
}
+ boolean deviceIsEncrypted() {
+ try {
+ return (mMountService.getEncryptionState() != IMountService.ENCRYPTION_STATE_NONE);
+ } catch (Exception e) {
+ // If we can't talk to the mount service we have a serious problem; fail
+ // "secure" i.e. assuming that the device is encrypted.
+ return true;
+ }
+ }
+
boolean haveBackupPassword() {
try {
return mBackupManager.hasBackupPassword();
diff --git a/packages/SystemUI/res/layout/global_screenshot.xml b/packages/SystemUI/res/layout/global_screenshot.xml
index 6cb8799..6d70135 100644
--- a/packages/SystemUI/res/layout/global_screenshot.xml
+++ b/packages/SystemUI/res/layout/global_screenshot.xml
@@ -25,6 +25,7 @@
android:id="@+id/global_screenshot_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_gravity="center"
android:background="@drawable/global_screenshot_background"
android:visibility="gone">
<ImageView android:id="@+id/global_screenshot"
@@ -32,9 +33,4 @@
android:layout_height="wrap_content"
android:adjustViewBounds="true" />
</FrameLayout>
- <ImageView android:id="@+id/global_screenshot_flash"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="#FFFFFFFF"
- android:visibility="gone" />
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index a63893e..af2c93c 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -77,7 +77,6 @@
android:layout_height="match_parent"
android:singleLine="true"
android:paddingRight="6dip"
- android:textSize="16sp"
android:gravity="center_vertical|left"
/>
</LinearLayout>
@@ -89,17 +88,19 @@
android:animationCache="false"
android:orientation="horizontal" >
<ImageSwitcher android:id="@+id/tickerIcon"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_marginRight="8dip"
+ android:layout_width="@dimen/status_bar_icon_size"
+ android:layout_height="@dimen/status_bar_icon_size"
+ android:layout_marginRight="4dip"
>
<com.android.systemui.statusbar.AnimatedImageView
- android:layout_width="25dip"
- android:layout_height="25dip"
+ android:layout_width="@dimen/status_bar_icon_size"
+ android:layout_height="@dimen/status_bar_icon_size"
+ android:scaleType="center"
/>
<com.android.systemui.statusbar.AnimatedImageView
- android:layout_width="25dip"
- android:layout_height="25dip"
+ android:layout_width="@dimen/status_bar_icon_size"
+ android:layout_height="@dimen/status_bar_icon_size"
+ android:scaleType="center"
/>
</ImageSwitcher>
<com.android.systemui.statusbar.phone.TickerView android:id="@+id/tickerText"
@@ -109,13 +110,13 @@
android:paddingTop="2dip"
android:paddingRight="10dip">
<TextView
- android:textAppearance="@*android:style/TextAppearance.StatusBar.Ticker"
+ android:textAppearance="@style/TextAppearance.StatusBar.PhoneTicker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
/>
<TextView
- android:textAppearance="@*android:style/TextAppearance.StatusBar.Ticker"
+ android:textAppearance="@style/TextAppearance.StatusBar.PhoneTicker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 3e2def5..cd4e37c 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -35,7 +35,7 @@
android:background="@drawable/notification_header_bg"
>
<com.android.systemui.statusbar.policy.DateView android:id="@+id/date"
- android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+ android:textAppearance="@style/TextAppearance.StatusBar.Date"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 65d5138..a717b57 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -168,10 +168,20 @@
<!-- Compatibility mode help screen: body text. [CHAR LIMIT=150] -->
<string name="compat_mode_help_body">When an app was designed for a smaller screen, a zoom control will appear by the clock.</string>
- <!-- toast message displayed when a screenshot is saved to the Gallery. -->
- <string name="screenshot_saving_toast">Screenshot saved to Gallery</string>
- <!-- toast message displayed when we fail to take a screenshot. -->
- <string name="screenshot_failed_toast">Could not save screenshot. External storage may be in use.</string>
+ <!-- Notification ticker displayed when a screenshot is being saved to the Gallery. [CHAR LIMIT=30] -->
+ <string name="screenshot_saving_ticker">Saving...</string>
+ <!-- Notification title displayed when a screenshot is being saved to the Gallery. [CHAR LIMIT=50] -->
+ <string name="screenshot_saving_title">Saving screenshot...</string>
+ <!-- Notification text displayed when a screenshot is being saved to the Gallery. [CHAR LIMIT=100] -->
+ <string name="screenshot_saving_text">Please wait for screenshot to be saved</string>
+ <!-- Notification title displayed when a screenshot is saved to the Gallery. [CHAR LIMIT=50] -->
+ <string name="screenshot_saved_title">Screenshot captured</string>
+ <!-- Notification text displayed when a screenshot is saved to the Gallery. [CHAR LIMIT=100] -->
+ <string name="screenshot_saved_text">Touch to view your screenshot</string>
+ <!-- Notification title displayed when we fail to take a screenshot. [CHAR LIMIT=50] -->
+ <string name="screenshot_failed_title">Screenshot failed</string>
+ <!-- Notification text displayed when we fail to take a screenshot. [CHAR LIMIT=100] -->
+ <string name="screenshot_failed_text">Failed to save screenshot. External storage may be in use.</string>
<!-- Title for the USB function chooser in UsbPreferenceActivity. [CHAR LIMIT=30] -->
<string name="usb_preference_title">USB file transfer options</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 3d49cd1..dc5c540 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -41,6 +41,13 @@
</style>
<style name="TextAppearance.StatusBar.Clock" parent="@*android:style/TextAppearance.StatusBar.Icon">
+ <!-- Note: must be dp to fit in status bar -->
+ <item name="android:textSize">16dp</item>
+ <item name="android:textStyle">normal</item>
+ <item name="android:textColor">@android:color/holo_blue_light</item>
+ </style>
+
+ <style name="TextAppearance.StatusBar.Date" parent="@*android:style/TextAppearance.StatusBar.Icon">
<item name="android:textSize">16sp</item>
<item name="android:textStyle">normal</item>
<item name="android:textColor">@android:color/holo_blue_light</item>
@@ -69,4 +76,10 @@
<item name="android:windowExitAnimation">@anim/priority_alert_exit</item>
</style>
+ <style name="TextAppearance.StatusBar.PhoneTicker"
+ parent="@*android:style/TextAppearance.StatusBar.Ticker">
+ <!-- Note: must be dp to fit in status bar -->
+ <item name="android:textSize">14dp</item>
+ </style>
+
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 3fa3078..cf073c4 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -19,27 +19,27 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
-import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.AsyncTask;
-import android.os.Binder;
import android.os.Environment;
import android.os.ServiceManager;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
-import android.util.Log;
import android.view.Display;
import android.view.IWindowManager;
import android.view.LayoutInflater;
@@ -50,16 +50,11 @@
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
-import android.widget.TextView;
-import android.widget.Toast;
import com.android.systemui.R;
import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
import java.io.OutputStream;
-import java.lang.Thread;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -83,6 +78,46 @@
private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
private static final String SCREENSHOT_FILE_PATH_TEMPLATE = "%s/%s/%s";
+ private int mNotificationId;
+ private NotificationManager mNotificationManager;
+ private Notification.Builder mNotificationBuilder;
+ private Intent mLaunchIntent;
+ private String mImageDir;
+ private String mImageFileName;
+ private String mImageFilePath;
+ private String mImageDate;
+ private long mImageTime;
+
+ SaveImageInBackgroundTask(Context context, NotificationManager nManager, int nId) {
+ Resources r = context.getResources();
+
+ // Prepare all the output metadata
+ mImageTime = System.currentTimeMillis();
+ mImageDate = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date(mImageTime));
+ mImageDir = Environment.getExternalStoragePublicDirectory(
+ Environment.DIRECTORY_PICTURES).getAbsolutePath();
+ mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, mImageDate);
+ mImageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, mImageDir,
+ SCREENSHOTS_DIR_NAME, mImageFileName);
+
+ // Show the intermediate notification
+ mLaunchIntent = new Intent(Intent.ACTION_VIEW);
+ mLaunchIntent.setDataAndType(Uri.fromFile(new File(mImageFilePath)), "image/png");
+ mLaunchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mNotificationId = nId;
+ mNotificationBuilder = new Notification.Builder(context)
+ .setTicker(r.getString(R.string.screenshot_saving_ticker))
+ .setContentTitle(r.getString(R.string.screenshot_saving_title))
+ .setContentText(r.getString(R.string.screenshot_saving_text))
+ .setSmallIcon(android.R.drawable.ic_menu_gallery)
+ .setWhen(System.currentTimeMillis());
+ Notification n = mNotificationBuilder.getNotification();
+ n.flags |= Notification.FLAG_NO_CLEAR;
+
+ mNotificationManager = nManager;
+ mNotificationManager.notify(nId, n);
+ }
+
@Override
protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) {
if (params.length != 1) return null;
@@ -91,23 +126,15 @@
Bitmap image = params[0].image;
try {
- long currentTime = System.currentTimeMillis();
- String date = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date(currentTime));
- String imageDir = Environment.getExternalStoragePublicDirectory(
- Environment.DIRECTORY_PICTURES).getAbsolutePath();
- String imageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, date);
- String imageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, imageDir,
- SCREENSHOTS_DIR_NAME, imageFileName);
-
// Save the screenshot to the MediaStore
ContentValues values = new ContentValues();
ContentResolver resolver = context.getContentResolver();
- values.put(MediaStore.Images.ImageColumns.DATA, imageFilePath);
- values.put(MediaStore.Images.ImageColumns.TITLE, imageFileName);
- values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, imageFileName);
- values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, currentTime);
- values.put(MediaStore.Images.ImageColumns.DATE_ADDED, currentTime);
- values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, currentTime);
+ values.put(MediaStore.Images.ImageColumns.DATA, mImageFilePath);
+ values.put(MediaStore.Images.ImageColumns.TITLE, mImageFileName);
+ values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, mImageFileName);
+ values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, mImageTime);
+ values.put(MediaStore.Images.ImageColumns.DATE_ADDED, mImageTime);
+ values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, mImageTime);
values.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/png");
Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
@@ -118,7 +145,7 @@
// update file size in the database
values.clear();
- values.put(MediaStore.Images.ImageColumns.SIZE, new File(imageFilePath).length());
+ values.put(MediaStore.Images.ImageColumns.SIZE, new File(mImageFilePath).length());
resolver.update(uri, values, null, null);
params[0].result = 0;
@@ -135,12 +162,22 @@
protected void onPostExecute(SaveImageInBackgroundData params) {
if (params.result > 0) {
// Show a message that we've failed to save the image to disk
- Toast.makeText(params.context, R.string.screenshot_failed_toast,
- Toast.LENGTH_SHORT).show();
+ GlobalScreenshot.notifyScreenshotError(params.context, mNotificationManager);
} else {
- // Show a message that we've saved the screenshot to disk
- Toast.makeText(params.context, R.string.screenshot_saving_toast,
- Toast.LENGTH_SHORT).show();
+ // Show the final notification to indicate screenshot saved
+ Resources r = params.context.getResources();
+
+ mNotificationBuilder
+ .setTicker(r.getString(R.string.screenshot_saved_title))
+ .setContentTitle(r.getString(R.string.screenshot_saved_title))
+ .setContentText(r.getString(R.string.screenshot_saved_text))
+ .setContentIntent(PendingIntent.getActivity(params.context, 0, mLaunchIntent, 0))
+ .setWhen(System.currentTimeMillis())
+ .setAutoCancel(true);
+
+ Notification n = mNotificationBuilder.getNotification();
+ n.flags &= ~Notification.FLAG_NO_CLEAR;
+ mNotificationManager.notify(mNotificationId, n);
}
params.finisher.run();
};
@@ -154,22 +191,21 @@
*/
class GlobalScreenshot {
private static final String TAG = "GlobalScreenshot";
- private static final int SCREENSHOT_FADE_IN_DURATION = 900;
+ private static final int SCREENSHOT_NOTIFICATION_ID = 789;
+ private static final int SCREENSHOT_FADE_IN_DURATION = 500;
private static final int SCREENSHOT_FADE_OUT_DELAY = 1000;
- private static final int SCREENSHOT_FADE_OUT_DURATION = 450;
- private static final int TOAST_FADE_IN_DURATION = 500;
- private static final int TOAST_FADE_OUT_DELAY = 1000;
- private static final int TOAST_FADE_OUT_DURATION = 500;
+ private static final int SCREENSHOT_FADE_OUT_DURATION = 300;
private static final float BACKGROUND_ALPHA = 0.65f;
- private static final float SCREENSHOT_SCALE = 0.85f;
- private static final float SCREENSHOT_MIN_SCALE = 0.7f;
- private static final float SCREENSHOT_ROTATION = -6.75f; // -12.5f;
+ private static final float SCREENSHOT_SCALE_FUDGE = 0.075f; // To account for the border padding
+ private static final float SCREENSHOT_SCALE = 0.8f;
+ private static final float SCREENSHOT_MIN_SCALE = 0.775f;
private Context mContext;
private LayoutInflater mLayoutInflater;
private IWindowManager mIWindowManager;
private WindowManager mWindowManager;
private WindowManager.LayoutParams mWindowLayoutParams;
+ private NotificationManager mNotificationManager;
private Display mDisplay;
private DisplayMetrics mDisplayMetrics;
private Matrix mDisplayMatrix;
@@ -182,10 +218,15 @@
private AnimatorSet mScreenshotAnimation;
- // General use cubic interpolator
- final TimeInterpolator mCubicInterpolator = new TimeInterpolator() {
+ // Fade interpolators
+ final TimeInterpolator mFadeInInterpolator = new TimeInterpolator() {
public float getInterpolation(float t) {
- return t*t*t;
+ return (float) Math.pow(t, 1.5f);
+ }
+ };
+ final TimeInterpolator mFadeOutInterpolator = new TimeInterpolator() {
+ public float getInterpolation(float t) {
+ return (float) t;
}
};
// The interpolator used to control the background alpha at the start of the animation
@@ -237,6 +278,8 @@
PixelFormat.TRANSLUCENT);
mWindowLayoutParams.setTitle("ScreenshotAnimation");
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ mNotificationManager =
+ (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mDisplay = mWindowManager.getDefaultDisplay();
}
@@ -248,7 +291,8 @@
data.context = mContext;
data.image = mScreenBitmap;
data.finisher = finisher;
- new SaveImageInBackgroundTask().execute(data);
+ new SaveImageInBackgroundTask(mContext, mNotificationManager, SCREENSHOT_NOTIFICATION_ID)
+ .execute(data);
}
/**
@@ -300,8 +344,7 @@
// If we couldn't take the screenshot, notify the user
if (mScreenBitmap == null) {
- Toast.makeText(mContext, R.string.screenshot_failed_toast,
- Toast.LENGTH_SHORT).show();
+ notifyScreenshotError(mContext, mNotificationManager);
finisher.run();
return;
}
@@ -341,12 +384,13 @@
}
private ValueAnimator createScreenshotFadeInAnimation() {
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
- anim.setInterpolator(mCubicInterpolator);
+ anim.setInterpolator(mFadeInInterpolator);
anim.setDuration(SCREENSHOT_FADE_IN_DURATION);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mBackgroundView.setVisibility(View.VISIBLE);
+ mScreenshotContainerView.setTranslationY(0f);
mScreenshotContainerView.setVisibility(View.VISIBLE);
}
});
@@ -356,18 +400,19 @@
float t = ((Float) animation.getAnimatedValue()).floatValue();
mBackgroundView.setAlpha(mBackgroundViewAlphaInterpolator.getInterpolation(t) *
BACKGROUND_ALPHA);
- float scaleT = SCREENSHOT_SCALE + (1f - t) * SCREENSHOT_SCALE;
+ float scaleT = SCREENSHOT_SCALE
+ + (1f - t) * (1f - SCREENSHOT_SCALE)
+ + SCREENSHOT_SCALE_FUDGE;
mScreenshotContainerView.setAlpha(t*t*t*t);
mScreenshotContainerView.setScaleX(scaleT);
mScreenshotContainerView.setScaleY(scaleT);
- mScreenshotContainerView.setRotation(t * SCREENSHOT_ROTATION);
}
});
return anim;
}
private ValueAnimator createScreenshotFadeOutAnimation() {
ValueAnimator anim = ValueAnimator.ofFloat(1f, 0f);
- anim.setInterpolator(mCubicInterpolator);
+ anim.setInterpolator(mFadeOutInterpolator);
anim.setStartDelay(SCREENSHOT_FADE_OUT_DELAY);
anim.setDuration(SCREENSHOT_FADE_OUT_DURATION);
anim.addListener(new AnimatorListenerAdapter() {
@@ -381,8 +426,9 @@
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float t = ((Float) animation.getAnimatedValue()).floatValue();
- float scaleT = SCREENSHOT_MIN_SCALE +
- t*(SCREENSHOT_SCALE - SCREENSHOT_MIN_SCALE);
+ float scaleT = SCREENSHOT_MIN_SCALE
+ + t * (SCREENSHOT_SCALE - SCREENSHOT_MIN_SCALE)
+ + SCREENSHOT_SCALE_FUDGE;
mScreenshotContainerView.setAlpha(t);
mScreenshotContainerView.setScaleX(scaleT);
mScreenshotContainerView.setScaleY(scaleT);
@@ -391,4 +437,19 @@
});
return anim;
}
+
+ static void notifyScreenshotError(Context context, NotificationManager nManager) {
+ Resources r = context.getResources();
+
+ // Clear all existing notification, compose the new notification and show it
+ Notification n = new Notification.Builder(context)
+ .setTicker(r.getString(R.string.screenshot_failed_title))
+ .setContentTitle(r.getString(R.string.screenshot_failed_title))
+ .setContentText(r.getString(R.string.screenshot_failed_text))
+ .setSmallIcon(android.R.drawable.ic_menu_report_image)
+ .setWhen(System.currentTimeMillis())
+ .setAutoCancel(true)
+ .getNotification();
+ nManager.notify(SCREENSHOT_NOTIFICATION_ID, n);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index 05ff8be..d112b5e 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -17,26 +17,12 @@
package com.android.systemui.screenshot;
import android.app.Service;
-import android.app.AlertDialog;
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
-import android.net.Uri;
-import android.hardware.usb.UsbAccessory;
-import android.hardware.usb.UsbManager;
-import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
-
-import com.android.systemui.R;
public class TakeScreenshotService extends Service {
private static final String TAG = "TakeScreenshotService";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
index 5959537..2e1803e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
@@ -146,4 +146,26 @@
mDoNotDisturb = new DoNotDisturb(mContext);
}
+
+ protected View updateNotificationVetoButton(View row, StatusBarNotification n) {
+ View vetoButton = row.findViewById(R.id.veto);
+ if (n.isClearable()) {
+ final String _pkg = n.pkg;
+ final String _tag = n.tag;
+ final int _id = n.id;
+ vetoButton.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ try {
+ mBarService.onNotificationClear(_pkg, _tag, _id);
+ } catch (RemoteException ex) {
+ // system process is dead if we're here.
+ }
+ }
+ });
+ vetoButton.setVisibility(View.VISIBLE);
+ } else {
+ vetoButton.setVisibility(View.GONE);
+ }
+ return vetoButton;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 9c8c229..4e9b411 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -94,7 +94,7 @@
public static final boolean DUMPTRUCK = true; // extra dumpsys info
// additional instrumentation for testing purposes; intended to be left on during development
- public static final boolean CHATTY = DEBUG || true;
+ public static final boolean CHATTY = DEBUG;
public static final String ACTION_STATUSBAR_START
= "com.android.internal.policy.statusbar.START";
@@ -618,6 +618,10 @@
boolean orderUnchanged = notification.notification.when==oldNotification.notification.when
&& notification.priority == oldNotification.priority;
// priority now encompasses isOngoing()
+
+ boolean updateTicker = notification.notification.tickerText != null
+ && !TextUtils.equals(notification.notification.tickerText,
+ oldEntry.notification.notification.tickerText);
boolean isFirstAnyway = rowParent.indexOfChild(oldEntry.row) == 0;
if (contentsUnchanged && (orderUnchanged || isFirstAnyway)) {
if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key);
@@ -665,10 +669,13 @@
addNotificationViews(key, notification);
}
+ // Update the veto button accordingly (and as a result, whether this row is
+ // swipe-dismissable)
+ updateNotificationVetoButton(oldEntry.row, notification);
+
// Restart the ticker if it's still running
- if (notification.notification.tickerText != null
- && !TextUtils.equals(notification.notification.tickerText,
- oldEntry.notification.notification.tickerText)) {
+ if (updateTicker) {
+ mTicker.halt();
tick(notification);
}
@@ -711,23 +718,7 @@
View row = inflater.inflate(R.layout.status_bar_notification_row, parent, false);
// wire up the veto button
- View vetoButton = row.findViewById(R.id.veto);
- if (notification.isClearable()) {
- final String _pkg = notification.pkg;
- final String _tag = notification.tag;
- final int _id = notification.id;
- vetoButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- try {
- mBarService.onNotificationClear(_pkg, _tag, _id);
- } catch (RemoteException ex) {
- // system process is dead if we're here.
- }
- }
- });
- } else {
- vetoButton.setVisibility(View.GONE);
- }
+ View vetoButton = updateNotificationVetoButton(row, notification);
vetoButton.setContentDescription(mContext.getString(
R.string.accessibility_remove_notification));
@@ -897,23 +888,7 @@
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.status_bar_notification_row, parent, false);
- View vetoButton = row.findViewById(R.id.veto);
- if (entry.notification.isClearable()) {
- final String _pkg = sbn.pkg;
- final String _tag = sbn.tag;
- final int _id = sbn.id;
- vetoButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- try {
- mBarService.onNotificationClear(_pkg, _tag, _id);
- } catch (RemoteException ex) {
- // system process is dead if we're here.
- }
- }
- });
- } else {
- vetoButton.setVisibility(View.GONE);
- }
+ View vetoButton = updateNotificationVetoButton(row, sbn);
vetoButton.setContentDescription(mContext.getString(
R.string.accessibility_remove_notification));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
index e76fe51..f5ceed0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.text.StaticLayout;
@@ -50,6 +51,7 @@
private View mTickerView;
private ImageSwitcher mIconSwitcher;
private TextSwitcher mTextSwitcher;
+ private float mIconScale;
private final class Segment {
StatusBarNotification notification;
@@ -145,6 +147,11 @@
public Ticker(Context context, View sb) {
mContext = context;
+ final Resources res = context.getResources();
+ final int outerBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_size);
+ final int imageBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size);
+ mIconScale = (float)imageBounds / (float)outerBounds;
+
mTickerView = sb.findViewById(R.id.ticker);
mIconSwitcher = (ImageSwitcher)sb.findViewById(R.id.tickerIcon);
@@ -152,6 +159,8 @@
AnimationUtils.loadAnimation(context, com.android.internal.R.anim.push_up_in));
mIconSwitcher.setOutAnimation(
AnimationUtils.loadAnimation(context, com.android.internal.R.anim.push_up_out));
+ mIconSwitcher.setScaleX(mIconScale);
+ mIconSwitcher.setScaleY(mIconScale);
mTextSwitcher = (TextSwitcher)sb.findViewById(R.id.tickerText);
mTextSwitcher.setInAnimation(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 8d964e3..4f9eb38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -61,7 +61,7 @@
// debug
static final String TAG = "StatusBar.NetworkController";
static final boolean DEBUG = false;
- static final boolean CHATTY = true; // additional diagnostics, but not logspew
+ static final boolean CHATTY = false; // additional diagnostics, but not logspew
// telephony
boolean mHspaDataDistinguishable;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 415a9a4..f0a10f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -840,6 +840,9 @@
boolean orderUnchanged = notification.notification.when==oldNotification.notification.when
&& notification.priority == oldNotification.priority;
// priority now encompasses isOngoing()
+ boolean updateTicker = notification.notification.tickerText != null
+ && !TextUtils.equals(notification.notification.tickerText,
+ oldEntry.notification.notification.tickerText);
boolean isLastAnyway = rowParent.indexOfChild(oldEntry.row) == rowParent.getChildCount()-1;
if (contentsUnchanged && (orderUnchanged || isLastAnyway)) {
if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key);
@@ -896,9 +899,8 @@
}
// Restart the ticker if it's still running
- if (notification.notification.tickerText != null
- && !TextUtils.equals(notification.notification.tickerText,
- oldEntry.notification.notification.tickerText)) {
+ if (updateTicker) {
+ mTicker.halt();
tick(key, notification, false);
}
@@ -1736,23 +1738,7 @@
Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.status_bar_notification_row, parent, false);
workAroundBadLayerDrawableOpacity(row);
- View vetoButton = row.findViewById(R.id.veto);
- if (entry.notification.isClearable()) {
- final String _pkg = sbn.pkg;
- final String _tag = sbn.tag;
- final int _id = sbn.id;
- vetoButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- try {
- mBarService.onNotificationClear(_pkg, _tag, _id);
- } catch (RemoteException ex) {
- // system process is dead if we're here.
- }
- }
- });
- } else {
- vetoButton.setVisibility(View.GONE);
- }
+ View vetoButton = updateNotificationVetoButton(row, entry.notification);
vetoButton.setContentDescription(mContext.getString(
R.string.accessibility_remove_notification));
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index d1bb8d1..ebf380a 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -49,6 +49,7 @@
import android.os.Handler;
import android.os.Message;
import android.os.IBinder;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
@@ -126,6 +127,13 @@
// The service can take a couple of seconds to start on the first try after boot
private final int FACELOCK_VIEW_AREA_SERVICE_TIMEOUT = 3000;
+ // So the user has a consistent amount of time when brought to the backup method from FaceLock
+ private final int BACKUP_LOCK_TIMEOUT = 5000;
+
+ // Needed to keep track of failed FaceUnlock attempts
+ private int mFailedFaceUnlockAttempts = 0;
+ private static final int FAILED_FACE_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 15;
+
/**
* The current {@link KeyguardScreen} will use this to communicate back to us.
*/
@@ -133,7 +141,10 @@
private boolean mRequiresSim;
- private volatile boolean mEmergencyCall;
+ //True if we have some sort of overlay on top of the Lockscreen
+ //Also true if we've activated a phone call, either emergency dialing or incoming
+ //This resets when the phone is turned off with no current call
+ private boolean mHasOverlay;
/**
@@ -215,6 +226,7 @@
private Runnable mRecreateRunnable = new Runnable() {
public void run() {
updateScreen(mMode, true);
+ restoreWidgetState();
}
};
@@ -238,10 +250,20 @@
// TODO: examine all widgets to derive clock status
mUpdateMonitor.reportClockVisible(true);
}
+
+ public boolean isVisible(View self) {
+ // TODO: this should be up to the lockscreen to determine if the view
+ // is currently showing. The idea is it can be used for the widget to
+ // avoid doing work if it's not visible. For now just returns the view's
+ // actual visibility.
+ return self.getVisibility() == View.VISIBLE;
+ }
};
private TransportControlView mTransportControlView;
+ private Parcelable mSavedState;
+
/**
* @return Whether we are stuck on the lock screen because the sim is
* missing.
@@ -274,7 +296,7 @@
mUpdateMonitor = updateMonitor;
mLockPatternUtils = lockPatternUtils;
mWindowController = controller;
- mEmergencyCall = false;
+ mHasOverlay = false;
mUpdateMonitor.registerInfoCallback(this);
@@ -329,12 +351,15 @@
}
public void takeEmergencyCallAction() {
- mEmergencyCall = true;
+ mHasOverlay = true;
// FaceLock must be stopped if it is running when emergency call is pressed
stopAndUnbindFromFaceLock();
// Continue showing FaceLock area until dialer comes up
- showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT);
+ if (mLockPatternUtils.usingBiometricWeak() &&
+ mLockPatternUtils.isBiometricWeakInstalled()) {
+ showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT);
+ }
pokeWakelock(EMERGENCY_CALL_TIMEOUT);
if (TelephonyManager.getDefault().getCallState()
@@ -358,6 +383,7 @@
public void keyguardDone(boolean authenticated) {
getCallback().keyguardDone(authenticated);
+ mSavedState = null; // clear state so we re-establish when locked again
}
public void keyguardDoneDrawing() {
@@ -417,6 +443,7 @@
}
public void reportSuccessfulUnlockAttempt() {
+ mFailedFaceUnlockAttempts = 0;
mLockPatternUtils.reportSuccessfulPasswordAttempt();
}
};
@@ -511,15 +538,18 @@
@Override
public void onScreenTurnedOff() {
+ if (DEBUG) Log.d(TAG, "screen off");
mScreenOn = false;
mForgotPattern = false;
- mEmergencyCall = false;
+ mHasOverlay = mUpdateMonitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE;
if (mMode == Mode.LockScreen) {
((KeyguardScreen) mLockScreen).onPause();
} else {
((KeyguardScreen) mUnlockScreen).onPause();
}
+ saveWidgetState();
+
// When screen is turned off, need to unbind from FaceLock service if using FaceLock
stopAndUnbindFromFaceLock();
}
@@ -528,14 +558,23 @@
* FaceLock, but only if we're not dealing with a call
*/
private void activateFaceLockIfAble() {
- final boolean transportInvisible = mTransportControlView == null ? true :
- mTransportControlView.getVisibility() != View.VISIBLE;
+ final boolean tooManyFaceUnlockTries =
+ (mFailedFaceUnlockAttempts >= FAILED_FACE_UNLOCK_ATTEMPTS_BEFORE_BACKUP);
+ final int failedBackupAttempts = mUpdateMonitor.getFailedAttempts();
+ final boolean backupIsTimedOut =
+ (failedBackupAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
+ if (tooManyFaceUnlockTries) Log.i(TAG, "tooManyFaceUnlockTries: " + tooManyFaceUnlockTries);
if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
- && transportInvisible) {
+ && !mHasOverlay
+ && !tooManyFaceUnlockTries
+ && !backupIsTimedOut) {
bindToFaceLock();
// Show FaceLock area, but only for a little bit so lockpattern will become visible if
// FaceLock fails to start or crashes
- showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_SERVICE_TIMEOUT);
+ if (mLockPatternUtils.usingBiometricWeak() &&
+ mLockPatternUtils.isBiometricWeakInstalled()) {
+ showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_SERVICE_TIMEOUT);
+ }
} else {
hideFaceLockArea();
}
@@ -543,14 +582,35 @@
@Override
public void onScreenTurnedOn() {
+ if (DEBUG) Log.d(TAG, "screen on");
boolean runFaceLock = false;
//Make sure to start facelock iff the screen is both on and focused
synchronized(mFaceLockStartupLock) {
mScreenOn = true;
runFaceLock = mWindowFocused;
}
+
show();
- if(runFaceLock) activateFaceLockIfAble();
+
+ restoreWidgetState();
+
+ if (runFaceLock) activateFaceLockIfAble();
+ }
+
+ private void saveWidgetState() {
+ if (mTransportControlView != null) {
+ if (DEBUG) Log.v(TAG, "Saving widget state");
+ mSavedState = mTransportControlView.onSaveInstanceState();
+ }
+ }
+
+ private void restoreWidgetState() {
+ if (mTransportControlView != null) {
+ if (DEBUG) Log.v(TAG, "Restoring widget state");
+ if (mSavedState != null) {
+ mTransportControlView.onRestoreInstanceState(mSavedState);
+ }
+ }
}
/** Unbind from facelock if something covers this window (such as an alarm)
@@ -558,7 +618,7 @@
*/
@Override
public void onWindowFocusChanged (boolean hasWindowFocus) {
- if(DEBUG) Log.d(TAG, hasWindowFocus ? "focused" : "unfocused");
+ if (DEBUG) Log.d(TAG, hasWindowFocus ? "focused" : "unfocused");
boolean runFaceLock = false;
//Make sure to start facelock iff the screen is both on and focused
synchronized(mFaceLockStartupLock) {
@@ -566,14 +626,11 @@
mWindowFocused = hasWindowFocus;
}
if(!hasWindowFocus) {
+ mHasOverlay = true;
stopAndUnbindFromFaceLock();
hideFaceLockArea();
} else if (runFaceLock) {
- //Don't activate facelock while the user is calling 911!
- if(mEmergencyCall) mEmergencyCall = false;
- else {
- activateFaceLockIfAble();
- }
+ activateFaceLockIfAble();
}
}
@@ -586,7 +643,11 @@
}
if (mLockPatternUtils.usingBiometricWeak() &&
- mLockPatternUtils.isBiometricWeakInstalled()) {
+ mLockPatternUtils.isBiometricWeakInstalled() && !mHasOverlay) {
+ // Note that show() gets called before the screen turns off to set it up for next time
+ // it is turned on. We don't want to set a timeout on the FaceLock area here because it
+ // may be gone by the time the screen is turned on again. We set the timout when the
+ // screen turns on instead.
showFaceLockArea();
} else {
hideFaceLockArea();
@@ -633,6 +694,7 @@
mShowLockBeforeUnlock = resources.getBoolean(R.bool.config_enableLockBeforeUnlockScreen);
mConfiguration = newConfig;
if (DEBUG_CONFIGURATION) Log.v(TAG, "**** re-creating lock screen since config changed");
+ saveWidgetState();
removeCallbacks(mRecreateRunnable);
post(mRecreateRunnable);
}
@@ -657,6 +719,7 @@
public void onPhoneStateChanged(int phoneState) {
if (DEBUG) Log.d(TAG, "phone state: " + phoneState);
if(phoneState == TelephonyManager.CALL_STATE_RINGING) {
+ mHasOverlay = true;
stopAndUnbindFromFaceLock();
hideFaceLockArea();
}
@@ -718,6 +781,16 @@
this.removeView(mUnlockScreen);
mUnlockScreen = null;
}
+ mUpdateMonitor.removeCallback(this);
+ if (mFaceLockService != null) {
+ try {
+ mFaceLockService.unregisterCallback(mFaceLockCallback);
+ } catch (RemoteException e) {
+ // Not much we can do
+ }
+ stopFaceLock();
+ mFaceLockService = null;
+ }
}
private boolean isSecure() {
@@ -1142,6 +1215,13 @@
if (mBoundToFaceLockService) {
if (DEBUG) Log.d(TAG, "before unbind from FaceLock service");
+ if (mFaceLockService != null) {
+ try {
+ mFaceLockService.unregisterCallback(mFaceLockCallback);
+ } catch (RemoteException e) {
+ // Not much we can do
+ }
+ }
mContext.unbindService(mFaceLockConnection);
if (DEBUG) Log.d(TAG, "after unbind from FaceLock service");
mBoundToFaceLockService = false;
@@ -1246,12 +1326,24 @@
}
// Stops the FaceLock UI and exposes the backup method without unlocking
- // This means either the user has cancelled out or FaceLock failed to recognize them
+ // This means the user has cancelled out
@Override
public void cancel() {
if (DEBUG) Log.d(TAG, "FaceLock cancel()");
hideFaceLockArea(); // Expose fallback
stopFaceLock();
+ mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
+ }
+
+ // Stops the FaceLock UI and exposes the backup method without unlocking
+ // This means FaceLock failed to recognize them
+ @Override
+ public void reportFailedAttempt() {
+ if (DEBUG) Log.d(TAG, "FaceLock reportFailedAttempt()");
+ mFailedFaceUnlockAttempts++;
+ hideFaceLockArea(); // Expose fallback
+ stopFaceLock();
+ mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
}
// Allows the Face Unlock service to poke the wake lock to keep the lockscreen alive
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index aac3209..48172fa 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -353,8 +353,13 @@
int mDockLeft, mDockTop, mDockRight, mDockBottom;
// During layout, the layer at which the doc window is placed.
int mDockLayer;
- int mLastSystemUiVisibility;
- int mForceClearingStatusBarVisibility = 0;
+ int mLastSystemUiFlags;
+ // Bits that we are in the process of clearing, so we want to prevent
+ // them from being set by applications until everything has been updated
+ // to have them clear.
+ int mResettingSystemUiFlags = 0;
+ // Bits that we are currently always keeping cleared.
+ int mForceClearedSystemUiFlags = 0;
FakeWindow mHideNavFakeWindow = null;
@@ -1719,6 +1724,21 @@
}
}
+ /**
+ * A delayed callback use to determine when it is okay to re-allow applications
+ * to use certain system UI flags. This is used to prevent applications from
+ * spamming system UI changes that prevent the navigation bar from being shown.
+ */
+ final Runnable mAllowSystemUiDelay = new Runnable() {
+ @Override public void run() {
+ }
+ };
+
+ /**
+ * Input handler used while nav bar is hidden. Captures any touch on the screen,
+ * to determine when the nav bar should be shown and prevent applications from
+ * receiving those touches.
+ */
final InputHandler mHideNavInputHandler = new BaseInputHandler() {
@Override
public void handleMotion(MotionEvent event, InputQueue.FinishedCallback finishedCallback) {
@@ -1731,12 +1751,30 @@
synchronized (mLock) {
// Any user activity always causes us to show the navigation controls,
// if they had been hidden.
- int newVal = mForceClearingStatusBarVisibility
+ int newVal = mResettingSystemUiFlags
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
- if (mForceClearingStatusBarVisibility != newVal) {
- mForceClearingStatusBarVisibility = newVal;
+ if (mResettingSystemUiFlags != newVal) {
+ mResettingSystemUiFlags = newVal;
changed = true;
}
+ // We don't allow the system's nav bar to be hidden
+ // again for 1 second, to prevent applications from
+ // spamming us and keeping it from being shown.
+ newVal = mForceClearedSystemUiFlags
+ | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ if (mForceClearedSystemUiFlags != newVal) {
+ mForceClearedSystemUiFlags = newVal;
+ changed = true;
+ mHandler.postDelayed(new Runnable() {
+ @Override public void run() {
+ synchronized (mLock) {
+ mForceClearedSystemUiFlags &=
+ ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ }
+ mWindowManagerFuncs.reevaluateStatusBarVisibility();
+ }
+ }, 1000);
+ }
}
if (changed) {
mWindowManagerFuncs.reevaluateStatusBarVisibility();
@@ -1753,10 +1791,11 @@
public int adjustSystemUiVisibilityLw(int visibility) {
// Reset any bits in mForceClearingStatusBarVisibility that
// are now clear.
- mForceClearingStatusBarVisibility &= visibility;
+ mResettingSystemUiFlags &= visibility;
// Clear any bits in the new visibility that are currently being
// force cleared, before reporting it.
- return visibility & ~mForceClearingStatusBarVisibility;
+ return visibility & ~mResettingSystemUiFlags
+ & ~mForceClearedSystemUiFlags;
}
public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) {
@@ -1795,11 +1834,28 @@
pf.right = df.right = vf.right = mDockRight;
pf.bottom = df.bottom = vf.bottom = mDockBottom;
+ final boolean navVisible = mNavigationBar != null && mNavigationBar.isVisibleLw() &&
+ (mLastSystemUiFlags&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
+
+ // When the navigation bar isn't visible, we put up a fake
+ // input window to catch all touch events. This way we can
+ // detect when the user presses anywhere to bring back the nav
+ // bar and ensure the application doesn't see the event.
+ if (navVisible) {
+ if (mHideNavFakeWindow != null) {
+ mHideNavFakeWindow.dismiss();
+ mHideNavFakeWindow = null;
+ }
+ } else if (mHideNavFakeWindow == null) {
+ mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow(
+ mHandler.getLooper(), mHideNavInputHandler,
+ "hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER,
+ 0, false, false, true);
+ }
+
// decide where the status bar goes ahead of time
if (mStatusBar != null) {
if (mNavigationBar != null) {
- final boolean navVisible = mNavigationBar.isVisibleLw() &&
- (mLastSystemUiVisibility&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
// Force the navigation bar to its appropriate place and
// size. We need to do this directly, instead of relying on
// it to bubble up from the nav bar, because this needs to
@@ -1831,21 +1887,6 @@
mTmpNavigationFrame.offset(mNavigationBarWidth, 0);
}
}
- // When the navigation bar isn't visible, we put up a fake
- // input window to catch all touch events. This way we can
- // detect when the user presses anywhere to bring back the nav
- // bar and ensure the application doesn't see the event.
- if (navVisible) {
- if (mHideNavFakeWindow != null) {
- mHideNavFakeWindow.dismiss();
- mHideNavFakeWindow = null;
- }
- } else if (mHideNavFakeWindow == null) {
- mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow(
- mHandler.getLooper(), mHideNavInputHandler,
- "hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER,
- 0, false, false, true);
- }
// And compute the final frame.
mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
mTmpNavigationFrame, mTmpNavigationFrame);
@@ -3653,12 +3694,13 @@
return 0;
}
final int visibility = mFocusedWindow.getSystemUiVisibility()
- & ~mForceClearingStatusBarVisibility;
- int diff = visibility ^ mLastSystemUiVisibility;
+ & ~mResettingSystemUiFlags
+ & ~mForceClearedSystemUiFlags;
+ int diff = visibility ^ mLastSystemUiFlags;
if (diff == 0) {
return 0;
}
- mLastSystemUiVisibility = visibility;
+ mLastSystemUiFlags = visibility;
mHandler.post(new Runnable() {
public void run() {
if (mStatusBarService == null) {
@@ -3685,11 +3727,14 @@
pw.print(prefix); pw.print("mLidOpen="); pw.print(mLidOpen);
pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
- if (mLastSystemUiVisibility != 0 || mForceClearingStatusBarVisibility != 0) {
- pw.print(prefix); pw.print("mLastSystemUiVisibility=0x");
- pw.println(Integer.toHexString(mLastSystemUiVisibility));
- pw.print(" mForceClearingStatusBarVisibility=0x");
- pw.println(Integer.toHexString(mForceClearingStatusBarVisibility));
+ if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
+ || mForceClearedSystemUiFlags != 0) {
+ pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
+ pw.print(Integer.toHexString(mLastSystemUiFlags));
+ pw.print(" mResettingSystemUiFlags=0x");
+ pw.print(Integer.toHexString(mResettingSystemUiFlags));
+ pw.print(" mForceClearedSystemUiFlags=0x");
+ pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
}
pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
pw.print(" mDockMode="); pw.print(mDockMode);
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index f9f5458..4ef8837 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -62,14 +62,15 @@
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.WorkSource;
+import android.os.storage.IMountService;
import android.provider.Settings;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
-import android.util.SparseIntArray;
import android.util.StringBuilderPrinter;
import com.android.internal.backup.BackupConstants;
@@ -187,6 +188,7 @@
private IActivityManager mActivityManager;
private PowerManager mPowerManager;
private AlarmManager mAlarmManager;
+ private IMountService mMountService;
IBackupManager mBackupManagerBinder;
boolean mEnabled; // access to this is synchronized on 'this'
@@ -660,6 +662,7 @@
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
mBackupManagerBinder = asInterface(asBinder());
@@ -1037,6 +1040,40 @@
// Backup password management
boolean passwordMatchesSaved(String candidatePw, int rounds) {
+ // First, on an encrypted device we require matching the device pw
+ final boolean isEncrypted;
+ try {
+ isEncrypted = (mMountService.getEncryptionState() != MountService.ENCRYPTION_STATE_NONE);
+ if (isEncrypted) {
+ if (DEBUG) {
+ Slog.i(TAG, "Device encrypted; verifying against device data pw");
+ }
+ // 0 means the password validated
+ // -2 means device not encrypted
+ // Any other result is either password failure or an error condition,
+ // so we refuse the match
+ final int result = mMountService.verifyEncryptionPassword(candidatePw);
+ if (result == 0) {
+ if (MORE_DEBUG) Slog.d(TAG, "Pw verifies");
+ return true;
+ } else if (result != -2) {
+ if (MORE_DEBUG) Slog.d(TAG, "Pw mismatch");
+ return false;
+ } else {
+ // ...else the device is supposedly not encrypted. HOWEVER, the
+ // query about the encryption state said that the device *is*
+ // encrypted, so ... we may have a problem. Log it and refuse
+ // the backup.
+ Slog.e(TAG, "verified encryption state mismatch against query; no match allowed");
+ return false;
+ }
+ }
+ } catch (Exception e) {
+ // Something went wrong talking to the mount service. This is very bad;
+ // assume that we fail password validation.
+ return false;
+ }
+
if (mPasswordHash == null) {
// no current password case -- require that 'currentPw' be null or empty
if (candidatePw == null || "".equals(candidatePw)) {
@@ -1114,7 +1151,15 @@
public boolean hasBackupPassword() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"hasBackupPassword");
- return (mPasswordHash != null && mPasswordHash.length() > 0);
+
+ try {
+ return (mMountService.getEncryptionState() != IMountService.ENCRYPTION_STATE_NONE)
+ || (mPasswordHash != null && mPasswordHash.length() > 0);
+ } catch (Exception e) {
+ // If we can't talk to the mount service we have a serious problem; fail
+ // "secure" i.e. assuming that we require a password
+ return true;
+ }
}
// Maintain persistent state around whether need to do an initialize operation.
@@ -5007,7 +5052,17 @@
params.observer = observer;
params.curPassword = curPassword;
- params.encryptPassword = encPpassword;
+
+ boolean isEncrypted;
+ try {
+ isEncrypted = (mMountService.getEncryptionState() != MountService.ENCRYPTION_STATE_NONE);
+ if (isEncrypted) Slog.w(TAG, "Device is encrypted; forcing enc password");
+ } catch (RemoteException e) {
+ // couldn't contact the mount service; fail "safe" and assume encryption
+ Slog.e(TAG, "Unable to contact mount service!");
+ isEncrypted = true;
+ }
+ params.encryptPassword = (isEncrypted) ? curPassword : encPpassword;
if (DEBUG) Slog.d(TAG, "Sending conf message with verb " + verb);
mWakelock.acquire();
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 582f0ed..5425813 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -1897,6 +1897,53 @@
}
}
+ /**
+ * Validate a user-supplied password string with cryptfs
+ */
+ @Override
+ public int verifyEncryptionPassword(String password) throws RemoteException {
+ // Only the system process is permitted to validate passwords
+ if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
+ throw new SecurityException("no permission to access the crypt keeper");
+ }
+
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
+ "no permission to access the crypt keeper");
+
+ if (TextUtils.isEmpty(password)) {
+ throw new IllegalArgumentException("password cannot be empty");
+ }
+
+ waitForReady();
+
+ if (DEBUG_EVENTS) {
+ Slog.i(TAG, "validating encryption password...");
+ }
+
+ try {
+ ArrayList<String> response = mConnector.doCommand("cryptfs verifypw " + password);
+ String[] tokens = response.get(0).split(" ");
+
+ if (tokens == null || tokens.length != 2) {
+ String msg = "Unexpected result from cryptfs verifypw: {";
+ if (tokens == null) msg += "null";
+ else for (int i = 0; i < tokens.length; i++) {
+ if (i != 0) msg += ',';
+ msg += tokens[i];
+ }
+ msg += '}';
+ Slog.e(TAG, msg);
+ return -1;
+ }
+
+ Slog.i(TAG, "cryptfs verifypw => " + tokens[1]);
+ return Integer.parseInt(tokens[1]);
+ } catch (NativeDaemonConnectorException e) {
+ // Encryption failed
+ return e.getCode();
+ }
+ }
+
public Parcelable[] getVolumeList() {
synchronized(mVolumes) {
int size = mVolumes.size();
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index ef48b9e..788ecda 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -43,10 +43,13 @@
import android.view.textservice.SpellCheckerInfo;
import android.view.textservice.SpellCheckerSubtype;
+import java.io.FileDescriptor;
import java.io.IOException;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
public class TextServicesManagerService extends ITextServicesManager.Stub {
private static final String TAG = TextServicesManagerService.class.getSimpleName();
@@ -480,6 +483,66 @@
}
}
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+
+ pw.println("Permission Denial: can't dump TextServicesManagerService from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
+ synchronized(mSpellCheckerMap) {
+ pw.println("Current Text Services Manager state:");
+ pw.println(" Spell Checker Map:");
+ for (Map.Entry<String, SpellCheckerInfo> ent : mSpellCheckerMap.entrySet()) {
+ pw.print(" "); pw.print(ent.getKey()); pw.println(":");
+ SpellCheckerInfo info = ent.getValue();
+ pw.print(" "); pw.print("id="); pw.println(info.getId());
+ pw.print(" "); pw.print("comp=");
+ pw.println(info.getComponent().toShortString());
+ int NS = info.getSubtypeCount();
+ for (int i=0; i<NS; i++) {
+ SpellCheckerSubtype st = info.getSubtypeAt(i);
+ pw.print(" "); pw.print("Subtype #"); pw.print(i); pw.println(":");
+ pw.print(" "); pw.print("locale="); pw.println(st.getLocale());
+ pw.print(" "); pw.print("extraValue=");
+ pw.println(st.getExtraValue());
+ }
+ }
+ pw.println("");
+ pw.println(" Spell Checker Bind Groups:");
+ for (Map.Entry<String, SpellCheckerBindGroup> ent
+ : mSpellCheckerBindGroups.entrySet()) {
+ SpellCheckerBindGroup grp = ent.getValue();
+ pw.print(" "); pw.print(ent.getKey()); pw.print(" ");
+ pw.print(grp); pw.println(":");
+ pw.print(" "); pw.print("mInternalConnection=");
+ pw.println(grp.mInternalConnection);
+ pw.print(" "); pw.print("mSpellChecker=");
+ pw.println(grp.mSpellChecker);
+ pw.print(" "); pw.print("mBound="); pw.print(grp.mBound);
+ pw.print(" mConnected="); pw.println(grp.mConnected);
+ int NL = grp.mListeners.size();
+ for (int i=0; i<NL; i++) {
+ InternalDeathRecipient listener = grp.mListeners.get(i);
+ pw.print(" "); pw.print("Listener #"); pw.print(i); pw.println(":");
+ pw.print(" "); pw.print("mTsListener=");
+ pw.println(listener.mTsListener);
+ pw.print(" "); pw.print("mScListener=");
+ pw.println(listener.mScListener);
+ pw.print(" "); pw.print("mGroup=");
+ pw.println(listener.mGroup);
+ pw.print(" "); pw.print("mScLocale=");
+ pw.print(listener.mScLocale);
+ pw.print(" mUid="); pw.println(listener.mUid);
+ }
+ }
+ }
+ }
+
// SpellCheckerBindGroup contains active text service session listeners.
// If there are no listeners anymore, the SpellCheckerBindGroup instance will be removed from
// mSpellCheckerBindGroups
@@ -488,6 +551,7 @@
private final InternalServiceConnection mInternalConnection;
private final ArrayList<InternalDeathRecipient> mListeners =
new ArrayList<InternalDeathRecipient>();
+ public boolean mBound;
public ISpellCheckerService mSpellChecker;
public boolean mConnected;
@@ -495,6 +559,7 @@
ITextServicesSessionListener listener, String locale,
ISpellCheckerSessionListener scListener, int uid, Bundle bundle) {
mInternalConnection = connection;
+ mBound = true;
mConnected = false;
addListener(listener, locale, scListener, uid, bundle);
}
@@ -580,15 +645,18 @@
if (DBG) {
Slog.d(TAG, "cleanLocked");
}
- if (mListeners.isEmpty()) {
+ // If there are no more active listeners, clean up. Only do this
+ // once.
+ if (mBound && mListeners.isEmpty()) {
+ mBound = false;
final String sciId = mInternalConnection.mSciId;
- if (mSpellCheckerBindGroups.containsKey(sciId)) {
+ SpellCheckerBindGroup cur = mSpellCheckerBindGroups.get(sciId);
+ if (cur == this) {
if (DBG) {
Slog.d(TAG, "Remove bind group.");
}
mSpellCheckerBindGroups.remove(sciId);
}
- // Unbind service when there is no active clients.
mContext.unbindService(mInternalConnection);
}
}
@@ -623,7 +691,7 @@
}
ISpellCheckerService spellChecker = ISpellCheckerService.Stub.asInterface(service);
final SpellCheckerBindGroup group = mSpellCheckerBindGroups.get(mSciId);
- if (group != null) {
+ if (this == group.mInternalConnection) {
group.onServiceConnected(spellChecker);
}
}
@@ -631,7 +699,12 @@
@Override
public void onServiceDisconnected(ComponentName name) {
- mSpellCheckerBindGroups.remove(mSciId);
+ synchronized(mSpellCheckerMap) {
+ final SpellCheckerBindGroup group = mSpellCheckerBindGroups.get(mSciId);
+ if (this == group.mInternalConnection) {
+ mSpellCheckerBindGroups.remove(mSciId);
+ }
+ }
}
}
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 660681b..5bfe6f8 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -1402,7 +1402,7 @@
long ident = Binder.clearCallingIdentity();
try {
if (hadLock) {
- noteAcquireWifiLock(wifiLock);
+ noteReleaseWifiLock(wifiLock);
switch(wifiLock.mMode) {
case WifiManager.WIFI_MODE_FULL:
++mFullLocksReleased;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1441a54..7c0cd9b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -451,7 +451,7 @@
}
const DisplayHardware& hw(graphicPlane(0).displayHardware());
- if (LIKELY(hw.canDraw() && !isFrozen())) {
+ if (LIKELY(hw.canDraw())) {
// repaint the framebuffer (if needed)
const int index = hw.getCurrentBufferIndex();
@@ -478,15 +478,13 @@
void SurfaceFlinger::postFramebuffer()
{
- if (!mSwapRegion.isEmpty()) {
- const DisplayHardware& hw(graphicPlane(0).displayHardware());
- const nsecs_t now = systemTime();
- mDebugInSwapBuffers = now;
- hw.flip(mSwapRegion);
- mLastSwapBufferTime = systemTime() - now;
- mDebugInSwapBuffers = 0;
- mSwapRegion.clear();
- }
+ const DisplayHardware& hw(graphicPlane(0).displayHardware());
+ const nsecs_t now = systemTime();
+ mDebugInSwapBuffers = now;
+ hw.flip(mSwapRegion);
+ mLastSwapBufferTime = systemTime() - now;
+ mDebugInSwapBuffers = 0;
+ mSwapRegion.clear();
}
void SurfaceFlinger::handleConsoleEvents()
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index d66cdf0..3d6537a 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -3,6 +3,7 @@
//
#include "AaptAssets.h"
+#include "ResourceFilter.h"
#include "Main.h"
#include <utils/misc.h>
@@ -16,6 +17,8 @@
static const char* kWildcardName = "any";
static const char* kAssetDir = "assets";
static const char* kResourceDir = "res";
+static const char* kValuesDir = "values";
+static const char* kMipmapDir = "mipmap";
static const char* kInvalidChars = "/\\:";
static const size_t kMaxAssetFileName = 100;
@@ -257,9 +260,69 @@
return 1;
}
+uint32_t
+AaptGroupEntry::getConfigValueForAxis(const ResTable_config& config, int axis)
+{
+ switch (axis) {
+ case AXIS_MCC:
+ return config.mcc;
+ case AXIS_MNC:
+ return config.mnc;
+ case AXIS_LANGUAGE:
+ return (((uint32_t)config.country[1]) << 24) | (((uint32_t)config.country[0]) << 16)
+ | (((uint32_t)config.language[1]) << 8) | (config.language[0]);
+ case AXIS_SCREENLAYOUTSIZE:
+ return config.screenLayout&ResTable_config::MASK_SCREENSIZE;
+ case AXIS_ORIENTATION:
+ return config.orientation;
+ case AXIS_UIMODETYPE:
+ return (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
+ case AXIS_UIMODENIGHT:
+ return (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
+ case AXIS_DENSITY:
+ return config.density;
+ case AXIS_TOUCHSCREEN:
+ return config.touchscreen;
+ case AXIS_KEYSHIDDEN:
+ return config.inputFlags;
+ case AXIS_KEYBOARD:
+ return config.keyboard;
+ case AXIS_NAVIGATION:
+ return config.navigation;
+ case AXIS_SCREENSIZE:
+ return config.screenSize;
+ case AXIS_SMALLESTSCREENWIDTHDP:
+ return config.smallestScreenWidthDp;
+ case AXIS_SCREENWIDTHDP:
+ return config.screenWidthDp;
+ case AXIS_SCREENHEIGHTDP:
+ return config.screenHeightDp;
+ case AXIS_VERSION:
+ return config.version;
+ }
+ return 0;
+}
+
+bool
+AaptGroupEntry::configSameExcept(const ResTable_config& config,
+ const ResTable_config& otherConfig, int axis)
+{
+ for (int i=AXIS_START; i<=AXIS_END; i++) {
+ if (i == axis) {
+ continue;
+ }
+ if (getConfigValueForAxis(config, i) != getConfigValueForAxis(otherConfig, i)) {
+ return false;
+ }
+ }
+ return true;
+}
+
bool
AaptGroupEntry::initFromDirName(const char* dir, String8* resType)
{
+ mParamsChanged = true;
+
Vector<String8> parts;
String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den;
@@ -629,79 +692,117 @@
{
String8 s = resType;
if (this->mcc != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += mcc;
}
if (this->mnc != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += mnc;
}
if (this->locale != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += locale;
}
if (this->smallestScreenWidthDp != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += smallestScreenWidthDp;
}
if (this->screenWidthDp != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += screenWidthDp;
}
if (this->screenHeightDp != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += screenHeightDp;
}
if (this->screenLayoutSize != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += screenLayoutSize;
}
if (this->screenLayoutLong != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += screenLayoutLong;
}
if (this->orientation != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += orientation;
}
if (this->uiModeType != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += uiModeType;
}
if (this->uiModeNight != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += uiModeNight;
}
if (this->density != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += density;
}
if (this->touchscreen != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += touchscreen;
}
if (this->keysHidden != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += keysHidden;
}
if (this->keyboard != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += keyboard;
}
if (this->navHidden != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += navHidden;
}
if (this->navigation != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += navigation;
}
if (this->screenSize != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += screenSize;
}
if (this->version != "") {
- s += "-";
+ if (s.length() > 0) {
+ s += "-";
+ }
s += version;
}
@@ -1286,9 +1387,14 @@
return v;
}
-ResTable_config AaptGroupEntry::toParams() const
+const ResTable_config& AaptGroupEntry::toParams() const
{
- ResTable_config params;
+ if (!mParamsChanged) {
+ return mParams;
+ }
+
+ mParamsChanged = false;
+ ResTable_config& params(mParams);
memset(¶ms, 0, sizeof(params));
getMccName(mcc.string(), ¶ms);
getMncName(mnc.string(), ¶ms);
@@ -1403,8 +1509,7 @@
String8 AaptFile::getPrintableSource() const
{
if (hasData()) {
- String8 name(mGroupEntry.locale.string());
- name.appendPath(mGroupEntry.vendor.string());
+ String8 name(mGroupEntry.toDirName(String8()));
name.appendPath(mPath);
name.append(" #generated");
return name;
@@ -1424,6 +1529,13 @@
return NO_ERROR;
}
+#if 0
+ printf("Error adding file %s: group %s already exists in leaf=%s path=%s\n",
+ file->getSourceFile().string(),
+ file->getGroupEntry().toDirName(String8()).string(),
+ mLeaf.string(), mPath.string());
+#endif
+
SourcePos(file->getSourceFile(), -1).error("Duplicate file.\n%s: Original is here.",
getPrintableSource().string());
return UNKNOWN_ERROR;
@@ -1434,20 +1546,23 @@
mFiles.removeItemsAt(index);
}
-void AaptGroup::print() const
+void AaptGroup::print(const String8& prefix) const
{
- printf(" %s\n", getPath().string());
+ printf("%s%s\n", prefix.string(), getPath().string());
const size_t N=mFiles.size();
size_t i;
for (i=0; i<N; i++) {
sp<AaptFile> file = mFiles.valueAt(i);
const AaptGroupEntry& e = file->getGroupEntry();
if (file->hasData()) {
- printf(" Gen: (%s) %d bytes\n", e.toString().string(),
+ printf("%s Gen: (%s) %d bytes\n", prefix.string(), e.toDirName(String8()).string(),
(int)file->getSize());
} else {
- printf(" Src: %s\n", file->getPrintableSource().string());
+ printf("%s Src: (%s) %s\n", prefix.string(), e.toDirName(String8()).string(),
+ file->getPrintableSource().string());
}
+ //printf("%s File Group Entry: %s\n", prefix.string(),
+ // file->getGroupEntry().toDirName(String8()).string());
}
}
@@ -1514,38 +1629,6 @@
mDirs.removeItem(name);
}
-status_t AaptDir::renameFile(const sp<AaptFile>& file, const String8& newName)
-{
- sp<AaptGroup> origGroup;
-
- // Find and remove the given file with shear, brute force!
- const size_t NG = mFiles.size();
- size_t i;
- for (i=0; origGroup == NULL && i<NG; i++) {
- sp<AaptGroup> g = mFiles.valueAt(i);
- const size_t NF = g->getFiles().size();
- for (size_t j=0; j<NF; j++) {
- if (g->getFiles().valueAt(j) == file) {
- origGroup = g;
- g->removeFile(j);
- if (NF == 1) {
- mFiles.removeItemsAt(i);
- }
- break;
- }
- }
- }
-
- //printf("Renaming %s to %s\n", file->getPath().getPathName(), newName.string());
-
- // Place the file under its new name.
- if (origGroup != NULL) {
- return addLeafFile(newName, file);
- }
-
- return NO_ERROR;
-}
-
status_t AaptDir::addLeafFile(const String8& leafName, const sp<AaptFile>& file)
{
sp<AaptGroup> group;
@@ -1710,17 +1793,17 @@
return NO_ERROR;
}
-void AaptDir::print() const
+void AaptDir::print(const String8& prefix) const
{
const size_t ND=getDirs().size();
size_t i;
for (i=0; i<ND; i++) {
- getDirs().valueAt(i)->print();
+ getDirs().valueAt(i)->print(prefix);
}
const size_t NF=getFiles().size();
for (i=0; i<NF; i++) {
- getFiles().valueAt(i)->print();
+ getFiles().valueAt(i)->print(prefix);
}
}
@@ -1744,6 +1827,24 @@
// =========================================================================
// =========================================================================
+AaptAssets::AaptAssets()
+ : AaptDir(String8(), String8()),
+ mChanged(false), mHaveIncludedAssets(false), mRes(NULL)
+{
+}
+
+const SortedVector<AaptGroupEntry>& AaptAssets::getGroupEntries() const {
+ if (mChanged) {
+ }
+ return mGroupEntries;
+}
+
+status_t AaptAssets::addFile(const String8& name, const sp<AaptGroup>& file)
+{
+ mChanged = true;
+ return AaptDir::addFile(name, file);
+}
+
sp<AaptFile> AaptAssets::addFile(
const String8& filePath, const AaptGroupEntry& entry,
const String8& srcDir, sp<AaptGroup>* outGroup,
@@ -1945,6 +2046,11 @@
goto bail;
}
+ count = filter(bundle);
+ if (count != NO_ERROR) {
+ totalCount = count;
+ goto bail;
+ }
bail:
return totalCount;
@@ -2002,9 +2108,9 @@
continue;
}
- if (bundle->getMaxResVersion() != NULL && group.version.length() != 0) {
+ if (bundle->getMaxResVersion() != NULL && group.getVersionString().length() != 0) {
int maxResInt = atoi(bundle->getMaxResVersion());
- const char *verString = group.version.string();
+ const char *verString = group.getVersionString().string();
int dirVersionInt = atoi(verString + 1); // skip 'v' in version name
if (dirVersionInt > maxResInt) {
fprintf(stderr, "max res %d, skipping %s\n", maxResInt, entry->d_name);
@@ -2015,7 +2121,7 @@
FileType type = getFileType(subdirName.string());
if (type == kFileTypeDirectory) {
- sp<AaptDir> dir = makeDir(String8(entry->d_name));
+ sp<AaptDir> dir = makeDir(resType);
ssize_t res = dir->slurpFullTree(bundle, subdirName, group,
resType, mFullResPaths);
if (res < 0) {
@@ -2027,7 +2133,13 @@
count += res;
}
- mDirs.add(dir);
+ // Only add this directory if we don't already have a resource dir
+ // for the current type. This ensures that we only add the dir once
+ // for all configs.
+ sp<AaptDir> rdir = resDir(resType);
+ if (rdir == NULL) {
+ mResDirs.add(dir);
+ }
} else {
if (bundle->getVerbose()) {
fprintf(stderr, " (ignoring file '%s')\n", subdirName.string());
@@ -2136,6 +2248,142 @@
return count;
}
+status_t AaptAssets::filter(Bundle* bundle)
+{
+ ResourceFilter reqFilter;
+ status_t err = reqFilter.parse(bundle->getConfigurations());
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ ResourceFilter prefFilter;
+ err = prefFilter.parse(bundle->getPreferredConfigurations());
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ if (reqFilter.isEmpty() && prefFilter.isEmpty()) {
+ return NO_ERROR;
+ }
+
+ if (bundle->getVerbose()) {
+ if (!reqFilter.isEmpty()) {
+ printf("Applying required filter: %s\n",
+ bundle->getConfigurations());
+ }
+ if (!prefFilter.isEmpty()) {
+ printf("Applying preferred filter: %s\n",
+ bundle->getPreferredConfigurations());
+ }
+ }
+
+ const Vector<sp<AaptDir> >& resdirs = mResDirs;
+ const size_t ND = resdirs.size();
+ for (size_t i=0; i<ND; i++) {
+ const sp<AaptDir>& dir = resdirs.itemAt(i);
+ if (dir->getLeaf() == kValuesDir) {
+ // The "value" dir is special since a single file defines
+ // multiple resources, so we can not do filtering on the
+ // files themselves.
+ continue;
+ }
+ if (dir->getLeaf() == kMipmapDir) {
+ // We also skip the "mipmap" directory, since the point of this
+ // is to include all densities without stripping. If you put
+ // other configurations in here as well they won't be stripped
+ // either... So don't do that. Seriously. What is wrong with you?
+ continue;
+ }
+
+ const size_t NG = dir->getFiles().size();
+ for (size_t j=0; j<NG; j++) {
+ sp<AaptGroup> grp = dir->getFiles().valueAt(j);
+
+ // First remove any configurations we know we don't need.
+ for (size_t k=0; k<grp->getFiles().size(); k++) {
+ sp<AaptFile> file = grp->getFiles().valueAt(k);
+ if (k == 0 && grp->getFiles().size() == 1) {
+ // If this is the only file left, we need to keep it.
+ // Otherwise the resource IDs we are using will be inconsistent
+ // with what we get when not stripping. Sucky, but at least
+ // for now we can rely on the back-end doing another filtering
+ // pass to take this out and leave us with this resource name
+ // containing no entries.
+ continue;
+ }
+ if (file->getPath().getPathExtension() == ".xml") {
+ // We can't remove .xml files at this point, because when
+ // we parse them they may add identifier resources, so
+ // removing them can cause our resource identifiers to
+ // become inconsistent.
+ continue;
+ }
+ const ResTable_config& config(file->getGroupEntry().toParams());
+ if (!reqFilter.match(config)) {
+ if (bundle->getVerbose()) {
+ printf("Pruning unneeded resource: %s\n",
+ file->getPrintableSource().string());
+ }
+ grp->removeFile(k);
+ k--;
+ }
+ }
+
+ // Quick check: no preferred filters, nothing more to do.
+ if (prefFilter.isEmpty()) {
+ continue;
+ }
+
+ // Now deal with preferred configurations.
+ for (int axis=AXIS_START; axis<=AXIS_END; axis++) {
+ for (size_t k=0; k<grp->getFiles().size(); k++) {
+ sp<AaptFile> file = grp->getFiles().valueAt(k);
+ if (k == 0 && grp->getFiles().size() == 1) {
+ // If this is the only file left, we need to keep it.
+ // Otherwise the resource IDs we are using will be inconsistent
+ // with what we get when not stripping. Sucky, but at least
+ // for now we can rely on the back-end doing another filtering
+ // pass to take this out and leave us with this resource name
+ // containing no entries.
+ continue;
+ }
+ if (file->getPath().getPathExtension() == ".xml") {
+ // We can't remove .xml files at this point, because when
+ // we parse them they may add identifier resources, so
+ // removing them can cause our resource identifiers to
+ // become inconsistent.
+ continue;
+ }
+ const ResTable_config& config(file->getGroupEntry().toParams());
+ if (!prefFilter.match(axis, config)) {
+ // This is a resource we would prefer not to have. Check
+ // to see if have a similar variation that we would like
+ // to have and, if so, we can drop it.
+ for (size_t m=0; m<grp->getFiles().size(); m++) {
+ if (m == k) continue;
+ sp<AaptFile> mfile = grp->getFiles().valueAt(m);
+ const ResTable_config& mconfig(mfile->getGroupEntry().toParams());
+ if (AaptGroupEntry::configSameExcept(config, mconfig, axis)) {
+ if (prefFilter.match(axis, mconfig)) {
+ if (bundle->getVerbose()) {
+ printf("Pruning unneeded resource: %s\n",
+ file->getPrintableSource().string());
+ }
+ grp->removeFile(k);
+ k--;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return NO_ERROR;
+}
+
sp<AaptSymbols> AaptAssets::getSymbolsFor(const String8& name)
{
sp<AaptSymbols> sym = mSymbols.valueFor(name);
@@ -2179,26 +2427,39 @@
return mIncludedAssets.getResources(false);
}
-void AaptAssets::print() const
+void AaptAssets::print(const String8& prefix) const
{
- printf("Locale/Vendor pairs:\n");
+ String8 innerPrefix(prefix);
+ innerPrefix.append(" ");
+ String8 innerInnerPrefix(innerPrefix);
+ innerInnerPrefix.append(" ");
+ printf("%sConfigurations:\n", prefix.string());
const size_t N=mGroupEntries.size();
for (size_t i=0; i<N; i++) {
- printf(" %s/%s\n",
- mGroupEntries.itemAt(i).locale.string(),
- mGroupEntries.itemAt(i).vendor.string());
+ String8 cname = mGroupEntries.itemAt(i).toDirName(String8());
+ printf("%s %s\n", prefix.string(),
+ cname != "" ? cname.string() : "(default)");
}
- printf("\nFiles:\n");
- AaptDir::print();
+ printf("\n%sFiles:\n", prefix.string());
+ AaptDir::print(innerPrefix);
+
+ printf("\n%sResource Dirs:\n", prefix.string());
+ const Vector<sp<AaptDir> >& resdirs = mResDirs;
+ const size_t NR = resdirs.size();
+ for (size_t i=0; i<NR; i++) {
+ const sp<AaptDir>& d = resdirs.itemAt(i);
+ printf("%s Type %s\n", prefix.string(), d->getLeaf().string());
+ d->print(innerInnerPrefix);
+ }
}
-sp<AaptDir> AaptAssets::resDir(const String8& name)
+sp<AaptDir> AaptAssets::resDir(const String8& name) const
{
- const Vector<sp<AaptDir> >& dirs = mDirs;
- const size_t N = dirs.size();
+ const Vector<sp<AaptDir> >& resdirs = mResDirs;
+ const size_t N = resdirs.size();
for (size_t i=0; i<N; i++) {
- const sp<AaptDir>& d = dirs.itemAt(i);
+ const sp<AaptDir>& d = resdirs.itemAt(i);
if (d->getLeaf() == name) {
return d;
}
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 82dfd71..d5345b2 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -24,6 +24,8 @@
bool valid_symbol_name(const String8& str);
+class AaptAssets;
+
enum {
AXIS_NONE = 0,
AXIS_MCC = 1,
@@ -45,7 +47,10 @@
AXIS_SMALLESTSCREENWIDTHDP,
AXIS_SCREENWIDTHDP,
AXIS_SCREENHEIGHTDP,
- AXIS_VERSION
+ AXIS_VERSION,
+
+ AXIS_START = AXIS_MCC,
+ AXIS_END = AXIS_VERSION,
};
enum {
@@ -56,6 +61,7 @@
SDK_MR1 = 7,
SDK_FROYO = 8,
SDK_HONEYCOMB_MR2 = 13,
+ SDK_ICE_CREAM_SANDWICH = 14,
};
/**
@@ -65,35 +71,19 @@
struct AaptGroupEntry
{
public:
- AaptGroupEntry() { }
+ AaptGroupEntry() : mParamsChanged(true) { }
AaptGroupEntry(const String8& _locale, const String8& _vendor)
- : locale(_locale), vendor(_vendor) { }
-
- String8 mcc;
- String8 mnc;
- String8 locale;
- String8 vendor;
- String8 smallestScreenWidthDp;
- String8 screenWidthDp;
- String8 screenHeightDp;
- String8 screenLayoutSize;
- String8 screenLayoutLong;
- String8 orientation;
- String8 uiModeType;
- String8 uiModeNight;
- String8 density;
- String8 touchscreen;
- String8 keysHidden;
- String8 keyboard;
- String8 navHidden;
- String8 navigation;
- String8 screenSize;
- String8 version;
+ : locale(_locale), vendor(_vendor), mParamsChanged(true) { }
bool initFromDirName(const char* dir, String8* resType);
static status_t parseNamePart(const String8& part, int* axis, uint32_t* value);
-
+
+ static uint32_t getConfigValueForAxis(const ResTable_config& config, int axis);
+
+ static bool configSameExcept(const ResTable_config& config,
+ const ResTable_config& otherConfig, int axis);
+
static bool getMccName(const char* name, ResTable_config* out = NULL);
static bool getMncName(const char* name, ResTable_config* out = NULL);
static bool getLocaleName(const char* name, ResTable_config* out = NULL);
@@ -116,7 +106,7 @@
int compare(const AaptGroupEntry& o) const;
- ResTable_config toParams() const;
+ const ResTable_config& toParams() const;
inline bool operator<(const AaptGroupEntry& o) const { return compare(o) < 0; }
inline bool operator<=(const AaptGroupEntry& o) const { return compare(o) <= 0; }
@@ -127,6 +117,33 @@
String8 toString() const;
String8 toDirName(const String8& resType) const;
+
+ const String8& getVersionString() const { return version; }
+
+private:
+ String8 mcc;
+ String8 mnc;
+ String8 locale;
+ String8 vendor;
+ String8 smallestScreenWidthDp;
+ String8 screenWidthDp;
+ String8 screenHeightDp;
+ String8 screenLayoutSize;
+ String8 screenLayoutLong;
+ String8 orientation;
+ String8 uiModeType;
+ String8 uiModeNight;
+ String8 density;
+ String8 touchscreen;
+ String8 keysHidden;
+ String8 keyboard;
+ String8 navHidden;
+ String8 navigation;
+ String8 screenSize;
+ String8 version;
+
+ mutable bool mParamsChanged;
+ mutable ResTable_config mParams;
};
inline int compare_type(const AaptGroupEntry& lhs, const AaptGroupEntry& rhs)
@@ -225,7 +242,7 @@
status_t addFile(const sp<AaptFile>& file);
void removeFile(size_t index);
- void print() const;
+ void print(const String8& prefix) const;
String8 getPrintableSource() const;
@@ -237,7 +254,7 @@
};
/**
- * A single directory of assets, which can contain for files and other
+ * A single directory of assets, which can contain files and other
* sub-directories.
*/
class AaptDir : public RefBase
@@ -254,25 +271,11 @@
const DefaultKeyedVector<String8, sp<AaptGroup> >& getFiles() const { return mFiles; }
const DefaultKeyedVector<String8, sp<AaptDir> >& getDirs() const { return mDirs; }
- status_t addFile(const String8& name, const sp<AaptGroup>& file);
- status_t addDir(const String8& name, const sp<AaptDir>& dir);
-
- sp<AaptDir> makeDir(const String8& name);
+ virtual status_t addFile(const String8& name, const sp<AaptGroup>& file);
void removeFile(const String8& name);
void removeDir(const String8& name);
- status_t renameFile(const sp<AaptFile>& file, const String8& newName);
-
- status_t addLeafFile(const String8& leafName,
- const sp<AaptFile>& file);
-
- virtual ssize_t slurpFullTree(Bundle* bundle,
- const String8& srcDir,
- const AaptGroupEntry& kind,
- const String8& resType,
- sp<FilePathStore>& fullResPaths);
-
/*
* Perform some sanity checks on the names of files and directories here.
* In particular:
@@ -292,11 +295,23 @@
*/
status_t validate() const;
- void print() const;
+ void print(const String8& prefix) const;
String8 getPrintableSource() const;
private:
+ friend class AaptAssets;
+
+ status_t addDir(const String8& name, const sp<AaptDir>& dir);
+ sp<AaptDir> makeDir(const String8& name);
+ status_t addLeafFile(const String8& leafName,
+ const sp<AaptFile>& file);
+ virtual ssize_t slurpFullTree(Bundle* bundle,
+ const String8& srcDir,
+ const AaptGroupEntry& kind,
+ const String8& resType,
+ sp<FilePathStore>& fullResPaths);
+
String8 mLeaf;
String8 mPath;
@@ -501,13 +516,15 @@
class AaptAssets : public AaptDir
{
public:
- AaptAssets() : AaptDir(String8(), String8()), mHaveIncludedAssets(false), mRes(NULL) { }
+ AaptAssets();
virtual ~AaptAssets() { delete mRes; }
const String8& getPackage() const { return mPackage; }
void setPackage(const String8& package) { mPackage = package; mSymbolsPrivatePackage = package; }
- const SortedVector<AaptGroupEntry>& getGroupEntries() const { return mGroupEntries; }
+ const SortedVector<AaptGroupEntry>& getGroupEntries() const;
+
+ virtual status_t addFile(const String8& name, const sp<AaptGroup>& file);
sp<AaptFile> addFile(const String8& filePath,
const AaptGroupEntry& entry,
@@ -524,15 +541,6 @@
ssize_t slurpFromArgs(Bundle* bundle);
- virtual ssize_t slurpFullTree(Bundle* bundle,
- const String8& srcDir,
- const AaptGroupEntry& kind,
- const String8& resType,
- sp<FilePathStore>& fullResPaths);
-
- ssize_t slurpResourceTree(Bundle* bundle, const String8& srcDir);
- ssize_t slurpResourceZip(Bundle* bundle, const char* filename);
-
sp<AaptSymbols> getSymbolsFor(const String8& name);
const DefaultKeyedVector<String8, sp<AaptSymbols> >& getSymbols() const { return mSymbols; }
@@ -544,10 +552,10 @@
status_t addIncludedResources(const sp<AaptFile>& file);
const ResTable& getIncludedResources() const;
- void print() const;
+ void print(const String8& prefix) const;
- inline const Vector<sp<AaptDir> >& resDirs() { return mDirs; }
- sp<AaptDir> resDir(const String8& name);
+ inline const Vector<sp<AaptDir> >& resDirs() const { return mResDirs; }
+ sp<AaptDir> resDir(const String8& name) const;
inline sp<AaptAssets> getOverlay() { return mOverlay; }
inline void setOverlay(sp<AaptAssets>& overlay) { mOverlay = overlay; }
@@ -565,12 +573,25 @@
setFullAssetPaths(sp<FilePathStore>& res) { mFullAssetPaths = res; }
private:
+ virtual ssize_t slurpFullTree(Bundle* bundle,
+ const String8& srcDir,
+ const AaptGroupEntry& kind,
+ const String8& resType,
+ sp<FilePathStore>& fullResPaths);
+
+ ssize_t slurpResourceTree(Bundle* bundle, const String8& srcDir);
+ ssize_t slurpResourceZip(Bundle* bundle, const char* filename);
+
+ status_t filter(Bundle* bundle);
+
String8 mPackage;
SortedVector<AaptGroupEntry> mGroupEntries;
DefaultKeyedVector<String8, sp<AaptSymbols> > mSymbols;
String8 mSymbolsPrivatePackage;
- Vector<sp<AaptDir> > mDirs;
+ Vector<sp<AaptDir> > mResDirs;
+
+ bool mChanged;
bool mHaveIncludedAssets;
AssetManager mIncludedAssets;
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index e507fb9..a3e5d9a 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -19,6 +19,7 @@
Package.cpp \
StringPool.cpp \
XMLNode.cpp \
+ ResourceFilter.cpp \
ResourceTable.cpp \
Images.cpp \
Resource.cpp \
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index 539c312..2d1060b 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -122,6 +122,8 @@
void setRClassDir(const char* dir) { mRClassDir = dir; }
const char* getConfigurations() const { return mConfigurations.size() > 0 ? mConfigurations.string() : NULL; }
void addConfigurations(const char* val) { if (mConfigurations.size() > 0) { mConfigurations.append(","); mConfigurations.append(val); } else { mConfigurations = val; } }
+ const char* getPreferredConfigurations() const { return mPreferredConfigurations.size() > 0 ? mPreferredConfigurations.string() : NULL; }
+ void addPreferredConfigurations(const char* val) { if (mPreferredConfigurations.size() > 0) { mPreferredConfigurations.append(","); mPreferredConfigurations.append(val); } else { mPreferredConfigurations = val; } }
const char* getResourceIntermediatesDir() const { return mResourceIntermediatesDir; }
void setResourceIntermediatesDir(const char* dir) { mResourceIntermediatesDir = dir; }
const android::Vector<const char*>& getPackageIncludes() const { return mPackageIncludes; }
@@ -244,6 +246,7 @@
const char* mRClassDir;
const char* mResourceIntermediatesDir;
android::String8 mConfigurations;
+ android::String8 mPreferredConfigurations;
android::Vector<const char*> mPackageIncludes;
android::Vector<const char*> mJarFiles;
android::Vector<const char*> mNoCompressExtensions;
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 413a2dc..637c27d 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -5,6 +5,7 @@
//
#include "Main.h"
#include "Bundle.h"
+#include "ResourceFilter.h"
#include "ResourceTable.h"
#include "XMLNode.h"
@@ -1572,7 +1573,7 @@
}
if (bundle->getVerbose()) {
- assets->print();
+ assets->print(String8());
}
// If they asked for any fileAs that need to be compiled, do so.
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp
index 311ceea..ffbe875 100644
--- a/tools/aapt/Images.cpp
+++ b/tools/aapt/Images.cpp
@@ -980,6 +980,10 @@
String8 printableName(file->getPrintableSource());
+ if (bundle->getVerbose()) {
+ printf("Processing image: %s\n", printableName.string());
+ }
+
png_structp read_ptr = NULL;
png_infop read_info = NULL;
FILE* fp;
@@ -1094,6 +1098,10 @@
status_t error = UNKNOWN_ERROR;
+ if (bundle->getVerbose()) {
+ printf("Processing image to cache: %s => %s\n", source.string(), dest.string());
+ }
+
// Get a file handler to read from
fp = fopen(source.string(),"rb");
if (fp == NULL) {
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 5135787..50c828d 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -65,9 +65,10 @@
" [--max-res-version VAL] \\\n"
" [-I base-package [-I base-package ...]] \\\n"
" [-A asset-source-dir] [-G class-list-file] [-P public-definitions-file] \\\n"
- " [-S resource-sources [-S resource-sources ...]] "
+ " [-S resource-sources [-S resource-sources ...]] \\\n"
" [-F apk-file] [-J R-file-dir] \\\n"
" [--product product1,product2,...] \\\n"
+ " [-c CONFIGS] [--preferred-configurations CONFIGS] \\\n"
" [-o] \\\n"
" [raw-files-dir [raw-files-dir] ...]\n"
"\n"
@@ -154,6 +155,10 @@
" generate dependency files in the same directories for R.java and resource package\n"
" --auto-add-overlay\n"
" Automatically add resources that are only in overlays.\n"
+ " --preferred-configurations\n"
+ " Like the -c option for filtering out unneeded configurations, but\n"
+ " only expresses a preference. If there is no resource available with\n"
+ " the preferred configuration then it will not be stripped.\n"
" --rename-manifest-package\n"
" Rewrite the manifest so that its package name is the package name\n"
" given here. Relative class names (for example .Foo) will be\n"
@@ -509,6 +514,15 @@
bundle.setGenDependencies(true);
} else if (strcmp(cp, "-utf16") == 0) {
bundle.setWantUTF16(true);
+ } else if (strcmp(cp, "-preferred-configurations") == 0) {
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '--preferred-configurations' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ bundle.addPreferredConfigurations(argv[0]);
} else if (strcmp(cp, "-rename-manifest-package") == 0) {
argc--;
argv++;
diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp
index 1e3efde..3930117 100644
--- a/tools/aapt/Package.cpp
+++ b/tools/aapt/Package.cpp
@@ -6,6 +6,7 @@
#include "Main.h"
#include "AaptAssets.h"
#include "ResourceTable.h"
+#include "ResourceFilter.h"
#include <utils/Log.h>
#include <utils/threads.h>
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 2e796a2..887fa74 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -352,18 +352,27 @@
if (index < 0) {
sp<ResourceTypeSet> set = new ResourceTypeSet();
+ NOISY(printf("Creating new resource type set for leaf %s with group %s (%p)\n",
+ leafName.string(), group->getPath().string(), group.get()));
set->add(leafName, group);
resources->add(resType, set);
} else {
sp<ResourceTypeSet> set = resources->valueAt(index);
index = set->indexOfKey(leafName);
if (index < 0) {
+ NOISY(printf("Adding to resource type set for leaf %s group %s (%p)\n",
+ leafName.string(), group->getPath().string(), group.get()));
set->add(leafName, group);
} else {
sp<AaptGroup> existingGroup = set->valueAt(index);
- int M = files.size();
- for (int j=0; j<M; j++) {
- existingGroup->addFile(files.valueAt(j));
+ NOISY(printf("Extending to resource type set for leaf %s group %s (%p)\n",
+ leafName.string(), group->getPath().string(), group.get()));
+ for (size_t j=0; j<files.size(); j++) {
+ NOISY(printf("Adding file %s in group %s resType %s\n",
+ files.valueAt(j)->getSourceFile().string(),
+ files.keyAt(j).toDirName(String8()).string(),
+ resType.string()));
+ status_t err = existingGroup->addFile(files.valueAt(j));
}
}
}
@@ -378,9 +387,12 @@
for (int i=0; i<N; i++) {
sp<AaptDir> d = dirs.itemAt(i);
+ NOISY(printf("Collecting dir #%d %p: %s, leaf %s\n", i, d.get(), d->getPath().string(),
+ d->getLeaf().string()));
collect_files(d, resources);
// don't try to include the res dir
+ NOISY(printf("Removing dir leaf %s\n", d->getLeaf().string()));
ass->removeDir(d->getLeaf());
}
}
@@ -570,7 +582,7 @@
size_t baseFileIndex =
baseGroup->getFiles().indexOfKey(overlayFiles.
keyAt(overlayGroupIndex));
- if(baseFileIndex < UNKNOWN_ERROR) {
+ if (baseFileIndex < UNKNOWN_ERROR) {
if (bundle->getVerbose()) {
printf("found a match (%zd) for overlay file %s, for flavor %s\n",
baseFileIndex,
@@ -580,6 +592,11 @@
baseGroup->removeFile(baseFileIndex);
} else {
// didn't find a match fall through and add it..
+ if (true || bundle->getVerbose()) {
+ printf("nothing matches overlay file %s, for flavor %s\n",
+ overlayGroup->getLeaf().string(),
+ overlayFiles.keyAt(overlayGroupIndex).toString().string());
+ }
}
baseGroup->addFile(overlayFiles.valueAt(overlayGroupIndex));
assets->addGroupEntry(overlayFiles.keyAt(overlayGroupIndex));
diff --git a/tools/aapt/ResourceFilter.cpp b/tools/aapt/ResourceFilter.cpp
new file mode 100644
index 0000000..8cfd2a5
--- /dev/null
+++ b/tools/aapt/ResourceFilter.cpp
@@ -0,0 +1,112 @@
+//
+// Copyright 2011 The Android Open Source Project
+//
+// Build resource files from raw assets.
+//
+
+#include "ResourceFilter.h"
+
+status_t
+ResourceFilter::parse(const char* arg)
+{
+ if (arg == NULL) {
+ return 0;
+ }
+
+ const char* p = arg;
+ const char* q;
+
+ while (true) {
+ q = strchr(p, ',');
+ if (q == NULL) {
+ q = p + strlen(p);
+ }
+
+ String8 part(p, q-p);
+
+ if (part == "zz_ZZ") {
+ mContainsPseudo = true;
+ }
+ int axis;
+ uint32_t value;
+ if (AaptGroupEntry::parseNamePart(part, &axis, &value)) {
+ fprintf(stderr, "Invalid configuration: %s\n", arg);
+ fprintf(stderr, " ");
+ for (int i=0; i<p-arg; i++) {
+ fprintf(stderr, " ");
+ }
+ for (int i=0; i<q-p; i++) {
+ fprintf(stderr, "^");
+ }
+ fprintf(stderr, "\n");
+ return 1;
+ }
+
+ ssize_t index = mData.indexOfKey(axis);
+ if (index < 0) {
+ mData.add(axis, SortedVector<uint32_t>());
+ }
+ SortedVector<uint32_t>& sv = mData.editValueFor(axis);
+ sv.add(value);
+ // if it's a locale with a region, also match an unmodified locale of the
+ // same language
+ if (axis == AXIS_LANGUAGE) {
+ if (value & 0xffff0000) {
+ sv.add(value & 0x0000ffff);
+ }
+ }
+ p = q;
+ if (!*p) break;
+ p++;
+ }
+
+ return NO_ERROR;
+}
+
+bool
+ResourceFilter::isEmpty() const
+{
+ return mData.size() == 0;
+}
+
+bool
+ResourceFilter::match(int axis, uint32_t value) const
+{
+ if (value == 0) {
+ // they didn't specify anything so take everything
+ return true;
+ }
+ ssize_t index = mData.indexOfKey(axis);
+ if (index < 0) {
+ // we didn't request anything on this axis so take everything
+ return true;
+ }
+ const SortedVector<uint32_t>& sv = mData.valueAt(index);
+ return sv.indexOf(value) >= 0;
+}
+
+bool
+ResourceFilter::match(int axis, const ResTable_config& config) const
+{
+ return match(axis, AaptGroupEntry::getConfigValueForAxis(config, axis));
+}
+
+bool
+ResourceFilter::match(const ResTable_config& config) const
+{
+ for (int i=AXIS_START; i<=AXIS_END; i++) {
+ if (!match(i, AaptGroupEntry::getConfigValueForAxis(config, i))) {
+ return false;
+ }
+ }
+ return true;
+}
+
+const SortedVector<uint32_t>* ResourceFilter::configsForAxis(int axis) const
+{
+ ssize_t index = mData.indexOfKey(axis);
+ if (index < 0) {
+ return NULL;
+ }
+ return &mData.valueAt(index);
+}
diff --git a/tools/aapt/ResourceFilter.h b/tools/aapt/ResourceFilter.h
new file mode 100644
index 0000000..647b7bb
--- /dev/null
+++ b/tools/aapt/ResourceFilter.h
@@ -0,0 +1,33 @@
+//
+// Copyright 2011 The Android Open Source Project
+//
+// Build resource files from raw assets.
+//
+
+#ifndef RESOURCE_FILTER_H
+#define RESOURCE_FILTER_H
+
+#include "AaptAssets.h"
+
+/**
+ * Implements logic for parsing and handling "-c" and "--preferred-configurations"
+ * options.
+ */
+class ResourceFilter
+{
+public:
+ ResourceFilter() : mData(), mContainsPseudo(false) {}
+ status_t parse(const char* arg);
+ bool isEmpty() const;
+ bool match(int axis, uint32_t value) const;
+ bool match(int axis, const ResTable_config& config) const;
+ bool match(const ResTable_config& config) const;
+ const SortedVector<uint32_t>* configsForAxis(int axis) const;
+ inline bool containsPseudo() const { return mContainsPseudo; }
+
+private:
+ KeyedVector<int,SortedVector<uint32_t> > mData;
+ bool mContainsPseudo;
+};
+
+#endif
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 99f74c6..fdb39ca 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -7,6 +7,7 @@
#include "ResourceTable.h"
#include "XMLNode.h"
+#include "ResourceFilter.h"
#include <utils/ByteOrder.h>
#include <utils/ResourceTypes.h>
@@ -2528,135 +2529,6 @@
return err;
}
-
-status_t
-ResourceFilter::parse(const char* arg)
-{
- if (arg == NULL) {
- return 0;
- }
-
- const char* p = arg;
- const char* q;
-
- while (true) {
- q = strchr(p, ',');
- if (q == NULL) {
- q = p + strlen(p);
- }
-
- String8 part(p, q-p);
-
- if (part == "zz_ZZ") {
- mContainsPseudo = true;
- }
- int axis;
- uint32_t value;
- if (AaptGroupEntry::parseNamePart(part, &axis, &value)) {
- fprintf(stderr, "Invalid configuration: %s\n", arg);
- fprintf(stderr, " ");
- for (int i=0; i<p-arg; i++) {
- fprintf(stderr, " ");
- }
- for (int i=0; i<q-p; i++) {
- fprintf(stderr, "^");
- }
- fprintf(stderr, "\n");
- return 1;
- }
-
- ssize_t index = mData.indexOfKey(axis);
- if (index < 0) {
- mData.add(axis, SortedVector<uint32_t>());
- }
- SortedVector<uint32_t>& sv = mData.editValueFor(axis);
- sv.add(value);
- // if it's a locale with a region, also match an unmodified locale of the
- // same language
- if (axis == AXIS_LANGUAGE) {
- if (value & 0xffff0000) {
- sv.add(value & 0x0000ffff);
- }
- }
- p = q;
- if (!*p) break;
- p++;
- }
-
- return NO_ERROR;
-}
-
-bool
-ResourceFilter::match(int axis, uint32_t value) const
-{
- if (value == 0) {
- // they didn't specify anything so take everything
- return true;
- }
- ssize_t index = mData.indexOfKey(axis);
- if (index < 0) {
- // we didn't request anything on this axis so take everything
- return true;
- }
- const SortedVector<uint32_t>& sv = mData.valueAt(index);
- return sv.indexOf(value) >= 0;
-}
-
-bool
-ResourceFilter::match(const ResTable_config& config) const
-{
- if (config.locale) {
- uint32_t locale = (config.country[1] << 24) | (config.country[0] << 16)
- | (config.language[1] << 8) | (config.language[0]);
- if (!match(AXIS_LANGUAGE, locale)) {
- return false;
- }
- }
- if (!match(AXIS_ORIENTATION, config.orientation)) {
- return false;
- }
- if (!match(AXIS_UIMODETYPE, (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE))) {
- return false;
- }
- if (!match(AXIS_UIMODENIGHT, (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT))) {
- return false;
- }
- if (!match(AXIS_DENSITY, config.density)) {
- return false;
- }
- if (!match(AXIS_TOUCHSCREEN, config.touchscreen)) {
- return false;
- }
- if (!match(AXIS_KEYSHIDDEN, config.inputFlags)) {
- return false;
- }
- if (!match(AXIS_KEYBOARD, config.keyboard)) {
- return false;
- }
- if (!match(AXIS_NAVIGATION, config.navigation)) {
- return false;
- }
- if (!match(AXIS_SCREENSIZE, config.screenSize)) {
- return false;
- }
- if (!match(AXIS_SMALLESTSCREENWIDTHDP, config.smallestScreenWidthDp)) {
- return false;
- }
- if (!match(AXIS_SCREENWIDTHDP, config.screenWidthDp)) {
- return false;
- }
- if (!match(AXIS_SCREENHEIGHTDP, config.screenHeightDp)) {
- return false;
- }
- if (!match(AXIS_SCREENLAYOUTSIZE, config.screenLayout&ResTable_config::MASK_SCREENSIZE)) {
- return false;
- }
- if (!match(AXIS_VERSION, config.version)) {
- return false;
- }
- return true;
-}
-
status_t ResourceTable::flatten(Bundle* bundle, const sp<AaptFile>& dest)
{
ResourceFilter filter;
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index 80f2192..8123bb3 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -549,19 +549,4 @@
map<String16, set<String8> > mLocalizations;
};
-class ResourceFilter
-{
-public:
- ResourceFilter() : mData(), mContainsPseudo(false) {}
- status_t parse(const char* arg);
- bool match(int axis, uint32_t value) const;
- bool match(const ResTable_config& config) const;
- inline bool containsPseudo() const { return mContainsPseudo; }
-
-private:
- KeyedVector<int,SortedVector<uint32_t> > mData;
- bool mContainsPseudo;
-};
-
-
#endif