Merge "cherrypick from master - docs: nfc updates Change-Id: Iaa782911f14b11bc896ac9ef06db2c43104d1dac" into ics-mr0
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/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index c5ee48d..7863102 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-
+
package android.app;
import android.content.Context;
@@ -71,7 +71,9 @@
*/
public void disable(int what) {
try {
- mService.disable(what, mToken, mContext.getPackageName());
+ if (mService != null) {
+ mService.disable(what, mToken, mContext.getPackageName());
+ }
} catch (RemoteException ex) {
// system process is dead anyway.
throw new RuntimeException(ex);
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 62bb965..54a89ad 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -197,7 +197,10 @@
String apnName = intent.getStringExtra(Phone.DATA_APN_KEY);
mNetworkInfo.setRoaming(intent.getBooleanExtra(Phone.DATA_NETWORK_ROAMING_KEY,
false));
-
+ if (VDBG) {
+ log(mApnType + " setting isAvailable to " +
+ intent.getBooleanExtra(Phone.NETWORK_UNAVAILABLE_KEY,false));
+ }
mNetworkInfo.setIsAvailable(!intent.getBooleanExtra(Phone.NETWORK_UNAVAILABLE_KEY,
false));
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
index 1735592..7df0193 100644
--- a/core/java/android/net/NetworkStateTracker.java
+++ b/core/java/android/net/NetworkStateTracker.java
@@ -132,6 +132,9 @@
* Returns an indication of whether this network is available for
* connections. A value of {@code false} means that some quasi-permanent
* condition prevents connectivity to this network.
+ *
+ * NOTE that this is broken on multi-connection devices. Should be fixed in J release
+ * TODO - fix on multi-pdp devices
*/
public boolean isAvailable();
diff --git a/core/java/android/service/textservice/SpellCheckerService.java b/core/java/android/service/textservice/SpellCheckerService.java
index b96099e..2ecf307 100644
--- a/core/java/android/service/textservice/SpellCheckerService.java
+++ b/core/java/android/service/textservice/SpellCheckerService.java
@@ -35,6 +35,28 @@
* SpellCheckerService provides an abstract base class for a spell checker.
* This class combines a service to the system with the spell checker service interface that
* spell checker must implement.
+ *
+ * <p>In addition to the normal Service lifecycle methods, this class
+ * introduces a new specific callback that subclasses should override
+ * {@link #createSession()} to provide a spell checker session that is corresponding
+ * to requested language and so on. The spell checker session returned by this method
+ * should extend {@link SpellCheckerService.Session}.
+ * </p>
+ *
+ * <h3>Returning spell check results</h3>
+ *
+ * <p>{@link SpellCheckerService.Session#onGetSuggestions(TextInfo, int)}
+ * should return spell check results.
+ * It receives {@link android.view.textservice.TextInfo} and returns
+ * {@link android.view.textservice.SuggestionsInfo} for the input.
+ * You may want to override
+ * {@link SpellCheckerService.Session#onGetSuggestionsMultiple(TextInfo[], int, boolean)} for
+ * better performance and quality.
+ * </p>
+ *
+ * <p>Please note that {@link SpellCheckerService.Session#getLocale()} does not return a valid
+ * locale before {@link SpellCheckerService.Session#onCreate()} </p>
+ *
*/
public abstract class SpellCheckerService extends Service {
private static final String TAG = SpellCheckerService.class.getSimpleName();
@@ -89,7 +111,7 @@
* but will be called in series on another thread.
* @param textInfo the text metadata
* @param suggestionsLimit the number of limit of suggestions returned
- * @return SuggestionInfo which contains suggestions for textInfo
+ * @return SuggestionsInfo which contains suggestions for textInfo
*/
public abstract SuggestionsInfo onGetSuggestions(TextInfo textInfo, int suggestionsLimit);
@@ -101,7 +123,7 @@
* @param textInfos an array of the text metadata
* @param suggestionsLimit the number of limit of suggestions returned
* @param sequentialWords true if textInfos can be treated as sequential words.
- * @return an array of SuggestionInfo of onGetSuggestions
+ * @return an array of SuggestionsInfo of onGetSuggestions
*/
public SuggestionsInfo[] onGetSuggestionsMultiple(TextInfo[] textInfos,
int suggestionsLimit, boolean sequentialWords) {
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/View.java b/core/java/android/view/View.java
index d5f18cc..61b13d5 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -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.
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index cdf1f8d..83df8a5 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -134,6 +134,11 @@
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,
@@ -167,7 +172,8 @@
StreamResources.RingerStream,
StreamResources.VoiceStream,
StreamResources.MediaStream,
- StreamResources.NotificationStream
+ StreamResources.NotificationStream,
+ StreamResources.AlarmStream
};
/** Object that contains data for each slider */
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/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index 34c9c29..93caabe 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -35,6 +35,13 @@
* Subtype can describe locale (e.g. en_US, fr_FR...) and mode (e.g. voice, keyboard...), and is
* used for IME switch and settings. The input method subtype allows the system to bring up the
* specified subtype of the designated input method directly.
+ *
+ * <p>It should be defined in an XML resource file of the input method
+ * with the <code><subtype></code> element.
+ * For more information, see the guide to
+ * <a href="{@docRoot}resources/articles/creating-input-method.html">
+ * Creating an Input Method</a>.</p>
+ *
*/
public final class InputMethodSubtype implements Parcelable {
private static final String TAG = InputMethodSubtype.class.getSimpleName();
diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java
index b940b80..793f514 100644
--- a/core/java/android/view/textservice/SpellCheckerSession.java
+++ b/core/java/android/view/textservice/SpellCheckerSession.java
@@ -34,6 +34,51 @@
/**
* The SpellCheckerSession interface provides the per client functionality of SpellCheckerService.
+ *
+ *
+ * <a name="Applications"></a>
+ * <h3>Applications</h3>
+ *
+ * <p>In most cases, applications that are using the standard
+ * {@link android.widget.TextView} or its subclasses will have little they need
+ * to do to work well with spell checker services. The main things you need to
+ * be aware of are:</p>
+ *
+ * <ul>
+ * <li> Properly set the {@link android.R.attr#inputType} in your editable
+ * text views, so that the spell checker will have enough context to help the
+ * user in editing text in them.
+ * </ul>
+ *
+ * <p>For the rare people amongst us writing client applications that use the spell checker service
+ * directly, you will need to use {@link #getSuggestions(TextInfo, int)} or
+ * {@link #getSuggestions(TextInfo[], int, boolean)} for obtaining results from the spell checker
+ * service by yourself.</p>
+ *
+ * <h3>Security</h3>
+ *
+ * <p>There are a lot of security issues associated with spell checkers,
+ * since they could monitor all the text being sent to them
+ * through, for instance, {@link android.widget.TextView}.
+ * The Android spell checker framework also allows
+ * arbitrary third party spell checkers, so care must be taken to restrict their
+ * selection and interactions.</p>
+ *
+ * <p>Here are some key points about the security architecture behind the
+ * spell checker framework:</p>
+ *
+ * <ul>
+ * <li>Only the system is allowed to directly access a spell checker framework's
+ * {@link android.service.textservice.SpellCheckerService} interface, via the
+ * {@link android.Manifest.permission#BIND_TEXT_SERVICE} permission. This is
+ * enforced in the system by not binding to a spell checker service that does
+ * not require this permission.
+ *
+ * <li>The user must explicitly enable a new spell checker in settings before
+ * they can be enabled, to confirm with the system that they know about it
+ * and want to make it available for use.
+ * </ul>
+ *
*/
public class SpellCheckerSession {
private static final String TAG = SpellCheckerSession.class.getSimpleName();
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index b06c112..69f88a5 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -35,6 +35,31 @@
*
* The user can change the current text services in Settings. And also applications can specify
* the target text services.
+ *
+ * <h3>Architecture Overview</h3>
+ *
+ * <p>There are three primary parties involved in the text services
+ * framework (TSF) architecture:</p>
+ *
+ * <ul>
+ * <li> The <strong>text services manager</strong> as expressed by this class
+ * is the central point of the system that manages interaction between all
+ * other parts. It is expressed as the client-side API here which exists
+ * in each application context and communicates with a global system service
+ * that manages the interaction across all processes.
+ * <li> A <strong>text service</strong> implements a particular
+ * interaction model allowing the client application to retrieve information of text.
+ * The system binds to the current text service that is in use, causing it to be created and run.
+ * <li> Multiple <strong>client applications</strong> arbitrate with the text service
+ * manager for connections to text services.
+ * </ul>
+ *
+ * <h3>Text services sessions</h3>
+ * <ul>
+ * <li>The <strong>spell checker session</strong> is one of the text services.
+ * {@link android.view.textservice.SpellCheckerSession}</li>
+ * </ul>
+ *
*/
public final class TextServicesManager {
private static final String TAG = TextServicesManager.class.getSimpleName();
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 48615bd..6e81530 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1917,6 +1917,7 @@
mLoadedPicture = ViewStateSerializer.deserializeViewState(stream, this);
mBlockWebkitViewMessages = true;
setNewPicture(mLoadedPicture, true);
+ mLoadedPicture.mViewState = null;
return true;
} catch (IOException e) {
Log.w(LOGTAG, "Failed to loadViewState", e);
@@ -4355,7 +4356,9 @@
selectionDone();
}
mOrientation = newConfig.orientation;
- mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT);
+ if (mWebViewCore != null && !mBlockWebkitViewMessages) {
+ mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT);
+ }
}
/**
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 206142a5..9151fdd 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -314,7 +314,10 @@
* Returns the zoom scale used for reading text on a double-tap.
*/
public final float getReadingLevelScale() {
- return mDisplayDensity * mWebView.getSettings().getDoubleTapZoom() / 100.0f;
+ WebSettings settings = mWebView.getSettings();
+ final float doubleTapZoomFactor = settings != null
+ ? settings.getDoubleTapZoom() / 100.f : 1.0f;
+ return mDisplayDensity * doubleTapZoomFactor;
}
public final float getInvDefaultScale() {
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/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/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 a7b5cd6..bf2cf8d 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 f96d123f..00427a1 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 b614b18..0ee10ac 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 e4f72f6..e07be7c 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 7c1dd9d..fcea3b4 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 0569e08..4006bd4 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 3d9afa8..7c1bab0 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 206e43f..c69bcf8 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 58103c8..a8cedd1 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 2ffe7a6..bc57f7a 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 7a92c9a..34209c0 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_star_off_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_dark.png
index 45a8d86..61f9e6b 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 94a0c12..62ac7f9 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 70a6e90..e10d5d1 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 4b76e28..685f8b5 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 bc2f696..d7ef1a6 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 6f83c05..fcf4623 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 86d42bb..9a6fc4d 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 9e3b006..3875ac3 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 1729228..a929e09 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 ff78fc5..013ca85 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 9a136d9..57cfa4d 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 d49952b..1a37993 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 2014422..5694cf7 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 80885d1..6406c06 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 35239da..c50efaf 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 09aecf4..1a899c9e 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 b667738..37547d2 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 392f852..7b0e089 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 b36bc53..692d705 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 e0f82606..769cb12 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 5fb6e96..c5372a8 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 8c80ea1..1dee51b 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 80e1fba..3c1e25a 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 4b9bf53..4cf50ad 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 d2ced31..d201bfb7 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 4ec4508..efb29f1 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 7b8168c..176d448 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 22783c9..f37b16a 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 c6a2e17..d88087b 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 5805ce1..1780ec0 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 6429517..58a5f16 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 c995c87..f9a8c7c 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 c75363b..b47cd08 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 69885ea..6e16e40 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 8cf2b4b..0dd81c0 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 60873dd7..5f1b881 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_text_dot.png b/core/res/res/drawable-hdpi/ic_text_dot.png
index a7eaec5..fa69c69 100644
--- a/core/res/res/drawable-hdpi/ic_text_dot.png
+++ b/core/res/res/drawable-hdpi/ic_text_dot.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 e77921c..449d427 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 b5e714a..14f4ff8 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 c659d94..5cf9086 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/rate_star_big_half_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_big_half_holo_dark.png
index c6d1cd1..67890f0 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 89afee8..e9ffa5b 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 58a2d40..cc08f88 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 fdbc011..ebdb47b 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 ec3394e..d594c46 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 3e90f35..b4fd29b 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 ae5e49b..d1756c7 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 73183ad..4605a42 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 279427b..41f33a8 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 e0edec9..6cd59ea 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 d61b613..e03711e 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 0bba5ba..a5ee171 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 f8d978a..c7fb673 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 b7f8e62..134a38b 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 d8cdd19d7..0e7c8a9 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 f830a03..4048260 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 03f030b..90e9c9c 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 604490d..383543a 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 2705a06..49841ea 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 1954c8c..69f0070 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 df1573b..c8358e9 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 8dcdc17..f62f74b 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 eff7117..c29ab07 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 50461b5..287afc6 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_sys_download_anim1.png b/core/res/res/drawable-hdpi/stat_sys_download_anim1.png
index ff29bbf..0b1aa34 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_tether_wifi.png b/core/res/res/drawable-hdpi/stat_sys_tether_wifi.png
index e0bd38b..7d4df50 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 fff81d7..39d2c95f 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 cabdc39..937720f 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/sym_def_app_icon.png b/core/res/res/drawable-hdpi/sym_def_app_icon.png
index c8a38ed..96a442e 100644
--- a/core/res/res/drawable-hdpi/sym_def_app_icon.png
+++ b/core/res/res/drawable-hdpi/sym_def_app_icon.png
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 eead92c..d2ed06d 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 185d839..be2dc68 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 e9fceec..e419249 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-mdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
index 9835b0f..06f0518 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/fastscroll_label_left_holo_light.9.png b/core/res/res/drawable-mdpi/fastscroll_label_left_holo_light.9.png
index cee85bb..987c097 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 bd496f8..8d87032 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 22f25ca..7fee560 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_text_dot.png b/core/res/res/drawable-mdpi/ic_text_dot.png
index 47913f6..2225bd5 100644
--- a/core/res/res/drawable-mdpi/ic_text_dot.png
+++ b/core/res/res/drawable-mdpi/ic_text_dot.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 989e76b..52c9e3a 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/scrubber_control_pressed_holo.png b/core/res/res/drawable-mdpi/scrubber_control_pressed_holo.png
index cb99fa3..ba53c0b 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/sym_def_app_icon.png b/core/res/res/drawable-mdpi/sym_def_app_icon.png
index b3e10f6..359047d 100644
--- a/core/res/res/drawable-mdpi/sym_def_app_icon.png
+++ b/core/res/res/drawable-mdpi/sym_def_app_icon.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 5ad26b8..96891ce 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-xhdpi/fastscroll_label_left_holo_dark.9.png b/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_dark.9.png
index 6a82a64..6e0244f 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 ccbdcc3..6a0bdfc 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_text_dot.png b/core/res/res/drawable-xhdpi/ic_text_dot.png
index d316f9a..869dd95 100644
--- a/core/res/res/drawable-xhdpi/ic_text_dot.png
+++ b/core/res/res/drawable-xhdpi/ic_text_dot.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 830aa27..55e2329 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/sym_def_app_icon.png b/core/res/res/drawable-xhdpi/sym_def_app_icon.png
index f381f86..71c6d76 100644
--- a/core/res/res/drawable-xhdpi/sym_def_app_icon.png
+++ b/core/res/res/drawable-xhdpi/sym_def_app_icon.png
Binary files differ
diff --git a/core/res/res/layout/grant_credentials_permission.xml b/core/res/res/layout/grant_credentials_permission.xml
index 3313590..dd85b33 100644
--- a/core/res/res/layout/grant_credentials_permission.xml
+++ b/core/res/res/layout/grant_credentials_permission.xml
@@ -77,7 +77,7 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/perms_dangerous_perm_color"
android:textStyle="bold"
- android:paddingLeft="6dip"
+ android:paddingLeft="16dip"
android:layout_toRightOf="@id/permission_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
@@ -88,7 +88,7 @@
android:textColor="@color/perms_dangerous_perm_color"
android:layout_marginTop="-4dip"
android:paddingBottom="8dip"
- android:paddingLeft="6dip"
+ android:paddingLeft="16dip"
android:layout_below="@id/account_type"
android:layout_toRightOf="@id/permission_icon"
android:layout_width="wrap_content"
@@ -101,7 +101,7 @@
android:textStyle="bold"
android:layout_marginTop="-4dip"
android:paddingBottom="8dip"
- android:paddingLeft="6dip"
+ android:paddingLeft="16dip"
android:layout_below="@id/account_name"
android:layout_toRightOf="@id/permission_icon"
android:layout_width="wrap_content"
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/colors.xml b/core/res/res/values/colors.xml
index a9c603f..c37871b 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -85,8 +85,8 @@
<color name="darker_gray">#aaa</color>
<!-- For security permissions -->
- <color name="perms_dangerous_grp_color">#dd6826</color>
- <color name="perms_dangerous_perm_color">#dd6826</color>
+ <color name="perms_dangerous_grp_color">#33b5e5</color>
+ <color name="perms_dangerous_perm_color">#33b5e5</color>
<color name="shadow">#cc222222</color>
<!-- For search-related UIs -->
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/data/sounds/AudioPackage7.mk b/data/sounds/AudioPackage7.mk
index 66edb7a..8d92b05 100755
--- a/data/sounds/AudioPackage7.mk
+++ b/data/sounds/AudioPackage7.mk
@@ -62,6 +62,6 @@
$(LOCAL_PATH)/ringtones/ogg/Scarabaeus.ogg:system/media/audio/ringtones/Scarabaeus.ogg \
$(LOCAL_PATH)/ringtones/ogg/Sceptrum.ogg:system/media/audio/ringtones/Sceptrum.ogg \
$(LOCAL_PATH)/ringtones/ogg/Solarium.ogg:system/media/audio/ringtones/Solarium.ogg \
- $(LOCAL_PATH)/ringtones/ogg/Testudo.ogg:system/media/audio/ringtones/Testudo.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Themos.ogg:system/media/audio/ringtones/Themos.ogg \
$(LOCAL_PATH)/ringtones/ogg/UrsaMinor.ogg:system/media/audio/ringtones/UrsaMinor.ogg \
$(LOCAL_PATH)/ringtones/ogg/Zeta.ogg:system/media/audio/ringtones/Zeta.ogg
diff --git a/data/sounds/ringtones/ogg/Themos.ogg b/data/sounds/ringtones/ogg/Themos.ogg
new file mode 100644
index 0000000..bc850b8
--- /dev/null
+++ b/data/sounds/ringtones/ogg/Themos.ogg
Binary files differ
diff --git a/data/sounds/ringtones/wav/Themos.wav b/data/sounds/ringtones/wav/Themos.wav
new file mode 100644
index 0000000..d4d5c6e
--- /dev/null
+++ b/data/sounds/ringtones/wav/Themos.wav
Binary files differ
diff --git a/docs/html/sdk/android-4.0.jd b/docs/html/sdk/android-4.0.jd
index b8cd947..9a9f02a 100644
--- a/docs/html/sdk/android-4.0.jd
+++ b/docs/html/sdk/android-4.0.jd
@@ -200,15 +200,14 @@
<h3 id="Calendar">Calendar Provider</h3>
-<p>The new calendar APIs allow you to access and modify the user’s calendars and events using the
-Calendar Provider. You can read, add, modify and delete calendars, events, attendees, reminders and
-alerts.</p>
+<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>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, for example, uses a sync adapter to synchronize Google
-Calendar events with the Calendar Provider, which can then be viewed with Android's built-in
+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
@@ -303,7 +302,7 @@
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
+<a href="{@docRoot}resources/samples/VoicemailProviderDemo/index.html">Voicemail Provider
Demo</a>.</p>
@@ -337,13 +336,19 @@
<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
+<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>
@@ -370,18 +375,37 @@
The focus or exposure in that area will continually update as the scene in the area changes.</p>
+<h4>Continuous auto focus for photos</h4>
+
+<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>
+<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>Lock auto exposure and white balance with {@link
+<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>
@@ -436,7 +460,7 @@
<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>
@@ -477,7 +501,7 @@
android.media.MediaMetadataRetriever}.</p>
<p>For a sample implementation, see the <a
-href=”{@docRoot}resources/samples/RandomMusicPlayer/index.html”>Random Music Player</a>, which
+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>
@@ -485,9 +509,9 @@
<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.
-New applications for Android 4.0 such as Google Talk and 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
@@ -572,7 +596,7 @@
<h3 id="AndroidBeam">Android Beam (NDEF Push with NFC)</h3>
<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
+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
@@ -619,7 +643,7 @@
android.nfc.NdefRecord} in the {@link android.nfc.NdefMessage}. For the activity you want to
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
@@ -628,7 +652,7 @@
should create an intent filter for your activity using the same URI scheme in order to receive the
incoming NDEF message.</p>
-<p>You should also pass an “Android application record” with your {@link android.nfc.NdefMessage} in
+<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
@@ -705,8 +729,8 @@
<li>{@link android.Manifest.permission#ACCESS_WIFI_STATE}</li>
<li>{@link android.Manifest.permission#CHANGE_WIFI_STATE}</li>
<li>{@link android.Manifest.permission#INTERNET} (although your app doesn’t technically connect
-to the Internet, the WiFi Direct implementation uses sockets that do require Internet
-permission to work).</li>
+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>
@@ -732,7 +756,7 @@
</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 Demo</a>
+look at the <a href="{@docRoot}resources/samples/WiFiDirectDemo/index.html">Wi-Fi Direct Demo</a>
sample application.</p>
@@ -767,7 +791,7 @@
<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
+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
@@ -1102,7 +1126,7 @@
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>
@@ -1141,8 +1165,8 @@
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 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
+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>
@@ -1150,9 +1174,9 @@
<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
+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
+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
@@ -1188,7 +1212,7 @@
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
+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
@@ -1224,7 +1248,8 @@
</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>
@@ -1237,7 +1262,7 @@
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 <a
+“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>
@@ -1259,7 +1284,7 @@
<h4>Other APIs for action bar</h4>
<ul>
<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
+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
@@ -1307,7 +1332,7 @@
and navigation bar:</p>
<ul>
<li>The {@link android.view.View#SYSTEM_UI_FLAG_LOW_PROFILE} flag replaces View.STATUS_BAR_HIDDEN
-flag. When set, this flag enables “low profile” mode for the system bar or
+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
@@ -1334,7 +1359,7 @@
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>
@@ -1351,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>
@@ -1380,9 +1406,9 @@
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>
@@ -1393,7 +1419,7 @@
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>
@@ -1413,7 +1439,7 @@
<h4>Hover events</h4>
-<p>The {@link android.view.View} class now supports “hover” events to enable richer interactions
+<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>
@@ -1435,11 +1461,11 @@
<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
+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>
@@ -1455,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},
@@ -1463,7 +1489,7 @@
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
@@ -1480,7 +1506,7 @@
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>
@@ -1538,11 +1564,11 @@
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>
@@ -1562,17 +1588,17 @@
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
+<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
+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,
+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>
@@ -1598,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>
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index 0d14f79..59675a8 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -1,8 +1,8 @@
page.title=ADT Plugin for Eclipse
adt.zip.version=14.0.0
adt.zip.download=ADT-14.0.0.zip
-adt.zip.bytes=6745047
-adt.zip.checksum=014312e1553e3b8da55cb6a24e33e432
+adt.zip.bytes=6747816
+adt.zip.checksum=3883973cd229dc4336911117af949509
@jd:body
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 67be5c9..82db803 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -2,20 +2,20 @@
sdk.redirect=0
sdk.win_installer=installer_r14-windows.exe
-sdk.win_installer_bytes=33860326
-sdk.win_installer_checksum=6d4f76385daaee766ad901699cdae6cc
+sdk.win_installer_bytes=33853391
+sdk.win_installer_checksum=4f1cb329a41328c2cee2908b31ae6f6b
sdk.win_download=android-sdk_r14-windows.zip
-sdk.win_bytes=33853090
-sdk.win_checksum=0c39628e296d6176ed928cc64498ba04
+sdk.win_bytes=33846273
+sdk.win_checksum=48d44ae4cfcadede68621acb53caee80
sdk.mac_download=android-sdk_r14-macosx.zip
-sdk.mac_bytes=30426431
-sdk.mac_checksum=189ce3e26dfb46298a7def21d3bdf271
+sdk.mac_bytes=30428734
+sdk.mac_checksum=812887018435382de8486f3bb26a5db4
sdk.linux_download=android-sdk_r14-linux.tgz
-sdk.linux_bytes=26082867
-sdk.linux_checksum=500483f8acd0d3cae94c68c3dcefbb98
+sdk.linux_bytes=26075938
+sdk.linux_checksum=35c989ff67184766dc4960813ede8ab5
@jd:body
diff --git a/include/gui/SensorManager.h b/include/gui/SensorManager.h
index e1b1a7be..3176462 100644
--- a/include/gui/SensorManager.h
+++ b/include/gui/SensorManager.h
@@ -20,6 +20,8 @@
#include <stdint.h>
#include <sys/types.h>
+#include <binder/IBinder.h>
+
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/Singleton.h>
@@ -41,7 +43,9 @@
// ----------------------------------------------------------------------------
-class SensorManager : public ASensorManager, public Singleton<SensorManager>
+class SensorManager :
+ public ASensorManager,
+ public Singleton<SensorManager>
{
public:
SensorManager();
@@ -52,9 +56,17 @@
sp<SensorEventQueue> createEventQueue();
private:
- sp<ISensorServer> mSensorServer;
- Sensor const** mSensorList;
- Vector<Sensor> mSensors;
+ // DeathRecipient interface
+ void sensorManagerDied();
+
+ status_t assertStateLocked() const;
+
+private:
+ mutable Mutex mLock;
+ mutable sp<ISensorServer> mSensorServer;
+ mutable Sensor const** mSensorList;
+ mutable Vector<Sensor> mSensors;
+ mutable sp<IBinder::DeathRecipient> mDeathObserver;
};
// ----------------------------------------------------------------------------
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..dafcdea 100644
--- a/libs/gui/SensorManager.cpp
+++ b/libs/gui/SensorManager.cpp
@@ -23,6 +23,7 @@
#include <utils/RefBase.h>
#include <utils/Singleton.h>
+#include <binder/IBinder.h>
#include <binder/IServiceManager.h>
#include <gui/ISensorServer.h>
@@ -40,17 +41,8 @@
SensorManager::SensorManager()
: mSensorList(0)
{
- const String16 name("sensorservice");
- while (getService(name, &mSensorServer) != NO_ERROR) {
- usleep(250000);
- }
-
- mSensors = mSensorServer->getSensorList();
- size_t count = mSensors.size();
- mSensorList = (Sensor const**)malloc(count * sizeof(Sensor*));
- for (size_t i=0 ; i<count ; i++) {
- mSensorList[i] = mSensors.array() + i;
- }
+ // okay we're not locked here, but it's not needed during construction
+ assertStateLocked();
}
SensorManager::~SensorManager()
@@ -58,29 +50,100 @@
free(mSensorList);
}
+void SensorManager::sensorManagerDied()
+{
+ Mutex::Autolock _l(mLock);
+ mSensorServer.clear();
+ free(mSensorList);
+ mSensorList = NULL;
+ mSensors.clear();
+}
+
+status_t SensorManager::assertStateLocked() const {
+ if (mSensorServer == NULL) {
+ // try for one second
+ const String16 name("sensorservice");
+ for (int i=0 ; i<4 ; i++) {
+ status_t err = getService(name, &mSensorServer);
+ if (err == NAME_NOT_FOUND) {
+ usleep(250000);
+ continue;
+ }
+ if (err != NO_ERROR) {
+ return err;
+ }
+ break;
+ }
+
+ class DeathObserver : public IBinder::DeathRecipient {
+ SensorManager& mSensorManger;
+ virtual void binderDied(const wp<IBinder>& who) {
+ LOGW("sensorservice died [%p]", who.unsafe_get());
+ mSensorManger.sensorManagerDied();
+ }
+ public:
+ DeathObserver(SensorManager& mgr) : mSensorManger(mgr) { }
+ };
+
+ mDeathObserver = new DeathObserver(*const_cast<SensorManager *>(this));
+ mSensorServer->asBinder()->linkToDeath(mDeathObserver);
+
+ mSensors = mSensorServer->getSensorList();
+ size_t count = mSensors.size();
+ mSensorList = (Sensor const**)malloc(count * sizeof(Sensor*));
+ for (size_t i=0 ; i<count ; i++) {
+ mSensorList[i] = mSensors.array() + i;
+ }
+ }
+
+ return NO_ERROR;
+}
+
+
+
ssize_t SensorManager::getSensorList(Sensor const* const** list) const
{
+ Mutex::Autolock _l(mLock);
+ status_t err = assertStateLocked();
+ if (err < 0) {
+ return ssize_t(err);
+ }
*list = mSensorList;
return mSensors.size();
}
Sensor const* SensorManager::getDefaultSensor(int type)
{
- // For now we just return the first sensor of that type we find.
- // in the future it will make sense to let the SensorService make
- // that decision.
- for (size_t i=0 ; i<mSensors.size() ; i++) {
- if (mSensorList[i]->getType() == type)
- return mSensorList[i];
+ Mutex::Autolock _l(mLock);
+ if (assertStateLocked() == NO_ERROR) {
+ // For now we just return the first sensor of that type we find.
+ // in the future it will make sense to let the SensorService make
+ // that decision.
+ for (size_t i=0 ; i<mSensors.size() ; i++) {
+ if (mSensorList[i]->getType() == type)
+ return mSensorList[i];
+ }
}
return NULL;
}
sp<SensorEventQueue> SensorManager::createEventQueue()
{
- sp<SensorEventQueue> result = new SensorEventQueue(
- mSensorServer->createSensorEventConnection());
- return result;
+ sp<SensorEventQueue> queue;
+
+ Mutex::Autolock _l(mLock);
+ while (assertStateLocked() == NO_ERROR) {
+ sp<ISensorEventConnection> connection =
+ mSensorServer->createSensorEventConnection();
+ if (connection == NULL) {
+ // SensorService just died.
+ LOGE("createEventQueue: connection is NULL. SensorService died.");
+ continue;
+ }
+ queue = new SensorEventQueue(connection);
+ break;
+ }
+ return queue;
}
// ----------------------------------------------------------------------------
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index e0c2b3b..1d20e248 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -517,8 +517,8 @@
ensureValidDirection(direction);
ensureValidStreamType(streamType);
-
- VolumeStreamState streamState = mStreamStates[STREAM_VOLUME_ALIAS[streamType]];
+ int streamTypeAlias = STREAM_VOLUME_ALIAS[streamType];
+ VolumeStreamState streamState = mStreamStates[streamTypeAlias];
final int oldIndex = (streamState.muteCount() != 0) ? streamState.mLastAudibleIndex : streamState.mIndex;
boolean adjustVolume = true;
@@ -527,14 +527,14 @@
if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
(!mVoiceCapable && streamType != AudioSystem.STREAM_VOICE_CALL &&
streamType != AudioSystem.STREAM_BLUETOOTH_SCO) ||
- (mVoiceCapable && streamType == AudioSystem.STREAM_RING)) {
+ (mVoiceCapable && streamTypeAlias == AudioSystem.STREAM_RING)) {
// do not vibrate if already in silent mode
if (mRingerMode != AudioManager.RINGER_MODE_NORMAL) {
flags &= ~AudioManager.FLAG_VIBRATE;
}
// Check if the ringer mode changes with this volume adjustment. If
// it does, it will handle adjusting the volume, so we won't below
- adjustVolume = checkForRingerModeChange(oldIndex, direction);
+ adjustVolume = checkForRingerModeChange(oldIndex, direction, streamTypeAlias);
}
// If stream is muted, adjust last audible index only
@@ -551,7 +551,7 @@
if (adjustVolume && streamState.adjustIndex(direction)) {
// Post message to set system volume (it in turn will post a message
// to persist). Do not change volume if stream is muted.
- sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, STREAM_VOLUME_ALIAS[streamType], SENDMSG_NOOP, 0, 0,
+ sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, streamTypeAlias, SENDMSG_NOOP, 0, 0,
streamState, 0);
}
index = streamState.mIndex;
@@ -567,6 +567,23 @@
final int oldIndex = (streamState.muteCount() != 0) ? streamState.mLastAudibleIndex : streamState.mIndex;
+ // setting ring or notifications volume to 0 on voice capable devices enters silent mode
+ if (mVoiceCapable && (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
+ (STREAM_VOLUME_ALIAS[streamType] == AudioSystem.STREAM_RING))) {
+ int newRingerMode = mRingerMode;
+ if (index == 0) {
+ newRingerMode = System.getInt(mContentResolver, System.VIBRATE_IN_SILENT, 1) == 1
+ ? AudioManager.RINGER_MODE_VIBRATE
+ : AudioManager.RINGER_MODE_SILENT;
+ setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], index, false, true);
+ } else {
+ newRingerMode = AudioManager.RINGER_MODE_NORMAL;
+ }
+ if (newRingerMode != mRingerMode) {
+ setRingerMode(newRingerMode);
+ }
+ }
+
index = rescaleIndex(index * 10, streamType, STREAM_VOLUME_ALIAS[streamType]);
setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], index, false, true);
@@ -692,6 +709,13 @@
if (isStreamMutedByRingerMode(streamType)) {
if (!isStreamAffectedByRingerMode(streamType) ||
mRingerMode == AudioManager.RINGER_MODE_NORMAL) {
+ // ring and notifications volume should never be 0 when not silenced
+ // on voice capable devices
+ if (mVoiceCapable &&
+ STREAM_VOLUME_ALIAS[streamType] == AudioSystem.STREAM_RING &&
+ mStreamStates[streamType].mLastAudibleIndex == 0) {
+ mStreamStates[streamType].mLastAudibleIndex = 10;
+ }
mStreamStates[streamType].mute(null, false);
mRingerModeMutedStreams &= ~(1 << streamType);
}
@@ -1593,7 +1617,7 @@
* adjusting volume. If so, this will set the proper ringer mode and volume
* indices on the stream states.
*/
- private boolean checkForRingerModeChange(int oldIndex, int direction) {
+ private boolean checkForRingerModeChange(int oldIndex, int direction, int streamType) {
boolean adjustVolumeIndex = true;
int newRingerMode = mRingerMode;
int uiIndex = (oldIndex + 5) / 10;
@@ -1608,7 +1632,8 @@
? AudioManager.RINGER_MODE_VIBRATE
: AudioManager.RINGER_MODE_SILENT;
}
- if (uiIndex == 0) {
+ if (uiIndex == 0 || (mPrevVolDirection == AudioManager.ADJUST_LOWER &&
+ mVoiceCapable && streamType == AudioSystem.STREAM_RING)) {
adjustVolumeIndex = false;
}
}
@@ -1616,13 +1641,8 @@
if (direction == AudioManager.ADJUST_RAISE) {
// exiting silent mode
newRingerMode = AudioManager.RINGER_MODE_NORMAL;
- if (uiIndex != 0) {
- adjustVolumeIndex = false;
- }
- } else {
- // prevent last audible index to reach 0
- adjustVolumeIndex = false;
}
+ adjustVolumeIndex = false;
}
if (newRingerMode != mRingerMode) {
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index f3174fe..63cbf5e 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -274,8 +274,14 @@
sp<ISurfaceTexture> new_st;
if (jsurface) {
sp<Surface> surface(Surface_getSurface(env, jsurface));
- new_st = surface->getSurfaceTexture();
- new_st->incStrong(thiz);
+ if (surface != NULL) {
+ new_st = surface->getSurfaceTexture();
+ new_st->incStrong(thiz);
+ } else {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "The surface has been released");
+ return;
+ }
}
env->SetIntField(thiz, fields.surface_texture, (int)new_st.get());
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 4f183f5..1e1de04 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -279,6 +279,8 @@
void NuCachedSource2::fetchInternal() {
LOGV("fetchInternal");
+ bool reconnect = false;
+
{
Mutex::Autolock autoLock(mLock);
CHECK(mFinalStatus == OK || mNumRetriesLeft > 0);
@@ -286,18 +288,24 @@
if (mFinalStatus != OK) {
--mNumRetriesLeft;
- status_t err =
- mSource->reconnectAtOffset(mCacheOffset + mCache->totalSize());
+ reconnect = true;
+ }
+ }
- if (err == ERROR_UNSUPPORTED) {
- mNumRetriesLeft = 0;
- return;
- } else if (err != OK) {
- LOGI("The attempt to reconnect failed, %d retries remaining",
- mNumRetriesLeft);
+ if (reconnect) {
+ status_t err =
+ mSource->reconnectAtOffset(mCacheOffset + mCache->totalSize());
- return;
- }
+ Mutex::Autolock autoLock(mLock);
+
+ if (err == ERROR_UNSUPPORTED) {
+ mNumRetriesLeft = 0;
+ return;
+ } else if (err != OK) {
+ LOGI("The attempt to reconnect failed, %d retries remaining",
+ mNumRetriesLeft);
+
+ return;
}
}
diff --git a/packages/SettingsProvider/res/drawable-hdpi/ic_launcher_settings.png b/packages/SettingsProvider/res/drawable-hdpi/ic_launcher_settings.png
index ff34a7f..8a5a2f7 100644
--- a/packages/SettingsProvider/res/drawable-hdpi/ic_launcher_settings.png
+++ b/packages/SettingsProvider/res/drawable-hdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SettingsProvider/res/drawable-mdpi/ic_launcher_settings.png b/packages/SettingsProvider/res/drawable-mdpi/ic_launcher_settings.png
index b08ad3b..803439f 100644
--- a/packages/SettingsProvider/res/drawable-mdpi/ic_launcher_settings.png
+++ b/packages/SettingsProvider/res/drawable-mdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SettingsProvider/res/drawable-xhdpi/ic_launcher_settings.png b/packages/SettingsProvider/res/drawable-xhdpi/ic_launcher_settings.png
new file mode 100644
index 0000000..ec3c8ea
--- /dev/null
+++ b/packages/SettingsProvider/res/drawable-xhdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_callout_line.9.png b/packages/SystemUI/res/drawable-hdpi/recents_callout_line.9.png
deleted file mode 100644
index 335d5a8..0000000
--- a/packages/SystemUI/res/drawable-hdpi/recents_callout_line.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_normal.9.png b/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_normal.9.png
new file mode 100644
index 0000000..d000f7e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_callout_line.9.png b/packages/SystemUI/res/drawable-mdpi/recents_callout_line.9.png
deleted file mode 100644
index 724a5cd..0000000
--- a/packages/SystemUI/res/drawable-mdpi/recents_callout_line.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_normal.9.png b/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_normal.9.png
new file mode 100644
index 0000000..f19dc93
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/recents_callout_line.9.png b/packages/SystemUI/res/drawable-xhdpi/recents_callout_line.9.png
deleted file mode 100644
index 1bd018a..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/recents_callout_line.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_normal.9.png b/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_normal.9.png
new file mode 100644
index 0000000..80fc849
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
index 58355bd..83c4faf 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
@@ -26,16 +26,17 @@
android:paddingRight="@dimen/status_bar_recents_item_padding">
<RelativeLayout android:id="@+id/recent_item"
- android:layout_gravity="bottom"
+ android:layout_gravity="center_vertical"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:paddingBottom="@*android:dimen/status_bar_height">
+ android:paddingTop="@*android:dimen/status_bar_height">
<FrameLayout android:id="@+id/app_thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
+ android:layout_marginTop="@dimen/status_bar_recents_thumbnail_top_margin"
android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
android:background="@drawable/recents_thumbnail_bg"
android:foreground="@drawable/recents_thumbnail_fg">
@@ -44,19 +45,22 @@
android:layout_height="@dimen/status_bar_recents_thumbnail_height"
android:visibility="invisible"
/>
-
- <ImageView android:id="@+id/app_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/status_bar_recents_app_icon_top_margin"
- android:layout_marginLeft="@dimen/status_bar_recents_app_icon_left_margin"
- android:maxWidth="@dimen/status_bar_recents_app_icon_max_width"
- android:maxHeight="@dimen/status_bar_recents_app_icon_max_height"
- android:adjustViewBounds="true"
- android:visibility="invisible"
- />
</FrameLayout>
+ <ImageView android:id="@+id/app_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/status_bar_recents_app_icon_top_margin"
+ android:layout_marginLeft="@dimen/status_bar_recents_app_icon_left_margin"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:maxWidth="@dimen/status_bar_recents_app_icon_max_width"
+ android:maxHeight="@dimen/status_bar_recents_app_icon_max_height"
+ android:scaleType="centerInside"
+ android:adjustViewBounds="true"
+ android:visibility="invisible"
+ />
+
<TextView android:id="@+id/app_label"
android:layout_width="@dimen/status_bar_recents_app_label_width"
android:layout_height="wrap_content"
@@ -67,6 +71,7 @@
android:layout_alignLeft="@id/app_thumbnail"
android:layout_below="@id/app_thumbnail"
android:layout_marginTop="@dimen/status_bar_recents_text_description_padding"
+ android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin"
android:singleLine="true"
android:ellipsize="marquee"
android:visibility="invisible"
diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
index 8c82eb1..3d8b9d6 100644
--- a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
@@ -26,32 +26,10 @@
android:paddingBottom="@dimen/status_bar_recents_item_padding">
<RelativeLayout android:id="@+id/recent_item"
+ android:layout_gravity="center_horizontal"
android:layout_height="wrap_content"
- android:layout_width="match_parent">
+ android:layout_width="wrap_content">
- <FrameLayout android:id="@+id/app_thumbnail"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
- android:background="@drawable/recents_thumbnail_bg"
- android:foreground="@drawable/recents_thumbnail_fg">
- <ImageView android:id="@+id/app_thumbnail_image"
- android:layout_width="@dimen/status_bar_recents_thumbnail_width"
- android:layout_height="@dimen/status_bar_recents_thumbnail_height"
- android:visibility="invisible"
- />
- <ImageView android:id="@+id/app_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/status_bar_recents_app_icon_left_margin"
- android:layout_marginTop="@dimen/status_bar_recents_app_icon_top_margin"
- android:maxWidth="@dimen/status_bar_recents_app_icon_max_width"
- android:maxHeight="@dimen/status_bar_recents_app_icon_max_height"
- android:adjustViewBounds="true"
- />
- </FrameLayout>
<TextView android:id="@+id/app_label"
android:layout_width="@dimen/status_bar_recents_app_label_width"
android:layout_height="wrap_content"
@@ -61,12 +39,26 @@
android:scrollHorizontally="true"
android:layout_alignParentLeft="true"
android:layout_alignTop="@id/app_icon"
+ android:paddingTop="2dp"
android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin"
android:singleLine="true"
android:ellipsize="marquee"
android:textColor="@color/status_bar_recents_app_label_color"
/>
-
+ <FrameLayout android:id="@+id/app_thumbnail"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_toRightOf="@id/app_label"
+ android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
+ android:background="@drawable/recents_thumbnail_bg"
+ android:foreground="@drawable/recents_thumbnail_fg">
+ <ImageView android:id="@+id/app_thumbnail_image"
+ android:layout_width="@dimen/status_bar_recents_thumbnail_width"
+ android:layout_height="@dimen/status_bar_recents_thumbnail_height"
+ android:visibility="invisible"
+ />
+ </FrameLayout>
<View android:id="@+id/recents_callout_line"
android:layout_width="@dimen/status_bar_recents_app_label_width"
android:layout_height="1dip"
@@ -79,6 +71,18 @@
android:background="@drawable/recents_callout_line"
/>
+ <ImageView android:id="@+id/app_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toRightOf="@id/app_label"
+ android:layout_marginLeft="@dimen/status_bar_recents_app_icon_left_margin"
+ android:layout_marginTop="@dimen/status_bar_recents_app_icon_top_margin"
+ android:maxWidth="@dimen/status_bar_recents_app_icon_max_width"
+ android:maxHeight="@dimen/status_bar_recents_app_icon_max_height"
+ android:scaleType="centerInside"
+ android:adjustViewBounds="true"
+ />
+
<TextView android:id="@+id/app_description"
android:layout_width="@dimen/status_bar_recents_app_label_width"
android:layout_height="wrap_content"
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_no_recent_apps.xml b/packages/SystemUI/res/layout/status_bar_no_recent_apps.xml
index 47ffb83..1675773 100644
--- a/packages/SystemUI/res/layout/status_bar_no_recent_apps.xml
+++ b/packages/SystemUI/res/layout/status_bar_no_recent_apps.xml
@@ -27,8 +27,8 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textSize="24dp"
- android:textColor="#ffffffff"
+ android:textSize="20dp"
+ android:textColor="@android:color/holo_blue_light"
android:text="@string/status_bar_no_recent_apps"
android:gravity="center_horizontal"
android:layout_gravity="center"
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index 32ebc80..e7c8b1f 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -23,15 +23,18 @@
<!-- How far the thumbnail for a recent app appears from left edge -->
<dimen name="status_bar_recents_thumbnail_left_margin">0dp</dimen>
<!-- How far the thumbnail for a recent app appears from top edge -->
- <dimen name="status_bar_recents_thumbnail_top_margin">12dp</dimen>
+ <dimen name="status_bar_recents_thumbnail_top_margin">28dp</dimen>
<!-- Padding for text descriptions -->
<dimen name="status_bar_recents_text_description_padding">8dp</dimen>
<!-- Width of application label text -->
<dimen name="status_bar_recents_app_label_width">156dip</dimen>
<!-- Left margin of application label text -->
- <dimen name="status_bar_recents_app_label_left_margin">16dip</dimen>
+ <dimen name="status_bar_recents_app_label_left_margin">12dip</dimen>
<!-- Margin between recents container and glow on the right -->
<dimen name="status_bar_recents_right_glow_margin">0dip</dimen>
<!-- Padding between recents items -->
<dimen name="status_bar_recents_item_padding">2dip</dimen>
+ <!-- Where to place the app icon over the thumbnail -->
+ <dimen name="status_bar_recents_app_icon_left_margin">8dp</dimen>
+ <dimen name="status_bar_recents_app_icon_top_margin">8dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-port/dimens.xml b/packages/SystemUI/res/values-port/dimens.xml
index 2bafd30..de7b836 100644
--- a/packages/SystemUI/res/values-port/dimens.xml
+++ b/packages/SystemUI/res/values-port/dimens.xml
@@ -18,15 +18,18 @@
<resources>
<!-- Recent Applications parameters -->
<!-- How far the thumbnail for a recent app appears from left edge -->
- <dimen name="status_bar_recents_thumbnail_left_margin">110dp</dimen>
+ <dimen name="status_bar_recents_thumbnail_left_margin">20dp</dimen>
<!-- Padding for text descriptions -->
<dimen name="status_bar_recents_text_description_padding">8dp</dimen>
<!-- Width of application label text -->
<dimen name="status_bar_recents_app_label_width">88dip</dimen>
<!-- Left margin of application label text -->
- <dimen name="status_bar_recents_app_label_left_margin">16dip</dimen>
+ <dimen name="status_bar_recents_app_label_left_margin">0dip</dimen>
<!-- Margin between recents container and glow on the right -->
<dimen name="status_bar_recents_right_glow_margin">100dip</dimen>
<!-- Padding between recents items -->
<dimen name="status_bar_recents_item_padding">0dip</dimen>
+ <!-- Where to place the app icon over the thumbnail -->
+ <dimen name="status_bar_recents_app_icon_left_margin">0dp</dimen>
+ <dimen name="status_bar_recents_app_icon_top_margin">8dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index c88d651..555baa2 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -29,4 +29,5 @@
<drawable name="notification_header_bg">#d8000000</drawable>
<drawable name="notification_tracking_bg">#d8000000</drawable>
<color name="notification_list_shadow_top">#80000000</color>
+ <drawable name="recents_callout_line">#66ffffff</drawable>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 830506c..bbc66cf 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -21,21 +21,18 @@
<!-- Recent Applications parameters -->
<!-- Upper width limit for application icon -->
- <dimen name="status_bar_recents_app_icon_max_width">64dp</dimen>
+ <dimen name="status_bar_recents_app_icon_max_width">48dp</dimen>
<!-- Upper height limit for application icon -->
- <dimen name="status_bar_recents_app_icon_max_height">64dp</dimen>
- <!-- Where to place the app icon over the thumbnail -->
- <dimen name="status_bar_recents_app_icon_left_margin">13dp</dimen>
- <dimen name="status_bar_recents_app_icon_top_margin">13dp</dimen>
+ <dimen name="status_bar_recents_app_icon_max_height">48dp</dimen>
<!-- Size of application thumbnail -->
<dimen name="status_bar_recents_thumbnail_width">164dp</dimen>
<dimen name="status_bar_recents_thumbnail_height">145dp</dimen>
<!-- Size of application label text -->
- <dimen name="status_bar_recents_app_label_text_size">16dip</dimen>
+ <dimen name="status_bar_recents_app_label_text_size">14dip</dimen>
<!-- Size of application description text -->
- <dimen name="status_bar_recents_app_description_text_size">16dip</dimen>
+ <dimen name="status_bar_recents_app_description_text_size">14dip</dimen>
<!-- Size of fading edge for scroll effect -->
<dimen name="status_bar_recents_fading_edge_length">20dip</dimen>
<!-- Margin between recents container and glow on the right -->
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/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/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/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index 2d8185b..008f5d8 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -524,6 +524,7 @@
callback.onRingerModeChanged(mRingMode);
callback.onPhoneStateChanged(mPhoneState);
callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
+ callback.onClockVisibilityChanged();
} else {
if (DEBUG) Log.e(TAG, "Object tried to add another INFO callback",
new Exception("Whoops"));
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
index 2fd165a..0499cfa 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
@@ -178,7 +178,6 @@
int visFlags =
( View.STATUS_BAR_DISABLE_BACK
| View.STATUS_BAR_DISABLE_HOME
- | View.STATUS_BAR_DISABLE_CLOCK
);
mKeyguardHost.setSystemUiVisibility(visFlags);
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 25355db..96998af 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -130,6 +130,10 @@
// 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.
*/
@@ -439,6 +443,7 @@
}
public void reportSuccessfulUnlockAttempt() {
+ mFailedFaceUnlockAttempts = 0;
mLockPatternUtils.reportSuccessfulPasswordAttempt();
}
};
@@ -553,7 +558,16 @@
* FaceLock, but only if we're not dealing with a call
*/
private void activateFaceLockIfAble() {
- if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE && !mHasOverlay) {
+ 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
+ && !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
@@ -695,8 +709,14 @@
public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {}
@Override
public void onRingerModeChanged(int state) {}
+
@Override
- public void onClockVisibilityChanged() {}
+ public void onClockVisibilityChanged() {
+ int visFlags = getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_CLOCK;
+ setSystemUiVisibility(visFlags
+ | (mUpdateMonitor.isClockVisible() ? View.STATUS_BAR_DISABLE_CLOCK : 0));
+ }
+
@Override
public void onDeviceProvisioned() {}
@@ -768,6 +788,15 @@
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() {
@@ -1192,6 +1221,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;
@@ -1296,7 +1332,7 @@
}
// 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()");
@@ -1305,6 +1341,17 @@
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
@Override
public void pokeWakelock() {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index aac3209..8b09e00 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/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index f306e4a..171710a 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -97,6 +97,16 @@
setCameraFree(i);
}
}
+
+ // Read the system property to determine if we have to use the
+ // AUDIO_STREAM_ENFORCED_AUDIBLE type.
+ char value[PROPERTY_VALUE_MAX];
+ property_get("ro.camera.sound.forced", value, "0");
+ if (strcmp(value, "0") != 0) {
+ mAudioStreamType = AUDIO_STREAM_ENFORCED_AUDIBLE;
+ } else {
+ mAudioStreamType = AUDIO_STREAM_MUSIC;
+ }
}
CameraService::~CameraService() {
@@ -282,21 +292,10 @@
// A reference count is kept to determine when we will actually release the
// media players.
-static MediaPlayer* newMediaPlayer(const char *file) {
- // Read the system property to determine if we have need to use the
- // AUDIO_STREAM_ENFORCED_AUDIBLE type.
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.camera.sound.forced", value, "0");
- int audioStreamType;
- if (strcmp(value, "0") != 0) {
- audioStreamType = AUDIO_STREAM_ENFORCED_AUDIBLE;
- } else {
- audioStreamType = AUDIO_STREAM_MUSIC;
- }
-
+MediaPlayer* CameraService::newMediaPlayer(const char *file) {
MediaPlayer* mp = new MediaPlayer();
if (mp->setDataSource(file, NULL) == NO_ERROR) {
- mp->setAudioStreamType(audioStreamType);
+ mp->setAudioStreamType(mAudioStreamType);
mp->prepare();
} else {
LOGE("Failed to load CameraService sounds: %s", file);
@@ -335,7 +334,7 @@
// do not play the sound if stream volume is 0
// (typically because ringer mode is silent).
int index;
- AudioSystem::getStreamVolumeIndex(AUDIO_STREAM_ENFORCED_AUDIBLE, &index);
+ AudioSystem::getStreamVolumeIndex(mAudioStreamType, &index);
if (index != 0) {
player->seekTo(0);
player->start();
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 57abf83..cdfbc56 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -76,6 +76,9 @@
void setCameraFree(int cameraId);
// sounds
+ audio_stream_type_t mAudioStreamType;
+ MediaPlayer* newMediaPlayer(const char *file);
+
Mutex mSoundLock;
sp<MediaPlayer> mSoundPlayer[NUM_SOUNDS];
int mSoundRef; // reference count (release all MediaPlayer when 0)
diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/java/com/android/server/NativeDaemonConnector.java
index 43d938c..28013bd 100644
--- a/services/java/com/android/server/NativeDaemonConnector.java
+++ b/services/java/com/android/server/NativeDaemonConnector.java
@@ -207,6 +207,13 @@
*/
private void sendCommandLocked(String command, String argument)
throws NativeDaemonConnectorException {
+ if (command != null && command.indexOf('\0') >= 0) {
+ throw new IllegalArgumentException("unexpected command: " + command);
+ }
+ if (argument != null && argument.indexOf('\0') >= 0) {
+ throw new IllegalArgumentException("unexpected argument: " + argument);
+ }
+
if (LOCAL_LOGD) Slog.d(TAG, String.format("SND -> {%s} {%s}", command, argument));
if (mOutputStream == null) {
Slog.e(TAG, "No connection to daemon", new IllegalStateException());
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index b05705e..fb13b75 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -16,6 +16,8 @@
package com.android.server;
+import static android.Manifest.permission.ACCESS_NETWORK_STATE;
+import static android.Manifest.permission.CHANGE_NETWORK_STATE;
import static android.Manifest.permission.DUMP;
import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
import static android.net.NetworkStats.SET_DEFAULT;
@@ -350,6 +352,7 @@
}
public InterfaceConfiguration getInterfaceConfig(String iface) throws IllegalStateException {
+ mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
String rsp;
try {
rsp = mConnector.doCommand("interface getcfg " + iface).get(0);
@@ -404,6 +407,7 @@
public void setInterfaceConfig(
String iface, InterfaceConfiguration cfg) throws IllegalStateException {
+ mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
LinkAddress linkAddr = cfg.addr;
if (linkAddr == null || linkAddr.getAddress() == null) {
throw new IllegalStateException("Null LinkAddress given");
@@ -421,6 +425,7 @@
}
public void setInterfaceDown(String iface) throws IllegalStateException {
+ mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
try {
InterfaceConfiguration ifcg = getInterfaceConfig(iface);
ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down");
@@ -432,6 +437,7 @@
}
public void setInterfaceUp(String iface) throws IllegalStateException {
+ mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
try {
InterfaceConfiguration ifcg = getInterfaceConfig(iface);
ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
@@ -444,6 +450,7 @@
public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable)
throws IllegalStateException {
+ mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
String cmd = String.format("interface ipv6privacyextensions %s %s", iface,
enable ? "enable" : "disable");
try {
@@ -459,7 +466,8 @@
/* TODO: This is right now a IPv4 only function. Works for wifi which loses its
IPv6 addresses on interface down, but we need to do full clean up here */
public void clearInterfaceAddresses(String iface) throws IllegalStateException {
- String cmd = String.format("interface clearaddrs %s", iface);
+ mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
+ String cmd = String.format("interface clearaddrs %s", iface);
try {
mConnector.doCommand(cmd);
} catch (NativeDaemonConnectorException e) {
@@ -491,10 +499,12 @@
}
public void addRoute(String interfaceName, RouteInfo route) {
+ mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
modifyRoute(interfaceName, ADD, route);
}
public void removeRoute(String interfaceName, RouteInfo route) {
+ mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
modifyRoute(interfaceName, REMOVE, route);
}
@@ -578,6 +588,7 @@
}
public RouteInfo[] getRoutes(String interfaceName) {
+ mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>();
// v4 routes listed as:
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/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/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index ae152fb..759a84b 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -254,9 +254,6 @@
/** CID of active data connection */
protected int mCidActive;
- /** indication of our availability (preconditions to trysetupData are met) **/
- protected boolean mAvailability = false;
-
// When false we will not auto attach and manually attaching is required.
protected boolean mAutoAttachOnCreation = false;
@@ -755,7 +752,7 @@
mPhone.notifyDataConnection(reason, apnIdToType(id));
}
}
- notifyDataAvailability(reason);
+ notifyOffApnsOfAvailability(reason);
}
// a new APN has gone active and needs to send events to catch up with the
@@ -783,15 +780,8 @@
}
// disabled apn's still need avail/unavail notificiations - send them out
- protected void notifyOffApnsOfAvailability(String reason, boolean availability) {
- if (mAvailability == availability) {
- if (DBG) {
- log("notifyOffApnsOfAvailability: no change in availability, " +
- "not nofitying about reason='" + reason + "' availability=" + availability);
- }
- return;
- }
- mAvailability = availability;
+ protected void notifyOffApnsOfAvailability(String reason) {
+ if (DBG) log("notifyOffApnsOfAvailability - reason= " + reason);
for (int id = 0; id < APN_NUM_TYPES; id++) {
if (!isApnIdEnabled(id)) {
notifyApnIdDisconnected(reason, id);
@@ -799,13 +789,6 @@
}
}
- // we had an availability change - tell the listeners
- protected void notifyDataAvailability(String reason) {
- // note that we either just turned all off because we lost availability
- // or all were off and could now go on, so only have off apns to worry about
- notifyOffApnsOfAvailability(reason, isDataPossible(Phone.APN_TYPE_DEFAULT));
- }
-
public boolean isApnTypeEnabled(String apnType) {
if (apnType == null) {
return false;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index 4dace82..3c7ff05 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -237,7 +237,7 @@
// FIXME this can be improved
setState(State.CONNECTED);
notifyDataConnection(reason);
- notifyOffApnsOfAvailability(reason, true);
+ notifyOffApnsOfAvailability(reason);
log("(fix?) We're on the simulator; assuming data is connected");
return true;
@@ -250,10 +250,10 @@
if ((mState == State.IDLE || mState == State.SCANNING) &&
isDataAllowed() && getAnyDataEnabled()) {
boolean retValue = setupData(reason);
- notifyOffApnsOfAvailability(reason, retValue);
+ notifyOffApnsOfAvailability(reason);
return retValue;
} else {
- notifyOffApnsOfAvailability(reason, false);
+ notifyOffApnsOfAvailability(reason);
return false;
}
}
@@ -276,7 +276,7 @@
}
setState(State.DISCONNECTING);
- notifyDataAvailability(reason);
+ notifyOffApnsOfAvailability(reason);
boolean notificationDeferred = false;
for (DataConnection conn : mDataConnections.values()) {
@@ -536,7 +536,7 @@
private void notifyNoData(FailCause lastFailCauseCode) {
setState(State.FAILED);
- notifyDataAvailability(null);
+ notifyOffApnsOfAvailability(null);
}
protected void gotoIdleAndNotifyDataConnection(String reason) {
@@ -583,7 +583,7 @@
@Override
protected void onRoamingOff() {
if (getDataOnRoamingEnabled() == false) {
- notifyDataAvailability(Phone.REASON_ROAMING_OFF);
+ notifyOffApnsOfAvailability(Phone.REASON_ROAMING_OFF);
trySetupData(Phone.REASON_ROAMING_OFF);
} else {
notifyDataConnection(Phone.REASON_ROAMING_OFF);
@@ -601,7 +601,7 @@
} else {
if (DBG) log("Tear down data connection on roaming.");
cleanUpAllConnections(null);
- notifyDataAvailability(Phone.REASON_ROAMING_ON);
+ notifyOffApnsOfAvailability(Phone.REASON_ROAMING_ON);
}
}
@@ -619,7 +619,7 @@
log("We're on the simulator; assuming data is connected");
}
- notifyDataAvailability(null);
+ notifyOffApnsOfAvailability(null);
if (mState != State.IDLE) {
cleanUpAllConnections(null);
@@ -710,7 +710,7 @@
if (mState == State.CONNECTED && !mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed()) {
stopNetStatPoll();
notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
- notifyDataAvailability(Phone.REASON_VOICE_CALL_STARTED);
+ notifyOffApnsOfAvailability(Phone.REASON_VOICE_CALL_STARTED);
}
}
@@ -727,7 +727,7 @@
// clean slate after call end.
resetPollStats();
}
- notifyDataAvailability(Phone.REASON_VOICE_CALL_ENDED);
+ notifyOffApnsOfAvailability(Phone.REASON_VOICE_CALL_ENDED);
} else {
mDataConnections.get(0).resetRetryCount();
// in case data setup was attempted when we were on a voice call
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 78ba7dd..5497b7f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -556,7 +556,7 @@
notifyDataConnection(Phone.REASON_DATA_ATTACHED);
} else {
// update APN availability so that APN can be enabled.
- notifyDataAvailability(Phone.REASON_DATA_ATTACHED);
+ notifyOffApnsOfAvailability(Phone.REASON_DATA_ATTACHED);
}
setupDataOnReadyApns(Phone.REASON_DATA_ATTACHED);
@@ -693,7 +693,7 @@
if (waitingApns.isEmpty()) {
if (DBG) log("trySetupData: No APN found");
notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN, apnContext);
- notifyOffApnsOfAvailability(apnContext.getReason(), false);
+ notifyOffApnsOfAvailability(apnContext.getReason());
return false;
} else {
apnContext.setWaitingApns(waitingApns);
@@ -708,7 +708,7 @@
}
// apnContext.setReason(apnContext.getReason());
boolean retValue = setupData(apnContext);
- notifyOffApnsOfAvailability(apnContext.getReason(), retValue);
+ notifyOffApnsOfAvailability(apnContext.getReason());
return retValue;
} else {
// TODO: check the condition.
@@ -716,23 +716,25 @@
&& (apnContext.getState() == State.IDLE
|| apnContext.getState() == State.SCANNING))
mPhone.notifyDataConnectionFailed(apnContext.getReason(), apnContext.getApnType());
- notifyOffApnsOfAvailability(apnContext.getReason(), false);
+ notifyOffApnsOfAvailability(apnContext.getReason());
return false;
}
}
@Override
// Disabled apn's still need avail/unavail notificiations - send them out
- protected void notifyOffApnsOfAvailability(String reason, boolean availability) {
- if (mAvailability == availability) return;
- mAvailability = availability;
-
+ protected void notifyOffApnsOfAvailability(String reason) {
for (ApnContext apnContext : mApnContexts.values()) {
if (!apnContext.isReady()) {
if (DBG) log("notifyOffApnOfAvailability type:" + apnContext.getApnType());
mPhone.notifyDataConnection(reason != null ? reason : apnContext.getReason(),
apnContext.getApnType(),
Phone.DataState.DISCONNECTED);
+ } else {
+ if (DBG) {
+ log("notifyOffApnsOfAvailability skipped apn due to isReady==false: " +
+ apnContext.toString());
+ }
}
}
}
@@ -1572,7 +1574,7 @@
createAllApnList();
if (mPhone.mCM.getRadioState().isOn()) {
if (DBG) log("onRecordsLoaded: notifying data availability");
- notifyDataAvailability(Phone.REASON_SIM_LOADED);
+ notifyOffApnsOfAvailability(Phone.REASON_SIM_LOADED);
}
setupDataOnReadyApns(Phone.REASON_SIM_LOADED);
}
@@ -1681,7 +1683,7 @@
if (DBG) log("onRoamingOff");
if (getDataOnRoamingEnabled() == false) {
- notifyDataAvailability(Phone.REASON_ROAMING_OFF);
+ notifyOffApnsOfAvailability(Phone.REASON_ROAMING_OFF);
setupDataOnReadyApns(Phone.REASON_ROAMING_OFF);
} else {
notifyDataConnection(Phone.REASON_ROAMING_OFF);
@@ -1697,7 +1699,7 @@
} else {
if (DBG) log("onRoamingOn: Tear down data connection on roaming.");
cleanUpAllConnections(true, Phone.REASON_ROAMING_ON);
- notifyDataAvailability(Phone.REASON_ROAMING_ON);
+ notifyOffApnsOfAvailability(Phone.REASON_ROAMING_ON);
}
}
@@ -1714,7 +1716,7 @@
}
if (mPhone.mIccRecords.getRecordsLoaded()) {
- notifyDataAvailability(null);
+ notifyOffApnsOfAvailability(null);
}
if (getOverallState() != State.IDLE) {
@@ -1740,7 +1742,7 @@
if (DBG) log("onRadioOffOrNotAvailable: is off and clean up all connections");
cleanUpAllConnections(false, Phone.REASON_RADIO_TURNED_OFF);
}
- notifyDataAvailability(null);
+ notifyOffApnsOfAvailability(null);
}
@Override
@@ -1985,7 +1987,7 @@
apnContext.getApnType());
}
}
- notifyDataAvailability(reason);
+ notifyOffApnsOfAvailability(reason);
}
/**
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
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 55e9587..b76f8b9 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -2698,6 +2698,19 @@
handleNetworkDisconnect();
}
transitionTo(mDriverStoppedState);
+ break;
+ }
+
+ // Supplicant can fail to report a NETWORK_DISCONNECTION_EVENT
+ // when authentication times out after a successful connection,
+ // we can figure this from the supplicant state. If supplicant
+ // state is DISCONNECTED, but the mNetworkInfo says we are not
+ // disconnected, we need to handle a disconnection
+ if (state == SupplicantState.DISCONNECTED &&
+ mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) {
+ if (DBG) log("Missed CTRL-EVENT-DISCONNECTED, disconnect");
+ handleNetworkDisconnect();
+ transitionTo(mDisconnectedState);
}
break;
/* Do a redundant disconnect without transition */