Merge "Show the keyguard if unsecure window on top" into klp-modular-dev
diff --git a/api/current.txt b/api/current.txt
index 1c24e01..e0b4999 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2850,6 +2850,7 @@
method public void onUserInteraction();
method protected void onUserLeaveHint();
method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
+ method public void onWindowDismissed();
method public void onWindowFocusChanged(boolean);
method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
method public void openContextMenu(android.view.View);
@@ -3366,6 +3367,7 @@
method public boolean onTouchEvent(android.view.MotionEvent);
method public boolean onTrackballEvent(android.view.MotionEvent);
method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
+ method public void onWindowDismissed();
method public void onWindowFocusChanged(boolean);
method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
method public void openContextMenu(android.view.View);
@@ -4008,7 +4010,9 @@
public static class Notification.Builder {
ctor public Notification.Builder(android.content.Context);
method public android.app.Notification.Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent);
+ method public android.app.Notification.Builder addExtras(android.os.Bundle);
method public android.app.Notification build();
+ method public android.os.Bundle getExtras();
method public deprecated android.app.Notification getNotification();
method public android.app.Notification.Builder setAutoCancel(boolean);
method public android.app.Notification.Builder setContent(android.widget.RemoteViews);
@@ -22701,6 +22705,7 @@
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
method public boolean onSearchRequested();
method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
+ method public void onWindowDismissed();
method public void onWindowFocusChanged(boolean);
method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
method public void setContentView(int);
@@ -28648,6 +28653,7 @@
field public static final int FEATURE_OPTIONS_PANEL = 0; // 0x0
field public static final int FEATURE_PROGRESS = 2; // 0x2
field public static final int FEATURE_RIGHT_ICON = 4; // 0x4
+ field public static final int FEATURE_SWIPE_TO_DISMISS = 11; // 0xb
field public static final int ID_ANDROID_CONTENT = 16908290; // 0x1020002
field public static final int PROGRESS_END = 10000; // 0x2710
field public static final int PROGRESS_INDETERMINATE_OFF = -4; // 0xfffffffc
@@ -28679,6 +28685,7 @@
method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
method public abstract boolean onSearchRequested();
method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
+ method public abstract void onWindowDismissed();
method public abstract void onWindowFocusChanged(boolean);
method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d6db8c2..ec58fb0 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2402,6 +2402,13 @@
}
return false;
}
+
+ /**
+ * Called when the main window associated with the activity has been dismissed.
+ */
+ public void onWindowDismissed() {
+ finish();
+ }
/**
* Called to process key events. You can override this to intercept all
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index cda2c5f..a8277b5 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -695,6 +695,10 @@
public void onDetachedFromWindow() {
}
+
+ public void onWindowDismissed() {
+ dismiss();
+ }
/**
* Called to process key events. You can override this to intercept all
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 1e96ebf..dd2dc01 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1586,12 +1586,31 @@
}
/**
- * Add metadata to this notification.
+ * Merge additional metadata into this notification.
*
- * A reference to the Bundle is held for the lifetime of this Builder, and the Bundle's
+ * <p>Values within the Bundle will replace existing extras values in this Builder.
+ *
+ * @see Notification#extras
+ */
+ public Builder addExtras(Bundle bag) {
+ if (mExtras == null) {
+ mExtras = new Bundle(bag);
+ } else {
+ mExtras.putAll(bag);
+ }
+ return this;
+ }
+
+ /**
+ * Set metadata for this notification.
+ *
+ * <p>A reference to the Bundle is held for the lifetime of this Builder, and the Bundle's
* current contents are copied into the Notification each time {@link #build()} is
* called.
*
+ * <p>Replaces any existing extras values with those from the provided Bundle.
+ * Use {@link #addExtras} to merge in metadata instead.
+ *
* @see Notification#extras
*/
public Builder setExtras(Bundle bag) {
@@ -1600,6 +1619,23 @@
}
/**
+ * Get the current metadata Bundle used by this notification Builder.
+ *
+ * <p>The returned Bundle is shared with this Builder.
+ *
+ * <p>The current contents of this Bundle are copied into the Notification each time
+ * {@link #build()} is called.
+ *
+ * @see Notification#extras
+ */
+ public Bundle getExtras() {
+ if (mExtras == null) {
+ mExtras = new Bundle();
+ }
+ return mExtras;
+ }
+
+ /**
* Add an action to this notification. Actions are typically displayed by
* the system as a button adjacent to the notification content.
* <p>
@@ -1857,7 +1893,7 @@
* this Notification object.
* @hide
*/
- public void addExtras(Bundle extras) {
+ public void populateExtras(Bundle extras) {
// Store original information used in the construction of this object
extras.putCharSequence(EXTRA_TITLE, mContentTitle);
extras.putCharSequence(EXTRA_TEXT, mContentText);
@@ -1895,7 +1931,7 @@
n.extras = mExtras != null ? new Bundle(mExtras) : new Bundle();
- addExtras(n.extras);
+ populateExtras(n.extras);
if (mStyle != null) {
mStyle.addExtras(n.extras);
}
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b16df28..0863368 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -18,6 +18,7 @@
import android.accounts.Account;
import android.app.Activity;
+import android.content.ActivityNotFoundException;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
@@ -40,6 +41,7 @@
import android.util.DisplayMetrics;
import android.util.Pair;
import android.view.View;
+import android.widget.Toast;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -7981,7 +7983,7 @@
// Trigger with obtained rectangle
Intent intent = composeQuickContactsIntent(context, target, lookupUri, mode,
excludeMimes);
- context.startActivity(intent);
+ startActivityWithErrorToast(context, intent);
}
/**
@@ -8014,7 +8016,16 @@
String[] excludeMimes) {
Intent intent = composeQuickContactsIntent(context, target, lookupUri, mode,
excludeMimes);
- context.startActivity(intent);
+ startActivityWithErrorToast(context, intent);
+ }
+
+ private static void startActivityWithErrorToast(Context context, Intent intent) {
+ try {
+ context.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(context, com.android.internal.R.string.quick_contacts_not_available,
+ Toast.LENGTH_SHORT).show();
+ }
}
}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 1abb1d7..7647c22 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -300,6 +300,10 @@
public void onDetachedFromWindow() {
}
+ @Override
+ public void onWindowDismissed() {
+ }
+
/** {@inheritDoc} */
@Override
public void onPanelClosed(int featureId, Menu menu) {
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 9414237..5763e72 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -463,13 +463,13 @@
public ViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
initViewGroup();
- initFromAttributes(context, attrs);
+ initFromAttributes(context, attrs, 0);
}
public ViewGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initViewGroup();
- initFromAttributes(context, attrs);
+ initFromAttributes(context, attrs, defStyle);
}
private boolean debugDraw() {
@@ -499,9 +499,8 @@
mPersistentDrawingCache = PERSISTENT_SCROLLING_CACHE;
}
- private void initFromAttributes(Context context, AttributeSet attrs) {
- TypedArray a = context.obtainStyledAttributes(attrs,
- R.styleable.ViewGroup);
+ private void initFromAttributes(Context context, AttributeSet attrs, int defStyle) {
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ViewGroup, defStyle, 0);
final int N = a.getIndexCount();
for (int i = 0; i < N; i++) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index bc0d7e3..d779628 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -232,8 +232,6 @@
InputStage mFirstInputStage;
InputStage mFirstPostImeInputStage;
- boolean mFlipControllerFallbackKeys;
-
boolean mWindowAttributesChanged = false;
int mWindowAttributesChangesFlag = 0;
@@ -370,8 +368,6 @@
mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
mFallbackEventHandler = PolicyManager.makeNewFallbackEventHandler(context);
mChoreographer = Choreographer.getInstance();
- mFlipControllerFallbackKeys =
- context.getResources().getBoolean(R.bool.flip_controller_fallback_keys);
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mAttachInfo.mScreenOn = powerManager.isScreenOn();
@@ -2912,11 +2908,8 @@
mView.dispatchConfigurationChanged(config);
}
}
-
- mFlipControllerFallbackKeys =
- mContext.getResources().getBoolean(R.bool.flip_controller_fallback_keys);
}
-
+
/**
* Return true if child is an ancestor of parent, (or equal to the parent).
*/
@@ -3985,7 +3978,6 @@
private final SyntheticJoystickHandler mJoystick = new SyntheticJoystickHandler();
private final SyntheticTouchNavigationHandler mTouchNavigation =
new SyntheticTouchNavigationHandler();
- private final SyntheticKeyHandler mKeys = new SyntheticKeyHandler();
public SyntheticInputStage() {
super(null);
@@ -4008,12 +4000,7 @@
mTouchNavigation.process(event);
return FINISH_HANDLED;
}
- } else if (q.mEvent instanceof KeyEvent) {
- if (mKeys.process((KeyEvent) q.mEvent)) {
- return FINISH_HANDLED;
- }
}
-
return FORWARD;
}
@@ -4843,63 +4830,6 @@
};
}
- final class SyntheticKeyHandler {
-
- public boolean process(KeyEvent event) {
- // In some locales (like Japan) controllers use B for confirm and A for back, rather
- // than vice versa, so we need to special case this here since the input system itself
- // is not locale-aware.
- int keyCode;
- switch(event.getKeyCode()) {
- case KeyEvent.KEYCODE_BUTTON_A:
- case KeyEvent.KEYCODE_BUTTON_C:
- case KeyEvent.KEYCODE_BUTTON_X:
- case KeyEvent.KEYCODE_BUTTON_Z:
- keyCode = mFlipControllerFallbackKeys ?
- KeyEvent.KEYCODE_BACK : KeyEvent.KEYCODE_DPAD_CENTER;
- break;
- case KeyEvent.KEYCODE_BUTTON_B:
- case KeyEvent.KEYCODE_BUTTON_Y:
- keyCode = mFlipControllerFallbackKeys ?
- KeyEvent.KEYCODE_DPAD_CENTER : KeyEvent.KEYCODE_BACK;
- break;
- case KeyEvent.KEYCODE_BUTTON_THUMBL:
- case KeyEvent.KEYCODE_BUTTON_THUMBR:
- case KeyEvent.KEYCODE_BUTTON_START:
- case KeyEvent.KEYCODE_BUTTON_1:
- case KeyEvent.KEYCODE_BUTTON_2:
- case KeyEvent.KEYCODE_BUTTON_3:
- case KeyEvent.KEYCODE_BUTTON_4:
- case KeyEvent.KEYCODE_BUTTON_5:
- case KeyEvent.KEYCODE_BUTTON_6:
- case KeyEvent.KEYCODE_BUTTON_7:
- case KeyEvent.KEYCODE_BUTTON_8:
- case KeyEvent.KEYCODE_BUTTON_9:
- case KeyEvent.KEYCODE_BUTTON_10:
- case KeyEvent.KEYCODE_BUTTON_11:
- case KeyEvent.KEYCODE_BUTTON_12:
- case KeyEvent.KEYCODE_BUTTON_13:
- case KeyEvent.KEYCODE_BUTTON_14:
- case KeyEvent.KEYCODE_BUTTON_15:
- case KeyEvent.KEYCODE_BUTTON_16:
- keyCode = KeyEvent.KEYCODE_DPAD_CENTER;
- break;
- case KeyEvent.KEYCODE_BUTTON_SELECT:
- case KeyEvent.KEYCODE_BUTTON_MODE:
- keyCode = KeyEvent.KEYCODE_MENU;
- default:
- return false;
- }
-
- enqueueInputEvent(new KeyEvent(event.getDownTime(), event.getEventTime(),
- event.getAction(), keyCode, event.getRepeatCount(), event.getMetaState(),
- event.getDeviceId(), event.getScanCode(),
- event.getFlags() | KeyEvent.FLAG_FALLBACK, event.getSource()));
- return true;
- }
-
- }
-
/**
* Returns true if the key is used for keyboard navigation.
* @param keyEvent The key event.
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index f0e6677..52f9c0b 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -311,7 +311,6 @@
lp.type = LayoutParams.TYPE_VOLUME_OVERLAY;
lp.width = LayoutParams.WRAP_CONTENT;
lp.height = LayoutParams.WRAP_CONTENT;
- lp.privateFlags |= LayoutParams.PRIVATE_FLAG_FORCE_SHOW_NAV_BAR;
window.setAttributes(lp);
window.addFlags(LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index b3a0699..c450f3c 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -91,10 +91,15 @@
public static final int FEATURE_ACTION_MODE_OVERLAY = 10;
/**
+ * Flag for requesting a decoration-free window that is dismissed by swiping from the left.
+ */
+ public static final int FEATURE_SWIPE_TO_DISMISS = 11;
+
+ /**
* Max value used as a feature ID
* @hide
*/
- public static final int FEATURE_MAX = FEATURE_ACTION_MODE_OVERLAY;
+ public static final int FEATURE_MAX = FEATURE_SWIPE_TO_DISMISS;
/** Flag for setting the progress bar's visibility to VISIBLE */
public static final int PROGRESS_VISIBILITY_ON = -1;
@@ -385,6 +390,12 @@
* @param mode The mode that was just finished.
*/
public void onActionModeFinished(ActionMode mode);
+
+ /**
+ * Called when a window is dismissed. This informs the callback that the
+ * window is gone, and it should finish itself.
+ */
+ public void onWindowDismissed();
}
public Window(Context context) {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 0ce4da5..53a4c0d0 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1063,13 +1063,6 @@
public static final int PRIVATE_FLAG_SHOW_FOR_ALL_USERS = 0x00000010;
/**
- * Special flag for the volume overlay: force the window manager out of "hide nav bar"
- * mode while the window is on screen.
- *
- * {@hide} */
- public static final int PRIVATE_FLAG_FORCE_SHOW_NAV_BAR = 0x00000020;
-
- /**
* Never animate position changes of the window.
*
* {@hide} */
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 5bc39f15..d53bb74 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -686,6 +686,15 @@
}
/**
+ * Used only by internal tests to free up memory.
+ *
+ * @hide
+ */
+ public static void freeMemoryForTests() {
+ getFactory().getStatics().freeMemoryForTests();
+ }
+
+ /**
* Informs WebView of the network state. This is used to set
* the JavaScript property window.navigator.isOnline and
* generates the online/offline event as specified in HTML5, sec. 5.7.7
diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java
index 9d9d882..e391aaf 100644
--- a/core/java/android/webkit/WebViewFactoryProvider.java
+++ b/core/java/android/webkit/WebViewFactoryProvider.java
@@ -50,6 +50,11 @@
String getDefaultUserAgent(Context context);
/**
+ * Used for tests only.
+ */
+ void freeMemoryForTests();
+
+ /**
* Implements the API method:
* {@link android.webkit.WebView#setWebContentsDebuggingEnabled(boolean) }
*/
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index 0957ab4..e90b460 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -1210,35 +1210,38 @@
child = (WeekView) view.getChildAt(offset);
}
- // Find out which month we're moving into
- int month;
- if (mIsScrollingUp) {
- month = child.getMonthOfFirstWeekDay();
- } else {
- month = child.getMonthOfLastWeekDay();
- }
-
- // And how it relates to our current highlighted month
- int monthDiff;
- if (mCurrentMonthDisplayed == 11 && month == 0) {
- monthDiff = 1;
- } else if (mCurrentMonthDisplayed == 0 && month == 11) {
- monthDiff = -1;
- } else {
- monthDiff = month - mCurrentMonthDisplayed;
- }
-
- // Only switch months if we're scrolling away from the currently
- // selected month
- if ((!mIsScrollingUp && monthDiff > 0) || (mIsScrollingUp && monthDiff < 0)) {
- Calendar firstDay = child.getFirstDay();
+ if (child != null) {
+ // Find out which month we're moving into
+ int month;
if (mIsScrollingUp) {
- firstDay.add(Calendar.DAY_OF_MONTH, -DAYS_PER_WEEK);
+ month = child.getMonthOfFirstWeekDay();
} else {
- firstDay.add(Calendar.DAY_OF_MONTH, DAYS_PER_WEEK);
+ month = child.getMonthOfLastWeekDay();
}
- setMonthDisplayed(firstDay);
+
+ // And how it relates to our current highlighted month
+ int monthDiff;
+ if (mCurrentMonthDisplayed == 11 && month == 0) {
+ monthDiff = 1;
+ } else if (mCurrentMonthDisplayed == 0 && month == 11) {
+ monthDiff = -1;
+ } else {
+ monthDiff = month - mCurrentMonthDisplayed;
+ }
+
+ // Only switch months if we're scrolling away from the currently
+ // selected month
+ if ((!mIsScrollingUp && monthDiff > 0) || (mIsScrollingUp && monthDiff < 0)) {
+ Calendar firstDay = child.getFirstDay();
+ if (mIsScrollingUp) {
+ firstDay.add(Calendar.DAY_OF_MONTH, -DAYS_PER_WEEK);
+ } else {
+ firstDay.add(Calendar.DAY_OF_MONTH, DAYS_PER_WEEK);
+ }
+ setMonthDisplayed(firstDay);
+ }
}
+
mPreviousScrollPosition = currScroll;
mPreviousScrollState = mCurrentScrollState;
}
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index c0fde2e..9c6a2e3 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -427,12 +427,12 @@
* Flag whether to ignore move events - we ignore such when we show in IME
* to prevent the content from scrolling.
*/
- private boolean mIngonreMoveEvents;
+ private boolean mIgnoreMoveEvents;
/**
- * Flag whether to show soft input on tap.
+ * Flag whether to perform a click on tap.
*/
- private boolean mShowSoftInputOnTap;
+ private boolean mPerformClickOnTap;
/**
* The top of the top selection divider.
@@ -808,8 +808,8 @@
mInputText.setVisibility(View.INVISIBLE);
mLastDownOrMoveEventY = mLastDownEventY = event.getY();
mLastDownEventTime = event.getEventTime();
- mIngonreMoveEvents = false;
- mShowSoftInputOnTap = false;
+ mIgnoreMoveEvents = false;
+ mPerformClickOnTap = false;
// Handle pressed state before any state change.
if (mLastDownEventY < mTopSelectionDividerTop) {
if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) {
@@ -840,7 +840,7 @@
postChangeCurrentByOneFromLongPress(
true, ViewConfiguration.getLongPressTimeout());
} else {
- mShowSoftInputOnTap = true;
+ mPerformClickOnTap = true;
postBeginSoftInputOnLongPressCommand();
}
return true;
@@ -861,7 +861,7 @@
int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_MOVE: {
- if (mIngonreMoveEvents) {
+ if (mIgnoreMoveEvents) {
break;
}
float currentMoveY = event.getY();
@@ -893,9 +893,9 @@
int deltaMoveY = (int) Math.abs(eventY - mLastDownEventY);
long deltaTime = event.getEventTime() - mLastDownEventTime;
if (deltaMoveY <= mTouchSlop && deltaTime < ViewConfiguration.getTapTimeout()) {
- if (mShowSoftInputOnTap) {
- mShowSoftInputOnTap = false;
- showSoftInput();
+ if (mPerformClickOnTap) {
+ mPerformClickOnTap = false;
+ performClick();
} else {
int selectorIndexOffset = (eventY / mSelectorElementHeight)
- SELECTOR_MIDDLE_ITEM_INDEX;
@@ -1188,6 +1188,27 @@
setValueInternal(value, false);
}
+ @Override
+ public boolean performClick() {
+ if (!mHasSelectorWheel) {
+ return super.performClick();
+ } else if (!super.performClick()) {
+ showSoftInput();
+ }
+ return true;
+ }
+
+ @Override
+ public boolean performLongClick() {
+ if (!mHasSelectorWheel) {
+ return super.performLongClick();
+ } else if (!super.performLongClick()) {
+ showSoftInput();
+ mIgnoreMoveEvents = true;
+ }
+ return true;
+ }
+
/**
* Shows the soft input for its input text.
*/
@@ -2166,8 +2187,7 @@
@Override
public void run() {
- showSoftInput();
- mIngonreMoveEvents = true;
+ performLongClick();
}
}
@@ -2295,7 +2315,14 @@
}
case AccessibilityNodeInfo.ACTION_CLICK: {
if (NumberPicker.this.isEnabled()) {
- showSoftInput();
+ performClick();
+ return true;
+ }
+ return false;
+ }
+ case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
+ if (NumberPicker.this.isEnabled()) {
+ performLongClick();
return true;
}
return false;
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 5392a96..6a369a6 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -308,6 +308,11 @@
mMirrorForRtl = a.getBoolean(R.styleable.ProgressBar_mirrorForRtl, mMirrorForRtl);
a.recycle();
+
+ // If not explicitly specified this view is important for accessibility.
+ if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
+ setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+ }
}
/**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 7a9809f..37121e2 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8667,6 +8667,10 @@
super.onRtlPropertiesChanged(layoutDirection);
mTextDir = getTextDirectionHeuristic();
+
+ if (mLayout != null) {
+ checkForRelayout();
+ }
}
TextDirectionHeuristic getTextDirectionHeuristic() {
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index ab871fb..942995b 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -372,23 +372,25 @@
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
mAppearingPackages = pkgList;
- mChangeType = PACKAGE_TEMPORARY_CHANGE;
+ mChangeType = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)
+ ? PACKAGE_UPDATING : PACKAGE_TEMPORARY_CHANGE;
mSomePackagesChanged = true;
if (pkgList != null) {
onPackagesAvailable(pkgList);
for (int i=0; i<pkgList.length; i++) {
- onPackageAppeared(pkgList[i], PACKAGE_TEMPORARY_CHANGE);
+ onPackageAppeared(pkgList[i], mChangeType);
}
}
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
mDisappearingPackages = pkgList;
- mChangeType = PACKAGE_TEMPORARY_CHANGE;
+ mChangeType = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)
+ ? PACKAGE_UPDATING : PACKAGE_TEMPORARY_CHANGE;
mSomePackagesChanged = true;
if (pkgList != null) {
onPackagesUnavailable(pkgList);
for (int i=0; i<pkgList.length; i++) {
- onPackageDisappeared(pkgList[i], PACKAGE_TEMPORARY_CHANGE);
+ onPackageDisappeared(pkgList[i], mChangeType);
}
}
}
diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java
new file mode 100644
index 0000000..cc8ce2c
--- /dev/null
+++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.animation.TimeInterpolator;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.FrameLayout;
+
+/**
+ * Special layout that finishes its activity when swiped away.
+ */
+public class SwipeDismissLayout extends FrameLayout {
+ private static final String TAG = "SwipeDismissLayout";
+
+ private static final float TRANSLATION_MIN_ALPHA = 0.5f;
+
+ public interface OnDismissedListener {
+ void onDismissed(SwipeDismissLayout layout);
+ }
+
+ public interface OnSwipeProgressChangedListener {
+ /**
+ * Called when the layout has been swiped and the position of the window should change.
+ *
+ * @param progress A number in [-1, 1] representing how far to the left
+ * or right the window has been swiped. Negative values are swipes
+ * left, and positives are right.
+ * @param translate A number in [-w, w], where w is the width of the
+ * layout. This is equivalent to progress * layout.getWidth().
+ */
+ void onSwipeProgressChanged(SwipeDismissLayout layout, float progress, float translate);
+
+ void onSwipeCancelled(SwipeDismissLayout layout);
+ }
+
+ // Cached ViewConfiguration and system-wide constant values
+ private int mSlop;
+ private int mMinFlingVelocity;
+ private int mMaxFlingVelocity;
+ private long mAnimationTime;
+ private TimeInterpolator mCancelInterpolator;
+ private TimeInterpolator mDismissInterpolator;
+
+ // Transient properties
+ private int mActiveTouchId;
+ private float mDownX;
+ private float mDownY;
+ private boolean mSwiping;
+ private boolean mDismissed;
+ private boolean mDiscardIntercept;
+ private VelocityTracker mVelocityTracker;
+ private float mTranslationX;
+
+ private OnDismissedListener mDismissedListener;
+ private OnSwipeProgressChangedListener mProgressListener;
+
+ public SwipeDismissLayout(Context context) {
+ super(context);
+ init(context);
+ }
+
+ public SwipeDismissLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ public SwipeDismissLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(context);
+ }
+
+ private void init(Context context) {
+ ViewConfiguration vc = ViewConfiguration.get(getContext());
+ mSlop = vc.getScaledTouchSlop();
+ mMinFlingVelocity = vc.getScaledMinimumFlingVelocity() * 16;
+ mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity();
+ mAnimationTime = getContext().getResources().getInteger(
+ android.R.integer.config_shortAnimTime);
+ mCancelInterpolator = new DecelerateInterpolator(1.5f);
+ mDismissInterpolator = new AccelerateInterpolator(1.5f);
+ }
+
+ public void setOnDismissedListener(OnDismissedListener listener) {
+ mDismissedListener = listener;
+ }
+
+ public void setOnSwipeProgressChangedListener(OnSwipeProgressChangedListener listener) {
+ mProgressListener = listener;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ // offset because the view is translated during swipe
+ ev.offsetLocation(mTranslationX, 0);
+
+ switch (ev.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ resetMembers();
+ mDownX = ev.getRawX();
+ mDownY = ev.getRawY();
+ mActiveTouchId = ev.getPointerId(0);
+ mVelocityTracker = VelocityTracker.obtain();
+ mVelocityTracker.addMovement(ev);
+ break;
+
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ resetMembers();
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ if (mVelocityTracker == null || mDiscardIntercept) {
+ break;
+ }
+
+ int pointerIndex = ev.findPointerIndex(mActiveTouchId);
+ float dx = ev.getRawX() - mDownX;
+ float x = ev.getX(pointerIndex);
+ float y = ev.getY(pointerIndex);
+ if (dx != 0 && canScroll(this, false, dx, x, y)) {
+ mDiscardIntercept = true;
+ break;
+ }
+ updateSwiping(ev);
+ break;
+ }
+
+ return !mDiscardIntercept && mSwiping;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (mVelocityTracker == null) {
+ return super.onTouchEvent(ev);
+ }
+ switch (ev.getActionMasked()) {
+ case MotionEvent.ACTION_UP:
+ updateDismiss(ev);
+ if (mDismissed) {
+ dismiss();
+ } else if (mSwiping) {
+ cancel();
+ }
+ resetMembers();
+ break;
+
+ case MotionEvent.ACTION_CANCEL:
+ cancel();
+ resetMembers();
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ mVelocityTracker.addMovement(ev);
+ updateSwiping(ev);
+ updateDismiss(ev);
+ if (mSwiping) {
+ setProgress(ev.getRawX() - mDownX);
+ break;
+ }
+ }
+ return true;
+ }
+
+ private void setProgress(float deltaX) {
+ mTranslationX = deltaX;
+ if (mProgressListener != null) {
+ mProgressListener.onSwipeProgressChanged(this, deltaX / getWidth(), deltaX);
+ }
+ }
+
+ private void dismiss() {
+ if (mDismissedListener != null) {
+ mDismissedListener.onDismissed(this);
+ }
+ }
+
+ protected void cancel() {
+ if (mProgressListener != null) {
+ mProgressListener.onSwipeCancelled(this);
+ }
+ }
+
+ /**
+ * Resets internal members when canceling.
+ */
+ private void resetMembers() {
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ }
+ mVelocityTracker = null;
+ mTranslationX = 0;
+ mDownX = 0;
+ mDownY = 0;
+ mSwiping = false;
+ mDismissed = false;
+ mDiscardIntercept = false;
+ }
+
+ private void updateSwiping(MotionEvent ev) {
+ if (!mSwiping) {
+ float deltaX = ev.getRawX() - mDownX;
+ float deltaY = ev.getRawY() - mDownY;
+ mSwiping = deltaX > mSlop * 2 && Math.abs(deltaY) < mSlop * 2;
+ }
+ }
+
+ private void updateDismiss(MotionEvent ev) {
+ if (!mDismissed) {
+ mVelocityTracker.addMovement(ev);
+ mVelocityTracker.computeCurrentVelocity(1000);
+
+ float deltaX = ev.getRawX() - mDownX;
+ float velocityX = mVelocityTracker.getXVelocity();
+ float absVelocityX = Math.abs(velocityX);
+ float absVelocityY = Math.abs(mVelocityTracker.getYVelocity());
+
+ if (deltaX > getWidth() / 2) {
+ mDismissed = true;
+ } else if (absVelocityX >= mMinFlingVelocity
+ && absVelocityX <= mMaxFlingVelocity
+ && absVelocityY < absVelocityX / 2
+ && velocityX > 0
+ && deltaX > 0) {
+ mDismissed = true;
+ }
+ }
+ }
+
+ /**
+ * Tests scrollability within child views of v in the direction of dx.
+ *
+ * @param v View to test for horizontal scrollability
+ * @param checkV Whether the view v passed should itself be checked for scrollability (true),
+ * or just its children (false).
+ * @param dx Delta scrolled in pixels. Only the sign of this is used.
+ * @param x X coordinate of the active touch point
+ * @param y Y coordinate of the active touch point
+ * @return true if child views of v can be scrolled by delta of dx.
+ */
+ protected boolean canScroll(View v, boolean checkV, float dx, float x, float y) {
+ if (v instanceof ViewGroup) {
+ final ViewGroup group = (ViewGroup) v;
+ final int scrollX = v.getScrollX();
+ final int scrollY = v.getScrollY();
+ final int count = group.getChildCount();
+ for (int i = count - 1; i >= 0; i--) {
+ final View child = group.getChildAt(i);
+ if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() &&
+ y + scrollY >= child.getTop() && y + scrollY < child.getBottom() &&
+ canScroll(child, true, dx, x + scrollX - child.getLeft(),
+ y + scrollY - child.getTop())) {
+ return true;
+ }
+ }
+ }
+
+ return checkV && v.canScrollHorizontally((int) -dx);
+ }
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e7db535..05c9b17 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1056,7 +1056,7 @@
android:permissionGroupFlags="personalInfo"
android:priority="370" />
- <!-- Allows an application to monitor, modify, or abort outgoing
+ <!-- Allows an application to modify or abort outgoing
calls. -->
<permission android:name="android.permission.PROCESS_OUTGOING_CALLS"
android:permissionGroup="android.permission-group.PHONE_CALLS"
@@ -1526,7 +1526,7 @@
@hide -->
<permission android:name="android.permission.FORCE_STOP_PACKAGES"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
- android:protectionLevel="signature"
+ android:protectionLevel="signature|system"
android:label="@string/permlab_forceStopPackages"
android:description="@string/permdesc_forceStopPackages" />
diff --git a/core/res/res/anim/swipe_window_enter.xml b/core/res/res/anim/swipe_window_enter.xml
new file mode 100644
index 0000000..e1617e2
--- /dev/null
+++ b/core/res/res/anim/swipe_window_enter.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@interpolator/decelerate_quad" >
+ <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+ android:fillEnabled="true" android:fillBefore="true"
+ android:fillAfter="true"
+ android:duration="@android:integer/config_activityDefaultDur" />
+</set>
diff --git a/core/res/res/anim/swipe_window_exit.xml b/core/res/res/anim/swipe_window_exit.xml
new file mode 100644
index 0000000..ed0c5d3
--- /dev/null
+++ b/core/res/res/anim/swipe_window_exit.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@interpolator/decelerate_quad" >
+ <translate android:fromXDelta="0%" android:toXDelta="100%"
+ android:fillEnabled="true" android:fillBefore="true"
+ android:fillAfter="true"
+ android:duration="400" />
+</set>
diff --git a/core/res/res/layout/number_picker_with_selector_wheel_micro.xml b/core/res/res/layout/number_picker_with_selector_wheel_micro.xml
new file mode 100644
index 0000000..a1c0921
--- /dev/null
+++ b/core/res/res/layout/number_picker_with_selector_wheel_micro.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <view class="android.widget.NumberPicker$CustomEditText"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:id="@+id/numberpicker_input"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:singleLine="true"
+ android:background="@null" />
+
+</merge>
diff --git a/core/res/res/layout/screen_swipe_dismiss.xml b/core/res/res/layout/screen_swipe_dismiss.xml
new file mode 100644
index 0000000..90e970fe
--- /dev/null
+++ b/core/res/res/layout/screen_swipe_dismiss.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!--
+This is a layout for a window whose resident activity is finished when swiped away.
+-->
+
+<com.android.internal.widget.SwipeDismissLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/content"
+ android:fitsSystemWindows="true"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ />
diff --git a/core/res/res/values-ja/bools.xml b/core/res/res/values-ja/bools.xml
deleted file mode 100644
index 59cf744..0000000
--- a/core/res/res/values-ja/bools.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<resources>
- <bool name="flip_controller_fallback_keys">true</bool>
-</resources>
-
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 42e3b50..24ebff3 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -447,6 +447,10 @@
to {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION}. -->
<attr name="windowTranslucentNavigation" format="boolean" />
+ <!-- Flag to indicate that a window can be swiped away to be dismissed.
+ Corresponds to {@link android.view.Window.FEATURE_SWIPE_TO_DISMISS} -->
+ <attr name="windowSwipeToDismiss" format="boolean" />
+
<!-- ============ -->
<!-- Alert Dialog styles -->
<!-- ============ -->
@@ -1604,6 +1608,7 @@
<attr name="windowCloseOnTouchOutside" />
<attr name="windowTranslucentStatus" />
<attr name="windowTranslucentNavigation" />
+ <attr name="windowSwipeToDismiss" />
<!-- The minimum width the window is allowed to be, along the major
axis of the screen. That is, when in landscape. Can be either
an absolute dimension or a fraction of the screen size in that
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
index 10a5d85..18e4f2f 100644
--- a/core/res/res/values/bools.xml
+++ b/core/res/res/values/bools.xml
@@ -26,5 +26,4 @@
<bool name="show_ongoing_ime_switcher">true</bool>
<bool name="action_bar_expanded_action_views_exclusive">true</bool>
<bool name="target_honeycomb_needs_options_menu">true</bool>
- <bool name="flip_controller_fallback_keys">false</bool>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 986a005..30243a4 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -932,13 +932,13 @@
<!-- [CHAR LIMIT=NONE] Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_getAppOpsStats">Allows the app to retrieve
collected application operation statistics. Not for use by normal apps.</string>
-
+
<!-- [CHAR LIMIT=NONE] Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_updateAppOpsStats">modify app ops statistics</string>
<!-- [CHAR LIMIT=NONE] Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_updateAppOpsStats">Allows the app to modify
collected application operation statistics. Not for use by normal apps.</string>
-
+
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_backup">control system backup and restore</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -2247,6 +2247,10 @@
<!-- Other SIP address type. Same context as Other phone type. -->
<string name="sipAddressTypeOther">Other</string>
+ <!-- Error message that is displayed when the user clicks on a quick contacts badge, but
+ there is no contacts application installed that can display the quick contact -->
+ <string name="quick_contacts_not_available">No application found to view this contact.</string>
+
<!-- Instructions telling the user to enter their SIM PIN to unlock the keyguard.
Displayed in one line in a large font. -->
<string name="keyguard_password_enter_pin_code">Type PIN code</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index cb2fd6d..4d4feeee 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -225,6 +225,14 @@
<item name="windowExitAnimation">@anim/fast_fade_out</item>
</style>
+ <!-- Window animations for swipe-dismissable windows. {@hide} -->
+ <style name="Animation.SwipeDismiss">
+ <item name="taskOpenEnterAnimation">@anim/swipe_window_enter</item>
+ <item name="taskOpenExitAnimation">@anim/swipe_window_exit</item>
+ <item name="taskCloseEnterAnimation">@anim/swipe_window_enter</item>
+ <item name="taskCloseExitAnimation">@anim/swipe_window_exit</item>
+ </style>
+
<!-- Status Bar Styles -->
<style name="TextAppearance.StatusBar">
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
diff --git a/core/res/res/values/styles_micro.xml b/core/res/res/values/styles_micro.xml
index 2fd283e..52d90bc 100644
--- a/core/res/res/values/styles_micro.xml
+++ b/core/res/res/values/styles_micro.xml
@@ -19,4 +19,16 @@
<style name="Widget.Micro.TextView">
<item name="android:fontFamily">sans-serif-condensed</item>
</style>
+
+ <style name="Widget.Micro.NumberPicker">
+ <item name="android:internalLayout">@android:layout/number_picker_with_selector_wheel_micro</item>
+ <item name="android:solidColor">@android:color/transparent</item>
+ <item name="android:selectionDivider">@android:drawable/numberpicker_selection_divider</item>
+ <item name="android:selectionDividerHeight">0dip</item>
+ <item name="android:selectionDividersDistance">104dip</item>
+ <item name="android:internalMinWidth">64dip</item>
+ <item name="android:internalMaxHeight">180dip</item>
+ <item name="virtualButtonPressedDrawable">?android:attr/selectableItemBackground</item>
+ <item name="android:descendantFocusability">blocksDescendants</item>
+ </style>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c38e753..f479806 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -288,7 +288,6 @@
<java-symbol type="bool" name="config_useFixedVolume" />
<java-symbol type="bool" name="config_forceDefaultOrientation" />
<java-symbol type="bool" name="config_wifi_batched_scan_supported" />
- <java-symbol type="bool" name="flip_controller_fallback_keys" />
<java-symbol type="integer" name="config_cursorWindowSize" />
<java-symbol type="integer" name="config_extraFreeKbytesAdjust" />
@@ -690,6 +689,7 @@
<java-symbol type="string" name="mobile_provisioning_apn" />
<java-symbol type="string" name="mobile_provisioning_url" />
<java-symbol type="string" name="mobile_redirected_provisioning_url" />
+ <java-symbol type="string" name="quick_contacts_not_available" />
<java-symbol type="string" name="reboot_safemode_confirm" />
<java-symbol type="string" name="reboot_safemode_title" />
<java-symbol type="string" name="relationTypeAssistant" />
@@ -1373,6 +1373,7 @@
<java-symbol type="layout" name="screen_progress" />
<java-symbol type="layout" name="screen_simple" />
<java-symbol type="layout" name="screen_simple_overlay_action_mode" />
+ <java-symbol type="layout" name="screen_swipe_dismiss" />
<java-symbol type="layout" name="screen_title" />
<java-symbol type="layout" name="screen_title_icons" />
<java-symbol type="string" name="system_ui_date_pattern" />
diff --git a/core/res/res/values/themes_micro.xml b/core/res/res/values/themes_micro.xml
index be5fa99..7c0b7bc 100644
--- a/core/res/res/values/themes_micro.xml
+++ b/core/res/res/values/themes_micro.xml
@@ -14,14 +14,45 @@
limitations under the License.
-->
<resources>
- <style name="Theme.Micro" parent="Theme.Holo" />
+ <style name="Theme.Micro" parent="Theme.Holo.NoActionBar">
+ <item name="textViewStyle">@android:style/Widget.Micro.TextView</item>
+ <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item>
+ <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item>
+ <item name="windowIsFloating">false</item>
+ <item name="windowIsTranslucent">true</item>
+ <item name="windowSwipeToDismiss">true</item>
+ </style>
- <style name="Theme.Micro.Light" parent="Theme.Holo.Light"/>
+ <style name="Theme.Micro.NoActionBar" parent="Theme.Holo.NoActionBar">
+ <item name="textViewStyle">@android:style/Widget.Micro.TextView</item>
+ <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item>
+ <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item>
+ <item name="windowIsFloating">false</item>
+ <item name="windowIsTranslucent">true</item>
+ <item name="windowSwipeToDismiss">true</item>
+ </style>
+ <style name="Theme.Micro.Light" parent="Theme.Holo.Light">
+ <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item>
+ <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item>
+ <item name="windowIsFloating">false</item>
+ <item name="windowIsTranslucent">true</item>
+ <item name="windowSwipeToDismiss">true</item>
+ </style>
<style name="Theme.Micro.Light.NoActionBar" parent="Theme.Holo.Light.NoActionBar">
<item name="textViewStyle">@android:style/Widget.Micro.TextView</item>
+ <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item>
+ <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item>
+ <item name="windowIsFloating">false</item>
+ <item name="windowIsTranslucent">true</item>
+ <item name="windowSwipeToDismiss">true</item>
</style>
<style name="Theme.Micro.Light.DarkActionBar" parent="Theme.Holo.Light.DarkActionBar">
<item name="textViewStyle">@android:style/Widget.Micro.TextView</item>
+ <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item>
+ <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item>
+ <item name="windowIsFloating">false</item>
+ <item name="windowIsTranslucent">true</item>
+ <item name="windowSwipeToDismiss">true</item>
</style>
</resources>
diff --git a/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm
index 695a74f..01d22ee 100644
--- a/data/keyboards/Generic.kcm
+++ b/data/keyboards/Generic.kcm
@@ -477,4 +477,128 @@
ctrl: fallback MENU
}
-### Gamepad buttons are handled by the view root ###
+### Gamepad buttons ###
+
+key BUTTON_A {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_B {
+ base: fallback BACK
+}
+
+key BUTTON_C {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_X {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_Y {
+ base: fallback BACK
+}
+
+key BUTTON_Z {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_L1 {
+ base: none
+}
+
+key BUTTON_R1 {
+ base: none
+}
+
+key BUTTON_L2 {
+ base: none
+}
+
+key BUTTON_R2 {
+ base: none
+}
+
+key BUTTON_THUMBL {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_THUMBR {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_START {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_SELECT {
+ base: fallback MENU
+}
+
+key BUTTON_MODE {
+ base: fallback MENU
+}
+
+key BUTTON_1 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_2 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_3 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_4 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_5 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_6 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_7 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_8 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_9 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_10 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_11 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_12 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_13 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_14 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_15 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_16 {
+ base: fallback DPAD_CENTER
+}
diff --git a/data/keyboards/Vendor_18d1_Product_2c40.kl b/data/keyboards/Vendor_18d1_Product_2c40.kl
new file mode 100644
index 0000000..903f13b6
--- /dev/null
+++ b/data/keyboards/Vendor_18d1_Product_2c40.kl
@@ -0,0 +1,42 @@
+# Copyright (C) 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Odie
+
+key 304 BUTTON_A
+key 305 BUTTON_B
+key 307 BUTTON_X
+key 308 BUTTON_Y
+key 310 BUTTON_L1
+key 311 BUTTON_R1
+key 316 BUTTON_MODE
+key 317 BUTTON_THUMBL
+key 318 BUTTON_THUMBR
+
+key 158 BACK WAKE_DROPPED
+key 172 HOME
+
+axis 0x00 X
+axis 0x01 Y
+axis 0x02 Z
+axis 0x05 RZ
+axis 0x09 RTRIGGER
+axis 0x0a LTRIGGER
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+led 0x00 CONTROLLER_1
+led 0x01 CONTROLLER_2
+led 0x02 CONTROLLER_3
+led 0x03 CONTROLLER_4
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index bcd4607..6d29c69 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -61,7 +61,7 @@
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on February 4, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on March 3, 2014.
<br/>Any versions with less than 0.1% distribution are not shown.</em>
</p>
@@ -92,7 +92,7 @@
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on February 4, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on March 3, 2014.
<br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
@@ -133,17 +133,17 @@
</tr>
<tr>
<td>2.0</th>
-<td>92.3%</td>
+<td>91.1%</td>
</tr>
<tr>
<td>3.0</th>
-<td>7.6%</td>
+<td>8.8%</td>
</tr>
</table>
-<p style="clear:both"><em>Data collected during a 7-day period ending on February 4, 2014</em></p>
+<p style="clear:both"><em>Data collected during a 7-day period ending on March 3, 2014</em></p>
@@ -161,17 +161,17 @@
var VERSION_DATA =
[
{
- "chart": "//chart.googleapis.com/chart?cht=p&chs=500x250&chl=Froyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chf=bg%2Cs%2C00000000&chd=t%3A1.3%2C20.0%2C0.1%2C16.1%2C60.7%2C1.8&chco=c4df9b%2C6fad0c",
+ "chart": "//chart.googleapis.com/chart?chl=Froyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chd=t%3A1.2%2C19.0%2C0.1%2C15.2%2C62.0%2C2.5&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&chs=500x250&cht=p",
"data": [
{
"api": 8,
"name": "Froyo",
- "perc": "1.3"
+ "perc": "1.2"
},
{
"api": 10,
"name": "Gingerbread",
- "perc": "20.0"
+ "perc": "19.0"
},
{
"api": 13,
@@ -181,27 +181,27 @@
{
"api": 15,
"name": "Ice Cream Sandwich",
- "perc": "16.1"
+ "perc": "15.2"
},
{
"api": 16,
"name": "Jelly Bean",
- "perc": "35.5"
+ "perc": "35.3"
},
{
"api": 17,
"name": "Jelly Bean",
- "perc": "16.3"
+ "perc": "17.1"
},
{
"api": 18,
"name": "Jelly Bean",
- "perc": "8.9"
+ "perc": "9.6"
},
{
"api": 19,
"name": "KitKat",
- "perc": "1.8"
+ "perc": "2.5"
}
]
}
@@ -217,17 +217,17 @@
"data": {
"Large": {
"hdpi": "0.6",
- "ldpi": "0.8",
- "mdpi": "4.4",
- "tvdpi": "1.6",
+ "ldpi": "0.7",
+ "mdpi": "4.3",
+ "tvdpi": "1.5",
"xhdpi": "0.6"
},
"Normal": {
- "hdpi": "33.3",
- "ldpi": "0.1",
- "mdpi": "13.9",
- "xhdpi": "20.2",
- "xxhdpi": "11.3"
+ "hdpi": "33.7",
+ "ldpi": "0.2",
+ "mdpi": "13.6",
+ "xhdpi": "19.9",
+ "xxhdpi": "11.9"
},
"Small": {
"ldpi": "8.1"
@@ -235,12 +235,12 @@
"Xlarge": {
"hdpi": "0.3",
"ldpi": "0.1",
- "mdpi": "4.5",
+ "mdpi": "4.3",
"xhdpi": "0.2"
}
},
- "densitychart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chf=bg%2Cs%2C00000000&chd=t%3A9.1%2C22.8%2C1.6%2C34.3%2C21.0%2C11.3&chco=c4df9b%2C6fad0c",
- "layoutchart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chl=Xlarge%7CLarge%7CNormal%7CSmall&chf=bg%2Cs%2C00000000&chd=t%3A5.1%2C8.0%2C78.9%2C8.1&chco=c4df9b%2C6fad0c"
+ "densitychart": "//chart.googleapis.com/chart?chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chd=t%3A9.1%2C22.2%2C1.5%2C34.6%2C20.7%2C11.9&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&chs=400x250&cht=p",
+ "layoutchart": "//chart.googleapis.com/chart?chl=Xlarge%7CLarge%7CNormal%7CSmall&chd=t%3A4.9%2C7.7%2C79.3%2C8.1&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&chs=400x250&cht=p"
}
];
diff --git a/docs/html/distribute/googleplay/promote/badge-files.jd b/docs/html/distribute/googleplay/promote/badge-files.jd
index ede1e21..03ebd01 100644
--- a/docs/html/distribute/googleplay/promote/badge-files.jd
+++ b/docs/html/distribute/googleplay/promote/badge-files.jd
@@ -18,107 +18,112 @@
<div class="col-4" style="margin-left:0">
- <a href="{@docRoot}downloads/brand/en_generic_rgb_wo.ai">English (English)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/english_get.ai">English (English)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/v2/amharic_get.ai">ኣማርኛ (Amharic)</a><br/>
<a href="{@docRoot}downloads/brand/af_generic_rgb_wo.ai">Afrikaans (Afrikaans)</a><br/>
<!--
<a href="{@docRoot}downloads/brand/ar_generic_rgb_wo.ai">العربية (Arabic)</a><br/>
-->
- <a href="{@docRoot}downloads/brand/be_generic_rgb_wo.ai">Беларуская (Belarusian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/belarusian_get.ai">Беларуская (Belarusian)</a><br/>
- <a href="{@docRoot}downloads/brand/bg_generic_rgb_wo.ai">български (Bulgarian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/bulgarian_get.ai">български (Bulgarian)</a><br/>
- <a href="{@docRoot}downloads/brand/ca_generic_rgb_wo.ai">Català (Catalan)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/catalan_get.ai">Català (Catalan)</a><br/>
- <a href="{@docRoot}downloads/brand/zh-cn_generic_rgb_wo.ai">中文 (中国) (Chinese)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/traditional_chinese_get.ai">中文 (中国) (Chinese)</a><br/>
- <a href="{@docRoot}downloads/brand/zh-hk_generic_rgb_wo.ai">中文(香港) (Chinese Hong Kong)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/hongkong_chinese_get.ai">中文(香港) (Chinese Hong Kong)</a><br/>
- <a href="{@docRoot}downloads/brand/zh-tw_generic_rgb_wo.ai">中文 (台灣) (Chinese Taiwan)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/taiwan_chinese_get.ai">中文 (台灣) (Chinese Taiwan)</a><br/>
- <a href="{@docRoot}downloads/brand/hr_generic_rgb_wo.ai">Hrvatski (Croatian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/croatian_get.ai">Hrvatski (Croatian)</a><br/>
- <a href="{@docRoot}downloads/brand/cs_generic_rgb_wo.ai">Česky (Czech)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/czech_get.ai">Česky (Czech)</a><br/>
- <a href="{@docRoot}downloads/brand/da_generic_rgb_wo.ai">Dansk (Danish)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/danish_get.ai">Dansk (Danish)</a><br/>
- <a href="{@docRoot}downloads/brand/nl_generic_rgb_wo.ai">Nederlands (Dutch)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/dutch_get.ai">Nederlands (Dutch)</a><br/>
- <a href="{@docRoot}downloads/brand/et_generic_rgb_wo.ai">Eesti keel (Estonian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/estonian_get.ai">Eesti keel (Estonian)</a><br/>
- <a href="{@docRoot}downloads/brand/fa_generic_rgb_wo.ai">فارسی (Farsi Persian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/farsi_get.ai">فارسی (Farsi Persian)</a><br/>
- <a href="{@docRoot}downloads/brand/fil_generic_rgb_wo.ai">Tagalog (Filipino)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/filipino_get.ai">Tagalog (Filipino)</a><br/>
- <a href="{@docRoot}downloads/brand/fi_generic_rgb_wo.ai">Suomi (Finnish)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/finnish_get.ai">Suomi (Finnish)</a><br/>
</div>
<div class="col-4">
- <a href="{@docRoot}downloads/brand/fr_generic_rgb_wo.ai">Français (French)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/french_get.ai">Français (French)</a><br/>
- <a href="{@docRoot}downloads/brand/de_generic_rgb_wo.ai">Deutsch (German)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/german_get.ai">Deutsch (German)</a><br/>
- <a href="{@docRoot}downloads/brand/el_generic_rgb_wo.ai">Ελληνικά (Greek)</a><br/>
-<!--
- <a href="{@docRoot}downloads/brand/iw-he_generic_rgb_wo.ai">עברית (Hebrew)</a><br/>
--->
- <a href="{@docRoot}downloads/brand/hu_generic_rgb_wo.ai">Magyar (Hungarian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/greek_get.ai">Ελληνικά (Greek)</a><br/>
- <a href="{@docRoot}downloads/brand/id-in_generic_rgb_wo.ai">Bahasa Indonesia (Indonesian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/hebrew_get.ai">עברית (Hebrew)</a><br/>
- <a href="{@docRoot}downloads/brand/it_generic_rgb_wo.ai">Italiano (Italian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/hindi_get.ai">हिन्दी (Hindi)</a><br/>
- <a href="{@docRoot}downloads/brand/ja_generic_rgb_wo.ai">日本語 (Japanese)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/hungarian_get.ai">Magyar (Hungarian)</a><br/>
- <a href="{@docRoot}downloads/brand/ko_generic_rgb_wo.ai">한국어 (Korean)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/indonesian_get.ai">Bahasa Indonesia (Indonesian)</a><br/>
- <a href="{@docRoot}downloads/brand/lv_generic_rgb_wo.ai">Latviski (Latvian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/italian_get.ai">Italiano (Italian)</a><br/>
- <a href="{@docRoot}downloads/brand/lt_generic_rgb_wo.ai">Lietuviškai (Lithuanian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/japanese_get.ai">日本語 (Japanese)</a><br/>
- <a href="{@docRoot}downloads/brand/ms_generic_rgb_wo.ai">Bahasa Melayu (Malay)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/kazakh_get.ai">Қазақ тілі (Kazakh)</a><br/>
- <a href="{@docRoot}downloads/brand/no_generic_rgb_wo.ai">Norsk (Norwegian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/korean_get.ai">한국어 (Korean)</a><br/>
- <a href="{@docRoot}downloads/brand/pl_generic_rgb_wo.ai">Polski (Polish)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/latvian_get.ai">Latviski (Latvian)</a><br/>
- <a href="{@docRoot}downloads/brand/pt-pt_generic_rgb_wo.ai">Português (Portuguese)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/lithuanian_get.ai">Lietuviškai (Lithuanian)</a><br/>
- <a href="{@docRoot}downloads/brand/pt-br_generic_rgb_wo.ai">Português Brasil (Portuguese Brazil)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/malay_get.ai">Bahasa Melayu (Malay)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/v2/norwegian_get.ai">Norsk (Norwegian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/v2/polish_get.ai">Polski (Polish)</a><br/>
</div>
<div class="col-4" style="margin-right:0">
- <a href="{@docRoot}downloads/brand/ro_generic_rgb_wo.ai">Românã (Romanian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/portugal_portuguese_get.ai">Português (Portuguese)</a><br/>
- <a href="{@docRoot}downloads/brand/ru_generic_rgb_wo.ai">Pусский (Russian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/brazilian_portuguese_get.ai">Português Brasil (Portuguese Brazil)</a><br/>
- <a href="{@docRoot}downloads/brand/sr_generic_rgb_wo.ai">Српски / srpski (Serbian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/romanian_get.ai">Românã (Romanian)</a><br/>
- <a href="{@docRoot}downloads/brand/sk_generic_rgb_wo.ai">Slovenčina (Slovak)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/russian_get.ai">Pусский (Russian)</a><br/>
- <a href="{@docRoot}downloads/brand/sl_generic_rgb_wo.ai">Slovenščina (Slovenian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/serbian_get.ai">Српски / srpski (Serbian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/v2/slovak_get.ai">Slovenčina (Slovak)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/v2/slovenian_get.ai">Slovenščina (Slovenian)</a><br/>
- <a href="{@docRoot}downloads/brand/es_generic_rgb_wo.ai">Español (Spanish)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/spanish_get.ai">Español (Spanish)</a><br/>
- <a href="{@docRoot}downloads/brand/es-419_generic_rgb_wo.ai">Español Latinoamérica (Spanish Latin America)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/spanish_latam_get.ai">Español Latinoamérica (Spanish Latin America)</a><br/>
- <a href="{@docRoot}downloads/brand/sv_generic_rgb_wo.ai">Svenska (Swedish)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/swahili_get.ai">Kiswahili (Swahili)</a><br/>
- <a href="{@docRoot}downloads/brand/sw_generic_rgb_wo.ai">Kiswahili (Swahili)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/swedish_get.ai">Svenska (Swedish)</a><br/>
- <a href="{@docRoot}downloads/brand/th_generic_rgb_wo.ai">ภาษาไทย (Thai)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/thai_get.ai">ภาษาไทย (Thai)</a><br/>
- <a href="{@docRoot}downloads/brand/tr_generic_rgb_wo.ai">Türkçe (Turkish)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/turkish_get.ai">Türkçe (Turkish)</a><br/>
<a href="{@docRoot}downloads/brand/uk_generic_rgb_wo.ai">Українська (Ukrainian)</a><br/>
-
<a href="{@docRoot}downloads/brand/vi_generic_rgb_wo.ai">Tiếng Việt (Vietnamese)</a><br/>
- <a href="{@docRoot}downloads/brand/zu_generic_rgb_wo.ai">isiZulu (Zulu)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/zulu_get.ai">isiZulu (Zulu)</a><br/>
</div>
<div style="clear:left"> </div>
@@ -128,126 +133,122 @@
+
+
+
<hr>
<img src="{@docRoot}images/brand/en_app_rgb_wo_60.png" alt="Android App On Google Play">
<div style="clear:left"> </div>
-<div class="col-8" style="margin-left:0">
+<div class="col-4" style="margin-left:0">
- <a href="{@docRoot}downloads/brand/en_app_rgb_wo.ai">English (English)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/english_app.ai">English (English)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/v2/afrikaans_app.ai">Afrikaans (Afrikaans)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/v2/amharic_app.ai">ኣማርኛ (Amharic)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/v2/arabic_app.ai">العربية (Arabic)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/v2/belarusian_app.ai">Беларуская (Belarusian)</a><br/>
-<!--
- <a href="{@docRoot}downloads/brand/af_app_rgb_wo.ai">Afrikaans (Afrikaans)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/bulgarian_app.ai">български (Bulgarian)</a><br/>
- <a href="{@docRoot}downloads/brand/ar_app_rgb_wo.ai">العربية (Arabic)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/catalan_app.ai">Català (Catalan)</a><br/>
- <a href="{@docRoot}downloads/brand/be_app_rgb_wo.ai">Беларуская (Belarusian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/bg_app_rgb_wo.ai">български (Bulgarian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/traditional_chinese_app.ai">中文 (中国) (Chinese)</a><br/>
- <a href="{@docRoot}downloads/brand/ca_app_rgb_wo.ai">Català (Catalan)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/hongkong_chinese_app.ai">中文(香港) (Chinese Hong Kong)</a><br/>
- <a href="{@docRoot}downloads/brand/zh-cn_app_rgb_wo.ai">中文 (中国) (Chinese)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/taiwan_chinese_app.ai">中文 (台灣) (Chinese Taiwan)</a><br/>
- <a href="{@docRoot}downloads/brand/zh-hk_app_rgb_wo.ai">中文(香港) (Chinese Hong Kong)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/croatian_app.ai">Hrvatski (Croatian)</a><br/>
- <a href="{@docRoot}downloads/brand/zh-tw_app_rgb_wo.ai">中文 (台灣) (Chinese Taiwan)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/czech_app.ai">Česky (Czech)</a><br/>
- <a href="{@docRoot}downloads/brand/hr_app_rgb_wo.ai">Hrvatski (Croatian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/danish_app.ai">Dansk (Danish)</a><br/>
- <a href="{@docRoot}downloads/brand/cs_app_rgb_wo.ai">Česky (Czech)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/dutch_app.ai">Nederlands (Dutch)</a><br/>
- <a href="{@docRoot}downloads/brand/da_app_rgb_wo.ai">Dansk (Danish)</a><br/>
--->
+ <a href="{@docRoot}downloads/brand/v2/estonian_app.ai">Eesti keel (Estonian)</a><br/>
- <a href="{@docRoot}downloads/brand/nl_app_rgb_wo.ai">Nederlands (Dutch)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/farsi_app.ai">فارسی (Farsi Persian)</a><br/>
-<!--
- <a href="{@docRoot}downloads/brand/et_app_rgb_wo.ai">Eesti keel (Estonian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/filipino_app.ai">Tagalog (Filipino)</a><br/>
- <a href="{@docRoot}downloads/brand/fa_app_rgb_wo.ai">فارسی (Farsi Persian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/fil_app_rgb_wo.ai">Tagalog (Filipino)</a><br/>
-
- <a href="{@docRoot}downloads/brand/fi_app_rgb_wo.ai">Suomi (Finnish)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/finnish_app.ai">Suomi (Finnish)</a><br/>
</div>
<div class="col-4">
--->
- <a href="{@docRoot}downloads/brand/fr_app_rgb_wo.ai">Français (French)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/french_app.ai">Français (French)</a><br/>
- <a href="{@docRoot}downloads/brand/de_app_rgb_wo.ai">Deutsch (German)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/german_app.ai">Deutsch (German)</a><br/>
-<!--
- <a href="{@docRoot}downloads/brand/el_app_rgb_wo.ai">Ελληνικά (Greek)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/greek_app.ai">Ελληνικά (Greek)</a><br/>
- <a href="{@docRoot}downloads/brand/iw-he_app_rgb_wo.ai">עברית (Hebrew)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/hebrew_app.ai">עברית (Hebrew)</a><br/>
- <a href="{@docRoot}downloads/brand/hu_app_rgb_wo.ai">Magyar (Hungarian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/hindi_app.ai">हिन्दी (Hindi)</a><br/>
- <a href="{@docRoot}downloads/brand/id-in_app_rgb_wo.ai">Bahasa Indonesia (Indonesian)</a><br/>
--->
+ <a href="{@docRoot}downloads/brand/v2/hungarian_app.ai">Magyar (Hungarian)</a><br/>
- <a href="{@docRoot}downloads/brand/it_app_rgb_wo.ai">Italiano (Italian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/indonesian_app.ai">Bahasa Indonesia (Indonesian)</a><br/>
- <a href="{@docRoot}downloads/brand/ja_app_rgb_wo.ai">日本語 (Japanese)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/italian_app.ai">Italiano (Italian)</a><br/>
- <a href="{@docRoot}downloads/brand/ko_app_rgb_wo.ai">한국어 (Korean)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/japanese_app.ai">日本語 (Japanese)</a><br/>
-<!--
- <a href="{@docRoot}downloads/brand/lv_app_rgb_wo.ai">Latviski (Latvian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/korean_app.ai">한국어 (Korean)</a><br/>
- <a href="{@docRoot}downloads/brand/lt_app_rgb_wo.ai">Lietuviškai (Lithuanian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/latvian_app.ai">Latviski (Latvian)</a><br/>
- <a href="{@docRoot}downloads/brand/ms_app_rgb_wo.ai">Bahasa Melayu (Malay)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/lithuanian_app.ai">Lietuviškai (Lithuanian)</a><br/>
- <a href="{@docRoot}downloads/brand/no_app_rgb_wo.ai">Norsk (Norwegian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/malay_app.ai">Bahasa Melayu (Malay)</a><br/>
- <a href="{@docRoot}downloads/brand/pl_app_rgb_wo.ai">Polski (Polish)</a><br/>
--->
+ <a href="{@docRoot}downloads/brand/v2/norwegian_app.ai">Norsk (Norwegian)</a><br/>
- <a href="{@docRoot}downloads/brand/pt-pt_app_rgb_wo.ai">Português (Portuguese)</a><br/>
-
- <a href="{@docRoot}downloads/brand/pt-br_app_rgb_wo.ai">Português Brasil (Portuguese Brazil)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/polish_app.ai">Polski (Polish)</a><br/>
-<!--
</div>
<div class="col-4" style="margin-right:0">
- <a href="{@docRoot}downloads/brand/ro_app_rgb_wo.ai">Românã (Romanian)</a><br/>
- <a href="{@docRoot}downloads/brand/ru_app_rgb_wo.ai">Pусский (Russian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/portugal_portuguese_app.ai">Português (Portuguese)</a><br/>
- <a href="{@docRoot}downloads/brand/sr_app_rgb_wo.ai">Српски / srpski (Serbian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/brazilian_portuguese_app.ai">Português Brasil (Portuguese Brazil)</a><br/>
- <a href="{@docRoot}downloads/brand/sk_app_rgb_wo.ai">Slovenčina (Slovak)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/romanian_app.ai">Românã (Romanian)</a><br/>
- <a href="{@docRoot}downloads/brand/sl_app_rgb_wo.ai">Slovenščina (Slovenian)</a><br/>
--->
+ <a href="{@docRoot}downloads/brand/v2/russian_app.ai">Pусский (Russian)</a><br/>
- <a href="{@docRoot}downloads/brand/es_app_rgb_wo.ai">Español (Spanish)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/serbian_app.ai">Српски / srpski (Serbian)</a><br/>
- <a href="{@docRoot}downloads/brand/es-419_app_rgb_wo.ai">Español Latinoamérica (Spanish Latin America)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/slovak_app.ai">Slovenčina (Slovak)</a><br/>
-<!--
- <a href="{@docRoot}downloads/brand/sv_app_rgb_wo.ai">Svenska (Swedish)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/slovenian_app.ai">Slovenščina (Slovenian)</a><br/>
- <a href="{@docRoot}downloads/brand/sw_app_rgb_wo.ai">Kiswahili (Swahili)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/spanish_app.ai">Español (Spanish)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/v2/spanish_latam_app.ai">Español Latinoamérica (Spanish Latin America)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/v2/swahili_app.ai">Kiswahili (Swahili)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/v2/swedish_app.ai">Svenska (Swedish)</a><br/>
- <a href="{@docRoot}downloads/brand/th_app_rgb_wo.ai">ภาษาไทย (Thai)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/thai_app.ai">ภาษาไทย (Thai)</a><br/>
- <a href="{@docRoot}downloads/brand/tr_app_rgb_wo.ai">Türkçe (Turkish)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/turkish_app.ai">Türkçe (Turkish)</a><br/>
- <a href="{@docRoot}downloads/brand/uk_app_rgb_wo.ai">Українська (Ukrainian)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/ukranian_app.ai">Українська (Ukrainian)</a><br/>
- <a href="{@docRoot}downloads/brand/vi_app_rgb_wo.ai">Tiếng Việt (Vietnamese)</a><br/>
+ <a href="{@docRoot}downloads/brand/v2/vietnamese_app.ai">Tiếng Việt (Vietnamese)</a><br/>
- <a href="{@docRoot}downloads/brand/zu_app_rgb_wo.ai">isiZulu (Zulu)</a><br/>
--->
+ <a href="{@docRoot}downloads/brand/v2/zulu_app.ai">isiZulu (Zulu)</a><br/>
</div>
<div style="clear:left"> </div>
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index a77cdfb..11ae36a 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -27,21 +27,21 @@
-sdk.linux_download=android-sdk_r22.3-linux.tgz
-sdk.linux_bytes=100968558
-sdk.linux_checksum=6ae581a906d6420ad67176dff25a31cc
+sdk.linux_download=android-sdk_r22.6-linux.tgz
+sdk.linux_bytes=100992666
+sdk.linux_checksum=dde27b72715e52693c1ebc908742fc40
-sdk.mac_download=android-sdk_r22.3-macosx.zip
-sdk.mac_bytes=74893875
-sdk.mac_checksum=ecde88ca1f05955826697848fcb4a9e7
+sdk.mac_download=android-sdk_r22.6-macosx.zip
+sdk.mac_bytes=74547402
+sdk.mac_checksum=10c0e2ab65444c4911d69356ca2343f5
-sdk.win_download=android-sdk_r22.3-windows.zip
-sdk.win_bytes=108847452
-sdk.win_checksum=9f0fe8c8884d6aee2b298fee203c62dc
+sdk.win_download=android-sdk_r22.6-windows.zip
+sdk.win_bytes=108862292
+sdk.win_checksum=6faa487d328be352a456c53d9cbf0e3d
-sdk.win_installer=installer_r22.3-windows.exe
-sdk.win_installer_bytes=88845794
-sdk.win_installer_checksum=ad50c4dd9e23cee65a1ed740ff3345fa
+sdk.win_installer=installer_r22.6-windows.exe
+sdk.win_installer_bytes=88856450
+sdk.win_installer_checksum=6e5351b414bd554f3ac4c79f9dd4d213
@@ -363,8 +363,8 @@
<div class="col-6 reqs" style="margin:0 0 15px 20px;display:none;">
<h5>Eclipse IDE</h5>
<ul>
- <li><a href="http://eclipse.org/mobile/">Eclipse</a> 3.6.2 (Helios) or greater
-<p class="note"><strong>Note:</strong> Eclipse 3.5 (Galileo) is no longer
+ <li><a href="http://eclipse.org/mobile/">Eclipse</a> 3.7.2 (Indigo) or greater
+<p class="note"><strong>Note:</strong> Eclipse 3.6 (Helios) is no longer
supported with the latest version of ADT.</p></li>
<li>Eclipse <a href="http://www.eclipse.org/jdt">JDT</a> plugin (included
in most Eclipse IDE packages) </li>
diff --git a/docs/html/sdk/installing/installing-adt.jd b/docs/html/sdk/installing/installing-adt.jd
index 66c3034..42cb92c 100644
--- a/docs/html/sdk/installing/installing-adt.jd
+++ b/docs/html/sdk/installing/installing-adt.jd
@@ -1,8 +1,8 @@
page.title=Installing the Eclipse Plugin
-adt.zip.version=22.3.0
-adt.zip.download=ADT-22.3.0.zip
-adt.zip.bytes=14493723
-adt.zip.checksum=0189080b23dfa0f866adafaaafcc34ab
+adt.zip.version=22.6.0
+adt.zip.download=ADT-22.6.0.zip
+adt.zip.bytes=14585211
+adt.zip.checksum=d95c6d8e678881f6c89f063b58d4162f
@jd:body
diff --git a/docs/html/tools/revisions/build-tools.jd b/docs/html/tools/revisions/build-tools.jd
index 749808f..c3c83ef 100644
--- a/docs/html/tools/revisions/build-tools.jd
+++ b/docs/html/tools/revisions/build-tools.jd
@@ -77,6 +77,18 @@
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>Build Tools, Revision 19.0.3</a> <em>(March 2014)</em>
+ </p>
+ <div class="toggle-content-toggleme">
+
+ <p>Fixed an issue with RenderScript support.</p>
+
+ </div>
+</div>
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>Build Tools, Revision 19.0.2</a> <em>(February 2014)</em>
</p>
<div class="toggle-content-toggleme">
diff --git a/docs/html/tools/sdk/eclipse-adt.jd b/docs/html/tools/sdk/eclipse-adt.jd
index c584ae5..d711e44 100644
--- a/docs/html/tools/sdk/eclipse-adt.jd
+++ b/docs/html/tools/sdk/eclipse-adt.jd
@@ -53,10 +53,73 @@
<p>For a summary of all known issues in ADT, see <a
href="http://tools.android.com/knownissues">http://tools.android.com/knownissues</a>.</p>
-
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>ADT 22.6.0</a> <em>(March 2014)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+<dl>
+ <dt>Dependencies:</dt>
+
+ <dd>
+ <ul>
+ <li>Java 1.6 or higher is required.</li>
+ <li>Eclipse Indigo (Version 3.7.2) or higher is required.</li>
+ <li>This version of ADT is designed for use with
+ <a href="{@docRoot}tools/sdk/tools-notes.html">SDK Tools r22.6</a>.
+ If you haven't already installed SDK Tools r22.6 into your SDK, use the
+ Android SDK Manager to do so.</li>
+ </ul>
+ </dd>
+
+ <dt>General Notes:</dt>
+ <dd>
+ <ul>
+ <li><p>Added support for Java 7 language features like multi-catch, try-with-resources,
+ and the diamond operator. These features require version 19 or higher
+ of the Build Tools. Try-with-resources requires <code>minSdkVersion</code>
+ 19; the rest of the new language features require
+ <code>minSdkVersion</code> 8 or higher.</p>
+ <p>To use the new language features after installing ADT 22.6.0, ensure
+ that you run Eclipse on JDK 7 and change your application project settings
+ to use JDK 7.</p>
+ </li>
+ <li>Added new lint checks:
+ <ul>
+ <li>Security:
+ <ul>
+ <li>Look for code potentially affected by a <code>SecureRandom</code>
+ vulnerability.</li>
+ <li>Check that calls to <code>checkPermission</code> use the return
+ value.</li>
+ </ul>
+ </li>
+ <li>Check that production builds do not use mock location providers.</li>
+ </ul>
+ </li>
+ <li>Updated the New Project templates to include the
+ <a href="{@docRoot}tools/support-library/features.html#v7-appcompat">
+ v7 appcompat Support Library</a>.</li>
+ <li>Updated the Android tools libraries to include the rendering sandbox,
+ improvements for converting resource XML string declarations to layout
+ strings, and other updates.</li>
+ <li>Improved the Gradle export wizard. Note that the new importer in Android
+ Studio is the preferred way to migrate existing projects to Gradle.</li>
+ <li>Fixed a deadlock during startup.</li>
+ <li>Fixed an issue with RenderScript support. Using RenderScript support mode
+ now requires version 19.0.3 of the Build Tools.</li>
+ </ul>
+ </dd>
+
+</dl>
+</div>
+</div>
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
alt=""/>ADT 22.3.0</a> <em>(October 2013)</em>
</p>
diff --git a/docs/html/tools/sdk/ndk/index.jd b/docs/html/tools/sdk/ndk/index.jd
index 4e50d98..a22dc90 100644
--- a/docs/html/tools/sdk/ndk/index.jd
+++ b/docs/html/tools/sdk/ndk/index.jd
@@ -2,33 +2,33 @@
page.template=sdk
-ndk.mac64_download=android-ndk-r9c-darwin-x86_64.tar.bz2
-ndk.mac64_bytes=358350393
-ndk.mac64_checksum=154bc0248671b8609037218d3faa47f5
+ndk.mac64_download=android-ndk-r9d-darwin-x86_64.tar.bz2
+ndk.mac64_bytes=400339614
+ndk.mac64_checksum=c914164b1231c574dbe40debef7048be
-ndk.mac32_download=android-ndk-r9c-darwin-x86.tar.bz2
-ndk.mac32_bytes=352900444
-ndk.mac32_checksum=0ba391eb12d4eed6bd7dbff5d8804e0f
+ndk.mac32_download=android-ndk-r9d-darwin-x86.tar.bz2
+ndk.mac32_bytes=393866116
+ndk.mac32_checksum=ee6544bd8093c79ea08c2e3a6ffe3573
-ndk.linux64_download=android-ndk-r9c-linux-x86_64.tar.bz2
-ndk.linux64_bytes=371254928
-ndk.linux64_checksum=e9c3fd9881c811753bb57f701b3e05b1
+ndk.linux64_download=android-ndk-r9d-linux-x86_64.tar.bz2
+ndk.linux64_bytes=412879983
+ndk.linux64_checksum=c7c775ab3342965408d20fd18e71aa45
-ndk.linux32_download=android-ndk-r9c-linux-x86.tar.bz2
-ndk.linux32_bytes=365412557
-ndk.linux32_checksum=93d2aa9a40501b568037642cdb174643
+ndk.linux32_download=android-ndk-r9d-linux-x86.tar.bz2
+ndk.linux32_bytes=405218267
+ndk.linux32_checksum=6c1d7d99f55f0c17ecbcf81ba0eb201f
-ndk.win64_download=android-ndk-r9c-windows-x86_64.zip
-ndk.win64_bytes=483804820
-ndk.win64_checksum=9e84d0d59ce7d4a24370b619fb8799e4
+ndk.win64_download=android-ndk-r9d-windows-x86_64.zip
+ndk.win64_bytes=520997454
+ndk.win64_checksum=8cd244fc799d0e6e59d65a59a8692588
-ndk.win32_download=android-ndk-r9c-windows-x86.zip
-ndk.win32_bytes=460676475
-ndk.win32_checksum=863b5ab371b63c3e9bf0d39e47903763
+ndk.win32_download=android-ndk-r9d-windows-x86.zip
+ndk.win32_bytes=491440074
+ndk.win32_checksum=b16516b611841a075685a10c59d6d7a2
-ndk.debug_info_download=android-ndk-r9c-cxx-stl-libs-with-debugging-info.zip
-ndk.debug_info_bytes=100364569
-ndk.debug_info_checksum=37911716e1fd2fe3abb8a410750d73e6
+ndk.debug_info_download=android-ndk-r9d-cxx-stl-libs-with-debug-info.zip
+ndk.debug_info_bytes=104947363
+ndk.debug_info_checksum=906c8d88e0f02295c3bfe6b8e98a1a35
page.title=Android NDK
@@ -272,19 +272,84 @@
<p>
<a href="#" onclick="return toggleContent(this)"> <img
src="/assets/images/triangle-opened.png" class="toggle-content-img" alt=""
- >Android NDK, Revision 9c</a> <em>(December 2013)</em>
+ >Android NDK, Revision 9d</a> <em>(March 2014)</em>
</p>
<div class="toggle-content-toggleme">
-<p>This is a bug-fix-only release.</p>
+ <dl>
+ <dt>Important changes:</dt>
+ <dd>
+ <ul>
+ <li>Added support for the Clang 3.4 compiler. The
+<code>NDK_TOOLCHAIN_VERSION=clang</code> option now picks Clang 3.4. GCC 4.6 is
+still the default compiler.</li>
+ <li>Added <code>APP_ABI=armeabi-v7a-hard</code>, with
+additional multilib option <code>-mfloat-abi=hard</code>. These options are for
+use with ARM GCC 4.6/4.8 and clang 3.3/3.4 (which use 4.8's assembler, linker,
+and libs). When using these options, note the following changes:</li>
+ <ul>
+ <li> When executing the <code>ndk-build</code> script, add the
+following options for armeabi-v7a target:
+<pre>TARGET_CFLAGS += -mhard-float -D_NDK_MATH_NO_SOFTFP=1
+TARGET_LDFLAGS += -Wl,--no-warn-mismatch -lm_hard</pre>
+The built library is copied to <code>libs/armeabi-v7a</code>. For make to
+behave as expected, you cannot specify both <code>armeabi-v7a</code> and
+<code>armeabi-v7a-hard</code> as make targets (i.e., on the APP_ABI= line).
+Doing so causes one of them to be ignored. Note that <code>APP_ABI=all</code>
+is still equivalent to
+<code>armeabi armeabi-v7a x86 mips</code>.</li>
+ <li>The <code>make-standalone-toolchain.sh</code> script copies
+additional libaries under <code>/hard</code> directories.
+ Add the above <code>CFLAGS</code> and <code>LFLAGS</code> to your
+makefile to enable GCC or Clang to link with
+ libraries in <code>/hard</code>.</li>
+ </ul>
+ <li>Added the yasm assembler, as well as <code>LOCAL_ASMFLAGS</code>
+and <code>EXPORT_ASMFLAGS</code> flags for x86
+targets. The <code>ndk-build</code> script uses
+<code>prebuilts/*/bin/yasm*</code> to build <code>LOCAL_SRC_FILES</code> that
+have the <code>.asm</code> extension.</li>
+ <li>Updated MClinker to 2.6.0, which adds <code>-gc-sections</code>
+support.</li>
+ <li>Added experimental libc++ support (upstream r201101). Use this new
+feature by following these steps:
+ <ul>
+ <li>Add <code>APP_STL := c++_static</code> or <code>APP_STL :=
+c++_shared</code> in <code>Application.mk</code>.
+ You may rebuild from source via <code>LIBCXX_FORCE_REBUILD :=
+true</code></li>
+ <li>Execute <code>make-standalone-toolchain.sh --stl=libc++</code>
+to create a standalone toolchain with libc++ headers/lib.</li>
+ </ul>
+ For more information, see
+<code>CPLUSPLUS-SUPPORT.html</code>.
+(Issue <a href="b.android.com/36496">36496</a>)</li>
+ </ul>
+ </dd>
<dl>
<dt>Important bug fixes:</dt>
<dd>
<ul>
- <li>Fixed a problem with GCC 4.8 ARM, in which the stack pointer is restored too early. This problem prevented the frame pointer from reliably accessing a variable in the stack frame. For more information, see <a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58854">http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58854</a>.</li>
-<li>- Fixed a problem with GCC 4.8 libstdc++, in which a bug in std::nth_element was causing generation of code that produced a random segfault. For more information, see <a href="https://code.google.com/p/android/issues/detail?id=62910">https://code.google.com/p/android/issues/detail?id=62910</a>.</li>
- <li>Fixed GCC 4.8 ICE in cc1/cc1plus with <code>-fuse-ld=mcld</code>, so that the following error no longer occurs:
-<pre>cc1: internal compiler error: in common_handle_option, at opts.c:1774</pre></li>
- <li>Fixed <code>-mhard-float</code> support for <code>__builtin</code> math functions. For ongoing information on fixes for -mhard-float with STL, please follow <a href="http://b.android.com/61784">http://b.android.com/61784</a>.</li>
+ <li>Fixed an uncaught throw from an unexpected
+exception handler for GCC 4.6/4.8 ARM EABI. (GCC Issue <a
+href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59392">59392</a>)</li>
+ <li>Fixed GCC 4.8 so that it now correctly resolves partial
+specialization of a template with
+ a dependent, non-type template argument. (GCC Issue <a
+href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59052">59052</a>)</li>
+ <li>Added more modules to prebuilt python (Issue <a
+href="b.android.com/59902">59902</a>):
+ <ul>
+ <li>Mac OS X: <code>zlib</code>, <code>bz2</code>,
+<code>_curses</code>, <code>_curses_panel</code>, <code>_hashlib</code>,
+<code>_ssl</code></li>
+ <li>Linux: <code>zlib</code>, <code>nis</code>,
+<code>crypt</code>, <code>_curses</code>, and <code>_curses_panel</code></li>
+ </ul>
+ <li>Fixed the x86 and MIPS gdbserver
+<code>event_getmsg_helper</code>.</li>
+ <li>Fixed numerous issues in the RenderScript NDK toolchain, including
+issues with compatibility across older devices and C++ reflection.</li>
+<br>
</ul>
</dd>
@@ -293,33 +358,187 @@
<ul>
<li>Header fixes:
<ul>
- <li>Changed prototype of <code>poll</code> to <code>poll(struct pollfd *, nfds_t, int);</code> in <code>poll.h</code>.</li>
- <li>Added <code>utimensat</code> to <code>libc.so</code> in API levels 12 and 19. It is now present in levels 12-19.</li>
-<li>Introduced <code>futimens</code> into <code>libc.so</code>, as of API level 19.</li>
-<li>Added missing <code>clock_settime()</code> and <code>clock_nanosleep()</code> to <code>time.h</code> for API 8 and higher.</li>
-<li>Added <code>CLOCK_MONOTONIC_RAW, CLOCK_REALTIME_COARSE, CLOCK_MONOTONIC_COARSE, CLOCK_BOOTTIME, CLOCK_REALTIME_ALARM,</code> and <code>CLOCK_BOOTTIME_ALARM</code> in <code>time.h.</code></li>
-<li>Removed obsolete <code>CLOCK_REALTIME_HR</code> and <code>CLOCK_MONOTONIC_HR.</code></li>
+ <li>Fixed a missing <code>#include <sys/types.h></code> in
+<code>android/asset_manager.h</code> for Android API level 13 and higher.
+ (Issue <a href="http://b.android.com/64988">64988</a>)</li>
+ <li>Fixed a missing <code>#include <stdint.h></code> in
+<code>android/rect_manager.h</code> for Android API level 14 and higher.</li>
+ <li>Added <code>JNICALL</code> to <code>JNI_OnLoad</code> and
+<code>JNI_OnUnload</code> in <code>jni.h</code>. Note that <code>JNICALL</code>
+ is defined as <code>__NDK_FPABI__</code> For more information, see
+<code>sys/cdefs.h</code>.</li>
+ <li>Updated the following headers so that they can be included
+without the need to
+manually include their dependencies (Issue <a
+href="http://b.android.com/64679">64679</a>):</li>
+<pre>
+android/tts.h
+EGL/eglext.h
+fts.h
+GLES/glext.h
+GLES2/gl2ext.h
+OMXAL/OpenMAXSL_Android.h
+SLES/OpenSLES_Android.h
+sys/prctl.h
+sys/utime.h
+</pre>
+ <li>Added <code>sys/cachectl.h</code> for all architectures. MIPS
+developers can now include this header instead of writing <code>#ifdef
+__mips__</code>.</li>
+ <li></code>Fixed <code>platforms/android-18/include/android/input.h
+</code> by adding <code>__NDK_FPABI__</code> to functions taking or returning
+float or double values.</li>
+ <li>Fixed MIPS <code>struct stat</code>, which was incorrectly set
+to its 64-bit counterpart for Android API level 12 and later. This wrong
+setting was a
+regression introduced in release r9c.</li>
+ <li>Defined <code>__PTHREAD_MUTEX_INIT_VALUE</code>,
+<code>__PTHREAD_RECURSIVE_MUTEX_INIT_VALUE</code>,
+ and <code>__PTHREAD_ERRORCHECK_MUTEX_INIT_VALUE</code> for Android API
+level 9 and lower.</li>
+ <li>Added <code>scalbln</code>, <code>scalblnf</code>, and
+<code>scalblnl</code> to x86 <code>libm.so</code> for APIs 18 and later.</li>
+ <li>Fixed a typo in
+<code>sources/android/support/include/iconv.h</code>.
+ (Issue <a href="http://b.android.com/63806">63806</a>)</li>
+
</ul>
</li>
- <li>Refactored samples Teapot, MoreTeapots, and <code>source/android/ndk_helper</code> as follows:
+ <li>Fixed gabi++ <code>std::unexpected()</code> to call
+<code>std::terminate()</code> so that
+ a user-defined <code>std::terminate()</code> handler has a chance to run.
+</li>
+ <li>Fixed gabi++ to catch <code>std::nullptr</code>.</li>
+ <li>Fixed samples Teapot and MoreTeapots:
<ul>
-<li>They now use a hard-float abi for armeabi-v7a.</li>
-<li>Android-19 now has immersive mode.</li>
-<li>Fixed a problem with <code>Check_ReleaseStringUTFChars</code> in <code>/system/lib/libdvm.so</code> that was causing crashes on x86 devices.</li>
+ <li>Solved a problem with Tegra 2 and 3 chips by changing specular
+variables to use medium precision. Values for specular power can now be less
+than 1.0. </li>
+ <li>Changed the samples so that pressing the volume button restores
+immersive mode and invalidates
+<code>SYSTEM_UI_FLAG_IMMERSIVE_STICKY</code>. Screen rotation does not
+trigger <code>onSystemUiVisibilityChange</code>, and so does not restore
+immersive mode.</li>
</ul>
</li>
-<li>Fixed ndk-build fails that happen in cygwin when the NDK package is referenced via symlink.</li>
-<li>Fixed ndk-build.cmd fails that happen in windows <code>cmd.exe</code> when <code>LOCAL_SRC_FILES</code> contains absolute paths. See <a href="https://android-review.googlesource.com/#/c/69992">https://android-review.googlesource.com/#/c/69992.</a></li>
-<li>Fixed ndk-stack to proceed even when it can't parse a frame due to inability to find a routine, filename, or line number. In any of those cases, it prints "??".</li>
-<li>Fixed ndk-stack windows-x64_64 so that it no longer erroneously matches a frame line with a line in the <code>stack:</code>
- section that doesn't contain <code>pc</code>, <code>eip</code>, or <code>ip</code>. For example:
-<pre>I/DEBUG ( 1151): #00 5f09db68 401f01c4 /system/lib/libc.so</pre></li>
+ <li>Fixed the <code>ndk-build</code> script to add
+<code>-rpath-link=$SYSROOT/usr/lib</code> and
+<code>-rpath-link=$TARGET_OUT</code> in order to use <code>ld.bfd</code> to
+link executables. (Issue <a href="http://b.android.com/64266">64266</a>)</li>
+ <li>Removed <code>-Bsymbolic</code> from all STL builds.</li>
+ <li>Fixed <code>ndk-gdb-py.cmd</code> by setting <code>SHELL</code> as
+an environment variable
+instead of passing it to
+ <code>python.exe</code>, which ignores the setting.
+ (Issue <a href="http://b.android.com/63054">63054</a>)</li>
+ <li>Fixed the <code>make-standalone-toolchain.sh</code> script so that
+the <code>--stl=stlport</code> option copies the gabi++ headers instead of
+symlinking them; the <code>cmd.exe</code> and MinGW shells do not understand
+symlinks created by cygwin.</li>
+ </ul>
+ </dd>
+
+ <dt>Other changes:</dt>
+ <dd>
+ <ul>
+ <li>Applied execution permissions to all <code>*cmd</code> scripts
+previously intended for use only in the <code>cmd.exe</code> shell, in case
+developers prefer to use <code>ndk-build.cmd</code> in cygwin instead of the
+recommended <code>ndk-build</code> script.</li>
+ <li>Improved the speed of the <code>make-standalone-toolchain.sh</code>
+script by moving instead of copying if the specified destination directory does
+not exist.</li>
+ </dd>
+ </ul>
+ </dl>
+ </div>
+</div>
+
+<div class="toggle-content closed">
+ <p>
+ <a href="#" onclick="return toggleContent(this)"> <img
+ src="/assets/images/triangle-closed.png" class="toggle-content-img" alt=""
+ >Android NDK, Revision 9c</a> <em>(December 2013)</em>
+ </p>
+ <div class="toggle-content-toggleme">
+<p>This is a bug-fix-only release.</p>
+ <dl>
+ <dt>Important bug fixes:</dt>
+ <dd>
+ <ul>
+ <li>Fixed a problem with GCC 4.8 ARM, in which the stack pointer is
+restored too early. This problem prevented the frame pointer from reliably
+accessing a variable in the stack frame. (GCC Issue <a
+href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58854">58854</a>)</li>
+<li>Fixed a problem with GCC 4.8 libstdc++, in which a bug in
+std::nth_element was causing generation of code that produced a random
+segfault. (Issue <a
+href="https://code.google.com/p/android/issues/detail?id=62910">62910</a>)</li>
+ <li>Fixed GCC 4.8 ICE in cc1/cc1plus with
+<code>-fuse-ld=mcld</code>, so that the following error no longer occurs:
+<pre>cc1: internal compiler error: in common_handle_option, at
+opts.c:1774</pre></li>
+ <li>Fixed <code>-mhard-float</code> support for
+<code>__builtin</code> math functions. For ongoing information on fixes for
+<code>-mhard-float</code> with STL, please follow Issue <a
+href="http://b.android.com/61784">61784</a>.</li>
+ </ul>
+ </dd>
+
+ <dt>Other bug fixes:</dt>
+ <dd>
+ <ul>
+ <li>Header fixes:
+ <ul>
+ <li>Changed prototype of <code>poll</code> to <code>poll(struct
+pollfd *, nfds_t, int);</code> in <code>poll.h</code>.</li>
+ <li>Added <code>utimensat</code> to <code>libc.so</code> for Android
+API levels 12 and 19. These libraries are now included for all Android API
+levels 12 through 19.</li>
+<li>Introduced <code>futimens</code> into <code>libc.so</code>, for Android API
+level 19.</li>
+<li>Added missing <code>clock_settime()</code> and
+<code>clock_nanosleep()</code> to <code>time.h</code> for Android API level 8
+and higher.</li>
+<li>Added <code>CLOCK_MONOTONIC_RAW, CLOCK_REALTIME_COARSE,
+CLOCK_MONOTONIC_COARSE, CLOCK_BOOTTIME, CLOCK_REALTIME_ALARM,</code> and
+<code>CLOCK_BOOTTIME_ALARM</code> in <code>time.h.</code></li>
+<li>Removed obsolete <code>CLOCK_REALTIME_HR</code> and
+<code>CLOCK_MONOTONIC_HR.</code></li>
+ </ul>
+ </li>
+ <li>In samples Teapot, MoreTeapots, and
+<code>source/android/ndk_helper</code>:
+ <ul>
+<li>Changed them so that they now use a hard-float abi for armeabi-v7a.</li>
+<li>Updated them to use immersive mode on Android API level 19 and
+higher.</li>
+<li>Fixed a problem with <code>Check_ReleaseStringUTFChars</code> in
+<code>/system/lib/libdvm.so</code> that was causing crashes on x86 devices.</li>
+ </ul>
+ </li>
+<li>Fixed <code>ndk-build</code> fails that happen in cygwin when the NDK
+package is
+referenced via symlink.</li>
+<li>Fixed <code>ndk-build.cmd</code> fails that happen in windows
+<code>cmd.exe</code> when
+<code>LOCAL_SRC_FILES</code> contains absolute paths. (Issue <a
+href="https://android-review.googlesource.com/#/c/69992">69992</a>)</li>
+<li>Fixed the <code>ndk-stack</code> script to proceed even when it can't parse
+a frame due to inability to find a routine, filename, or line number. In any of
+these cases, it prints <code>??</code>.</li>
+<li>Fixed the <code>ndk-stack</code> stack for windows-x64_64 targets so that
+it no longer erroneously matches a frame line with a line in the
+<code>stack:</code> section that doesn't contain <code>pc</code>,
+<code>eip</code>, or <code>ip</code>. For example:
+<pre>I/DEBUG ( 1151): #00 5f09db68 401f01c4
+/system/lib/libc.so</pre></li>
<li>Fixed gabi++ so that it:
<ul>
<li>Does not use malloc() to allocate C++ thread-local
objects.</li>
- <li>Avoids deadlocks in gabi++ in cases where libc.debug.malloc is non-zero in
- userdebug/eng Android platform builds.</li>
+ <li>Avoids deadlocks in gabi++ in cases where libc.debug.malloc is
+non-zero in userdebug/eng Android platform builds.</li>
</ul>
</ul>
</dd>
@@ -328,12 +547,29 @@
<dd>
<ul>
<li>Added <code>LOCAL_EXPORT_LDFLAGS</code>.</li>
-<li>Introduced the <code>NDK_PROJECT_PATH=null</code> setting for use in an integrated build system where options are explicitly passed to <code>ndk-build</code>. With this setting, <code>ndk-build</code> makes no attempt to look for <code>NDK_PROJECT_PATH.</code> This setting also prevents variables from deriving default settings from NDK_PROJECT_PATH. As a result, the following variables must now be explicitly specified (with their default values if such exist): <code>NDK_OUT, NDK_LIBS_OUT, APP_BUILD_SCRIPT, NDK_DEBUG</code> (optional, default to 0), and other <code>APP_*</code>'s contained in <code>Application.mk</code>.</li>
-<li><code>APP_ABI</code> can now be enumerated in a comma-delimited list. For example:
+<li>Introduced the <code>NDK_PROJECT_PATH=null</code> setting for use in an
+integrated build system where options are explicitly passed to
+<code>ndk-build</code>. With this setting, <code>ndk-build</code> makes no
+attempt to look for <code>NDK_PROJECT_PATH.</code> This setting also prevents
+variables from deriving default settings from NDK_PROJECT_PATH. As a result,
+the following variables must now be explicitly specified (with their default
+values if such exist): <code>NDK_OUT, NDK_LIBS_OUT, APP_BUILD_SCRIPT,
+NDK_DEBUG</code> (optional, default to 0), and other <code>APP_*</code>'s
+contained in <code>Application.mk</code>.</li>
+<li><code>APP_ABI</code> can now be enumerated in a comma-delimited list. For
+example:
<pre>APP_ABI := "armeabi,armeabi-v7a"</pre></li>
-<li>Provided the ability (option <code>-g</code>) to rebuild all of STL with debugging info in an optional, separate package called <code>android-ndk-r9c-cxx-stl-libs-with-debugging-info.zip</code>. This option helps ndk-stack to provide better a stack dump across STL. This change should not affect the code/size of the final, stripped file.</li>
-<li>Enhanced <code>hello-jni</code> samples to report <code>APP_ABI</code> at compilation.</li>
-<li>Used the <code>ar</code> tool in Deterministic mode (option <code>-D</code>) to build static libraries. For more information, see <a href="http://b.android.com/60705">http://b.android.com/60705</a>.</li>
+<li>Provided the ability to rebuild all of STL with debugging info in an
+optional, separate package called
+<code>android-ndk-r9c-cxx-stl-libs-with-debugging-info.zip</code>, using the
+<code>-g</code> option. This option
+helps the <code>ndk-stack</code> script provide better a stack dump across STL.
+This change should not affect the code/size of the final, stripped file.</li>
+<li>Enhanced <code>hello-jni</code> samples to report <code>APP_ABI</code> at
+compilation.</li>
+<li>Used the <code>ar</code> tool in Deterministic mode (option
+<code>-D</code>) to build static libraries. (Issue <a
+href="http://b.android.com/60705">60705</a>)</li>
</ul>
</dd>
@@ -360,7 +596,7 @@
(Issues <a href="http://b.android.com/47150">47150</a>,
<a href="http://b.android.com/58528">58528</a>, and
<a href="http://b.android.com/38423">38423</a>)</li>
- <li>Added support for API level 19, including Renderscript binding.</li>
+ <li>Added support for Android API level 19, including Renderscript binding.</li>
<li>Added support for <code>-mhard-float</code> in the existing armeabi-v7a ABI. For more
information and current restrictions on Clang, see
{@code tests/device/hard-float/jni/Android.mk}.</li>
@@ -2392,8 +2628,8 @@
dealing with signed chars.</li>
<li>Adds missing documentation for the
"gnustl_static" value for APP_STL, that allows you to link against
- a static library version of GNU libstdc++. </li>
- <li>The following <code>ndk-build</code> issues are fixed:
+ a static library version of GNU libstdc++. </li> the
+ <li>Fixed the following <code>ndk-build</code> issues:
<ul>
<li>A bug that created inconsistent dependency files when a
compilation error occured on Windows. This prevented a proper build after
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index c28b946..99f0b38 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -26,10 +26,92 @@
href="http://tools.android.com/knownissues">http://tools.android.com/knownissues</a>.</p>
-
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>SDK Tools, Revision 22.6</a> <em>(March 2014)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+
+ <dl>
+ <dt>Dependencies:</dt>
+ <dd>
+ <ul>
+ <li>Android SDK Platform-tools revision 18 or later.</li>
+ <li>If you are developing in Eclipse with ADT, note that this version of SDK Tools is
+ designed for use with ADT 22.6.0 and later. If you haven't already, update your
+ <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> to 22.6.0.</li>
+ <li>If you are developing outside Eclipse, you must have
+ <a href="http://ant.apache.org/">Apache Ant</a> 1.8 or later.</li>
+ </ul>
+ </dd>
+
+ <dt>General Notes:</dt>
+ <dd>
+ <ul>
+ <li><p>The command line <code>lint</code> script (<code>tools\lint.bat</code> on
+ Windows platforms, <code>tools/lint</code> on other platforms) and the
+ <code>lint</code> target on <code>ant</code> builds fail with the following
+ error:</p>
+ <p><code>Exception in thread "main" java.lang.NoClassDefFoundError:
+ lombok/ast/AstVisitor</code></p>
+ <p>As a temporary workaround, rename the file
+ <code>tools\lib\lombok-ast-0.2.2.jar</code> to
+ <code>tools\lib\lombok-ast.jar</code>.
+ We will release an updated version of the tools with a fix for
+ this issue as soon as possible.</p>
+ </li>
+ <li>Added support for Java 7 language features like multi-catch, try-with-resources,
+ and the diamond operator. These features require version 19 or higher
+ of the Build Tools. Try-with-resources requires <code>minSdkVersion</code>
+ 19; the rest of the new language features require
+ <code>minSdkVersion</code> 8 or higher.</li>
+ <li>Added new lint checks:
+ <ul>
+ <li>Security:
+ <ul>
+ <li>Look for code potentially affected by a <code>SecureRandom</code>
+ vulnerability.</li>
+ <li>Check that calls to <code>checkPermission</code> use the return value.</li>
+ </ul>
+ </li>
+ <li>Check that production builds do not use mock location providers.</li>
+ <li>Look for manifest values that are overwritten by values from Gradle build
+ scripts.</li>
+ </ul>
+ </li>
+ <li>Fixed a number of minor issues in the SDK and build system.</li>
+ <li>Emulator:
+ <ul>
+ <li>Fixed a problem with the emulator shutting down immediately for Android 1.5
+ on the Nexus One and Nexus S devices.
+ (<a href="http://b.android.com/64945">Issue 64945</a>)</li>
+ <li>Fixed a problem with port numbers longer than four digits.
+ (<a href="http://b.android.com/60024">Issue 60024</a>)</li>
+ <li>Fixed battery errors for the Nexus One and Nexus S devices.
+ (<a href="http://b.android.com/39959">Issue 39959</a>)</li>
+ <li>Fixed a problem with paths or arguments that contain
+ spaces on Windows platforms.
+ (<a href="http://b.android.com/18317">Issue 18317</a>)</li>
+ <li>Fixed a problem with long path values on Windows platforms.
+ (<a href="http://b.android.com/33336">Issue 33336</a>)</li>
+ <li>Fixed a problem with the {@code -snapshot-list} command line
+ option on 64-bit systems.
+ (<a href="http://b.android.com/34233">Issue 34233</a>)</li>
+ </ul>
+ </li>
+ <li>Fixed an issue with RenderScript support. Using RenderScript support mode
+ now requires version 19.0.3 of the Build Tools.</li>
+ </ul>
+ </dd>
+ </dl>
+ </div>
+</div>
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>SDK Tools, Revision 22.3</a> <em>(October 2013)</em>
</p>
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index 6dbb3cd..910b24c 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -404,7 +404,7 @@
* @throws IllegalArgumentException
*/
public boolean setSynchronizationMode(int sync) throws IllegalArgumentException {
- if ((sync != POSITION_SYNCHRONIZATION_NONE) || (sync != POSITION_SYNCHRONIZATION_CHECK)) {
+ if ((sync != POSITION_SYNCHRONIZATION_NONE) && (sync != POSITION_SYNCHRONIZATION_CHECK)) {
throw new IllegalArgumentException("Unknown synchronization mode " + sync);
}
if (!mIsRegistered) {
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 63a61e2..685bbcc 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -37,11 +37,11 @@
libcamera_client \
libmtp \
libusbhost \
- libexif \
+ libjhead \
libstagefright_amrnb_common \
LOCAL_REQUIRED_MODULES := \
- libexif_jni
+ libjhead_jni
LOCAL_STATIC_LIBRARIES := \
libstagefright_amrnbenc
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index cb17ac6..eb63a54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -37,6 +37,8 @@
private static final boolean DEBUG = false;
private static final boolean DEBUG_COLORS = false;
+ public static final boolean HIGH_END = ActivityManager.isHighEndGfx();
+
public static final int MODE_OPAQUE = 0;
public static final int MODE_SEMI_TRANSPARENT = 1;
public static final int MODE_TRANSLUCENT = 2;
@@ -48,7 +50,6 @@
private final String mTag;
private final View mView;
- private final boolean mSupportsTransitions = ActivityManager.isHighEndGfx();
private final BarBackgroundDrawable mBarBackground;
private int mMode;
@@ -57,7 +58,7 @@
mTag = "BarTransitions." + view.getClass().getSimpleName();
mView = view;
mBarBackground = new BarBackgroundDrawable(mView.getContext(), gradientResourceId);
- if (mSupportsTransitions) {
+ if (HIGH_END) {
mView.setBackground(mBarBackground);
}
}
@@ -67,18 +68,22 @@
}
public void transitionTo(int mode, boolean animate) {
+ // low-end devices do not support translucent modes, fallback to opaque
+ if (!HIGH_END && (mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSLUCENT)) {
+ mode = MODE_OPAQUE;
+ }
if (mMode == mode) return;
int oldMode = mMode;
mMode = mode;
if (DEBUG) Log.d(mTag, String.format("%s -> %s animate=%s",
modeToString(oldMode), modeToString(mode), animate));
- if (mSupportsTransitions) {
- onTransition(oldMode, mMode, animate);
- }
+ onTransition(oldMode, mMode, animate);
}
protected void onTransition(int oldMode, int newMode, boolean animate) {
- applyModeBackground(oldMode, newMode, animate);
+ if (HIGH_END) {
+ applyModeBackground(oldMode, newMode, animate);
+ }
}
protected void applyModeBackground(int oldMode, int newMode, boolean animate) {
diff --git a/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java b/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java
index 3e57a77..b734c41 100644
--- a/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java
+++ b/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java
@@ -178,6 +178,7 @@
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
,
PixelFormat.TRANSLUCENT);
+ lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
lp.setTitle("ImmersiveModeConfirmation");
lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications;
lp.gravity = Gravity.FILL;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 44fc1f8..7c047c3 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -38,6 +38,7 @@
import com.android.internal.widget.ActionBarContextView;
import com.android.internal.widget.ActionBarOverlayLayout;
import com.android.internal.widget.ActionBarView;
+import com.android.internal.widget.SwipeDismissLayout;
import android.app.KeyguardManager;
import android.content.Context;
@@ -267,6 +268,15 @@
// Remove the action bar feature if we have no title. No title dominates.
removeFeature(FEATURE_ACTION_BAR);
}
+
+ if ((features & (1 << FEATURE_ACTION_BAR)) != 0 && featureId == FEATURE_SWIPE_TO_DISMISS) {
+ throw new AndroidRuntimeException(
+ "You cannot combine swipe dismissal and the action bar.");
+ }
+ if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0 && featureId == FEATURE_ACTION_BAR) {
+ throw new AndroidRuntimeException(
+ "You cannot combine swipe dismissal and the action bar.");
+ }
return super.requestFeature(featureId);
}
@@ -2838,6 +2848,10 @@
requestFeature(FEATURE_ACTION_MODE_OVERLAY);
}
+ if (a.getBoolean(com.android.internal.R.styleable.Window_windowSwipeToDismiss, false)) {
+ requestFeature(FEATURE_SWIPE_TO_DISMISS);
+ }
+
if (a.getBoolean(com.android.internal.R.styleable.Window_windowFullscreen, false)) {
setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN & (~getForcedWindowFlags()));
}
@@ -2964,7 +2978,9 @@
int layoutResource;
int features = getLocalFeatures();
// System.out.println("Features: 0x" + Integer.toHexString(features));
- if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
+ if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
+ layoutResource = com.android.internal.R.layout.screen_swipe_dismiss;
+ } else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
@@ -3034,6 +3050,10 @@
}
}
+ if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
+ registerSwipeCallbacks();
+ }
+
// Remaining setup -- of background and title -- that only applies
// to top-level windows.
if (getContainer() == null) {
@@ -3390,6 +3410,53 @@
return (mRightIconView = (ImageView)findViewById(com.android.internal.R.id.right_icon));
}
+ private void registerSwipeCallbacks() {
+ SwipeDismissLayout swipeDismiss =
+ (SwipeDismissLayout) findViewById(com.android.internal.R.id.content);
+ swipeDismiss.setOnDismissedListener(new SwipeDismissLayout.OnDismissedListener() {
+ @Override
+ public void onDismissed(SwipeDismissLayout layout) {
+ Callback cb = getCallback();
+ if (cb != null) {
+ try {
+ cb.onWindowDismissed();
+ } catch (AbstractMethodError e) {
+ Log.e(TAG, "onWindowDismissed not implemented in " +
+ cb.getClass().getSimpleName(), e);
+ }
+ }
+ }
+ });
+ swipeDismiss.setOnSwipeProgressChangedListener(
+ new SwipeDismissLayout.OnSwipeProgressChangedListener() {
+ private boolean mIsTranslucent = false;
+
+ @Override
+ public void onSwipeProgressChanged(
+ SwipeDismissLayout layout, float progress, float translate) {
+ WindowManager.LayoutParams newParams = getAttributes();
+ newParams.x = (int) translate;
+ setAttributes(newParams);
+
+ int flags = 0;
+ if (newParams.x == 0) {
+ flags = FLAG_FULLSCREEN;
+ } else {
+ flags = FLAG_LAYOUT_NO_LIMITS;
+ }
+ setFlags(flags, FLAG_FULLSCREEN | FLAG_LAYOUT_NO_LIMITS);
+ }
+
+ @Override
+ public void onSwipeCancelled(SwipeDismissLayout layout) {
+ WindowManager.LayoutParams newParams = getAttributes();
+ newParams.x = 0;
+ setAttributes(newParams);
+ setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN | FLAG_LAYOUT_NO_LIMITS);
+ }
+ });
+ }
+
/**
* Helper method for calling the {@link Callback#onPanelClosed(int, Menu)}
* callback. This method will grab whatever extra state is needed for the
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 16c3739..08a0dff7 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -3277,8 +3277,9 @@
+ mRestrictedScreenWidth;
pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
+ mRestrictedScreenHeight;
- } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) {
- // Toasts are stable to interim decor changes.
+ } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT
+ || attrs.type == TYPE_VOLUME_OVERLAY) {
+ // These dialogs are stable to interim decor changes.
pf.left = df.left = of.left = cf.left = mStableLeft;
pf.top = df.top = of.top = cf.top = mStableTop;
pf.right = df.right = of.right = cf.right = mStableRight;
@@ -3383,13 +3384,10 @@
WindowManager.LayoutParams attrs) {
if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
+ win.isVisibleOrBehindKeyguardLw());
- if (mTopFullscreenOpaqueWindowState == null && (win.getAttrs().privateFlags
- &WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_NAV_BAR) != 0
- || (win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD)) {
- if (mForcingShowNavBarLayer < 0) {
- mForcingShowNavBar = true;
- mForcingShowNavBarLayer = win.getSurfaceLayer();
- }
+ if (mTopFullscreenOpaqueWindowState == null
+ && win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) {
+ mForcingShowNavBar = true;
+ mForcingShowNavBarLayer = win.getSurfaceLayer();
}
if (mTopFullscreenOpaqueWindowState == null &&
win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index ca2f7b1..277fbac 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -82,7 +82,6 @@
import com.android.internal.backup.BackupConstants;
import com.android.internal.backup.IBackupTransport;
import com.android.internal.backup.IObbBackupService;
-import com.android.internal.backup.LocalTransport;
import com.android.server.EventLogTags;
import com.android.server.SystemService;
import com.android.server.backup.PackageManagerBackupAgent.Metadata;
@@ -143,11 +142,16 @@
private static final boolean DEBUG = true;
private static final boolean MORE_DEBUG = false;
+ // Historical and current algorithm names
+ static final String PBKDF_CURRENT = "PBKDF2WithHmacSHA1";
+ static final String PBKDF_FALLBACK = "PBKDF2WithHmacSHA1And8bit";
+
// Name and current contents version of the full-backup manifest file
static final String BACKUP_MANIFEST_FILENAME = "_manifest";
static final int BACKUP_MANIFEST_VERSION = 1;
static final String BACKUP_FILE_HEADER_MAGIC = "ANDROID BACKUP\n";
- static final int BACKUP_FILE_VERSION = 1;
+ static final int BACKUP_FILE_VERSION = 2;
+ static final int BACKUP_PW_FILE_VERSION = 2;
static final boolean COMPRESS_FULL_BACKUPS = true; // should be true in production
static final String SHARED_BACKUP_AGENT_PACKAGE = "com.android.sharedstoragebackup";
@@ -467,6 +471,8 @@
private final SecureRandom mRng = new SecureRandom();
private String mPasswordHash;
private File mPasswordHashFile;
+ private int mPasswordVersion;
+ private File mPasswordVersionFile;
private byte[] mPasswordSalt;
// Configuration of PBKDF2 that we use for generating pw hashes and intermediate keys
@@ -827,6 +833,27 @@
}
mDataDir = Environment.getDownloadCacheDirectory();
+ mPasswordVersion = 1; // unless we hear otherwise
+ mPasswordVersionFile = new File(mBaseStateDir, "pwversion");
+ if (mPasswordVersionFile.exists()) {
+ FileInputStream fin = null;
+ DataInputStream in = null;
+ try {
+ fin = new FileInputStream(mPasswordVersionFile);
+ in = new DataInputStream(fin);
+ mPasswordVersion = in.readInt();
+ } catch (IOException e) {
+ Slog.e(TAG, "Unable to read backup pw version");
+ } finally {
+ try {
+ if (in != null) in.close();
+ if (fin != null) fin.close();
+ } catch (IOException e) {
+ Slog.w(TAG, "Error closing pw version files");
+ }
+ }
+ }
+
mPasswordHashFile = new File(mBaseStateDir, "pwhash");
if (mPasswordHashFile.exists()) {
FileInputStream fin = null;
@@ -1127,13 +1154,13 @@
}
}
- private SecretKey buildPasswordKey(String pw, byte[] salt, int rounds) {
- return buildCharArrayKey(pw.toCharArray(), salt, rounds);
+ private SecretKey buildPasswordKey(String algorithm, String pw, byte[] salt, int rounds) {
+ return buildCharArrayKey(algorithm, pw.toCharArray(), salt, rounds);
}
- private SecretKey buildCharArrayKey(char[] pwArray, byte[] salt, int rounds) {
+ private SecretKey buildCharArrayKey(String algorithm, char[] pwArray, byte[] salt, int rounds) {
try {
- SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
+ SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);
KeySpec ks = new PBEKeySpec(pwArray, salt, rounds, PBKDF2_KEY_SIZE);
return keyFactory.generateSecret(ks);
} catch (InvalidKeySpecException e) {
@@ -1144,8 +1171,8 @@
return null;
}
- private String buildPasswordHash(String pw, byte[] salt, int rounds) {
- SecretKey key = buildPasswordKey(pw, salt, rounds);
+ private String buildPasswordHash(String algorithm, String pw, byte[] salt, int rounds) {
+ SecretKey key = buildPasswordKey(algorithm, pw, salt, rounds);
if (key != null) {
return byteArrayToHex(key.getEncoded());
}
@@ -1173,13 +1200,13 @@
return result;
}
- private byte[] makeKeyChecksum(byte[] pwBytes, byte[] salt, int rounds) {
+ private byte[] makeKeyChecksum(String algorithm, byte[] pwBytes, byte[] salt, int rounds) {
char[] mkAsChar = new char[pwBytes.length];
for (int i = 0; i < pwBytes.length; i++) {
mkAsChar[i] = (char) pwBytes[i];
}
- Key checksum = buildCharArrayKey(mkAsChar, salt, rounds);
+ Key checksum = buildCharArrayKey(algorithm, mkAsChar, salt, rounds);
return checksum.getEncoded();
}
@@ -1191,7 +1218,7 @@
}
// Backup password management
- boolean passwordMatchesSaved(String candidatePw, int rounds) {
+ boolean passwordMatchesSaved(String algorithm, String candidatePw, int rounds) {
// First, on an encrypted device we require matching the device pw
final boolean isEncrypted;
try {
@@ -1235,7 +1262,7 @@
} else {
// hash the stated current pw and compare to the stored one
if (candidatePw != null && candidatePw.length() > 0) {
- String currentPwHash = buildPasswordHash(candidatePw, mPasswordSalt, rounds);
+ String currentPwHash = buildPasswordHash(algorithm, candidatePw, mPasswordSalt, rounds);
if (mPasswordHash.equalsIgnoreCase(currentPwHash)) {
// candidate hash matches the stored hash -- the password matches
return true;
@@ -1250,11 +1277,37 @@
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"setBackupPassword");
- // If the supplied pw doesn't hash to the the saved one, fail
- if (!passwordMatchesSaved(currentPw, PBKDF2_HASH_ROUNDS)) {
+ // When processing v1 passwords we may need to try two different PBKDF2 checksum regimes
+ final boolean pbkdf2Fallback = (mPasswordVersion < BACKUP_PW_FILE_VERSION);
+
+ // If the supplied pw doesn't hash to the the saved one, fail. The password
+ // might be caught in the legacy crypto mismatch; verify that too.
+ if (!passwordMatchesSaved(PBKDF_CURRENT, currentPw, PBKDF2_HASH_ROUNDS)
+ && !(pbkdf2Fallback && passwordMatchesSaved(PBKDF_FALLBACK,
+ currentPw, PBKDF2_HASH_ROUNDS))) {
return false;
}
+ // Snap up to current on the pw file version
+ mPasswordVersion = BACKUP_PW_FILE_VERSION;
+ FileOutputStream pwFout = null;
+ DataOutputStream pwOut = null;
+ try {
+ pwFout = new FileOutputStream(mPasswordVersionFile);
+ pwOut = new DataOutputStream(pwFout);
+ pwOut.writeInt(mPasswordVersion);
+ } catch (IOException e) {
+ Slog.e(TAG, "Unable to write backup pw version; password not changed");
+ return false;
+ } finally {
+ try {
+ if (pwOut != null) pwOut.close();
+ if (pwFout != null) pwFout.close();
+ } catch (IOException e) {
+ Slog.w(TAG, "Unable to close pw version record");
+ }
+ }
+
// Clearing the password is okay
if (newPw == null || newPw.isEmpty()) {
if (mPasswordHashFile.exists()) {
@@ -1272,7 +1325,7 @@
try {
// Okay, build the hash of the new backup password
byte[] salt = randomBytes(PBKDF2_SALT_SIZE);
- String newPwHash = buildPasswordHash(newPw, salt, PBKDF2_HASH_ROUNDS);
+ String newPwHash = buildPasswordHash(PBKDF_CURRENT, newPw, salt, PBKDF2_HASH_ROUNDS);
OutputStream pwf = null, buffer = null;
DataOutputStream out = null;
@@ -1315,6 +1368,19 @@
}
}
+ private boolean backupPasswordMatches(String currentPw) {
+ if (hasBackupPassword()) {
+ final boolean pbkdf2Fallback = (mPasswordVersion < BACKUP_PW_FILE_VERSION);
+ if (!passwordMatchesSaved(PBKDF_CURRENT, currentPw, PBKDF2_HASH_ROUNDS)
+ && !(pbkdf2Fallback && passwordMatchesSaved(PBKDF_FALLBACK,
+ currentPw, PBKDF2_HASH_ROUNDS))) {
+ if (DEBUG) Slog.w(TAG, "Backup password mismatch; aborting");
+ return false;
+ }
+ }
+ return true;
+ }
+
// Maintain persistent state around whether need to do an initialize operation.
// Must be called with the queue lock held.
void recordInitPendingLocked(boolean isPending, String transportName) {
@@ -2735,11 +2801,9 @@
// Verify that the given password matches the currently-active
// backup password, if any
- if (hasBackupPassword()) {
- if (!passwordMatchesSaved(mCurrentPassword, PBKDF2_HASH_ROUNDS)) {
- if (DEBUG) Slog.w(TAG, "Backup password mismatch; aborting");
- return;
- }
+ if (!backupPasswordMatches(mCurrentPassword)) {
+ if (DEBUG) Slog.w(TAG, "Backup password mismatch; aborting");
+ return;
}
// Write the global file header. All strings are UTF-8 encoded; lines end
@@ -2747,7 +2811,7 @@
// final '\n'.
//
// line 1: "ANDROID BACKUP"
- // line 2: backup file format version, currently "1"
+ // line 2: backup file format version, currently "2"
// line 3: compressed? "0" if not compressed, "1" if compressed.
// line 4: name of encryption algorithm [currently only "none" or "AES-256"]
//
@@ -2855,7 +2919,7 @@
OutputStream ofstream) throws Exception {
// User key will be used to encrypt the master key.
byte[] newUserSalt = randomBytes(PBKDF2_SALT_SIZE);
- SecretKey userKey = buildPasswordKey(mEncryptPassword, newUserSalt,
+ SecretKey userKey = buildPasswordKey(PBKDF_CURRENT, mEncryptPassword, newUserSalt,
PBKDF2_HASH_ROUNDS);
// the master key is random for each backup
@@ -2902,7 +2966,7 @@
// stated number of PBKDF2 rounds
IV = c.getIV();
byte[] mk = masterKeySpec.getEncoded();
- byte[] checksum = makeKeyChecksum(masterKeySpec.getEncoded(),
+ byte[] checksum = makeKeyChecksum(PBKDF_CURRENT, masterKeySpec.getEncoded(),
checksumSalt, PBKDF2_HASH_ROUNDS);
ByteArrayOutputStream blob = new ByteArrayOutputStream(IV.length + mk.length
@@ -3245,11 +3309,9 @@
FileInputStream rawInStream = null;
DataInputStream rawDataIn = null;
try {
- if (hasBackupPassword()) {
- if (!passwordMatchesSaved(mCurrentPassword, PBKDF2_HASH_ROUNDS)) {
- if (DEBUG) Slog.w(TAG, "Backup password mismatch; aborting");
- return;
- }
+ if (!backupPasswordMatches(mCurrentPassword)) {
+ if (DEBUG) Slog.w(TAG, "Backup password mismatch; aborting");
+ return;
}
mBytes = 0;
@@ -3270,8 +3332,12 @@
if (Arrays.equals(magicBytes, streamHeader)) {
// okay, header looks good. now parse out the rest of the fields.
String s = readHeaderLine(rawInStream);
- if (Integer.parseInt(s) == BACKUP_FILE_VERSION) {
- // okay, it's a version we recognize
+ final int archiveVersion = Integer.parseInt(s);
+ if (archiveVersion <= BACKUP_FILE_VERSION) {
+ // okay, it's a version we recognize. if it's version 1, we may need
+ // to try two different PBKDF2 regimes to compare checksums.
+ final boolean pbkdf2Fallback = (archiveVersion == 1);
+
s = readHeaderLine(rawInStream);
compressed = (Integer.parseInt(s) != 0);
s = readHeaderLine(rawInStream);
@@ -3279,7 +3345,8 @@
// no more header to parse; we're good to go
okay = true;
} else if (mDecryptPassword != null && mDecryptPassword.length() > 0) {
- preCompressStream = decodeAesHeaderAndInitialize(s, rawInStream);
+ preCompressStream = decodeAesHeaderAndInitialize(s, pbkdf2Fallback,
+ rawInStream);
if (preCompressStream != null) {
okay = true;
}
@@ -3339,7 +3406,71 @@
return buffer.toString();
}
- InputStream decodeAesHeaderAndInitialize(String encryptionName, InputStream rawInStream) {
+ InputStream attemptMasterKeyDecryption(String algorithm, byte[] userSalt, byte[] ckSalt,
+ int rounds, String userIvHex, String masterKeyBlobHex, InputStream rawInStream,
+ boolean doLog) {
+ InputStream result = null;
+
+ try {
+ Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ SecretKey userKey = buildPasswordKey(algorithm, mDecryptPassword, userSalt,
+ rounds);
+ byte[] IV = hexToByteArray(userIvHex);
+ IvParameterSpec ivSpec = new IvParameterSpec(IV);
+ c.init(Cipher.DECRYPT_MODE,
+ new SecretKeySpec(userKey.getEncoded(), "AES"),
+ ivSpec);
+ byte[] mkCipher = hexToByteArray(masterKeyBlobHex);
+ byte[] mkBlob = c.doFinal(mkCipher);
+
+ // first, the master key IV
+ int offset = 0;
+ int len = mkBlob[offset++];
+ IV = Arrays.copyOfRange(mkBlob, offset, offset + len);
+ offset += len;
+ // then the master key itself
+ len = mkBlob[offset++];
+ byte[] mk = Arrays.copyOfRange(mkBlob,
+ offset, offset + len);
+ offset += len;
+ // and finally the master key checksum hash
+ len = mkBlob[offset++];
+ byte[] mkChecksum = Arrays.copyOfRange(mkBlob,
+ offset, offset + len);
+
+ // now validate the decrypted master key against the checksum
+ byte[] calculatedCk = makeKeyChecksum(algorithm, mk, ckSalt, rounds);
+ if (Arrays.equals(calculatedCk, mkChecksum)) {
+ ivSpec = new IvParameterSpec(IV);
+ c.init(Cipher.DECRYPT_MODE,
+ new SecretKeySpec(mk, "AES"),
+ ivSpec);
+ // Only if all of the above worked properly will 'result' be assigned
+ result = new CipherInputStream(rawInStream, c);
+ } else if (doLog) Slog.w(TAG, "Incorrect password");
+ } catch (InvalidAlgorithmParameterException e) {
+ if (doLog) Slog.e(TAG, "Needed parameter spec unavailable!", e);
+ } catch (BadPaddingException e) {
+ // This case frequently occurs when the wrong password is used to decrypt
+ // the master key. Use the identical "incorrect password" log text as is
+ // used in the checksum failure log in order to avoid providing additional
+ // information to an attacker.
+ if (doLog) Slog.w(TAG, "Incorrect password");
+ } catch (IllegalBlockSizeException e) {
+ if (doLog) Slog.w(TAG, "Invalid block size in master key");
+ } catch (NoSuchAlgorithmException e) {
+ if (doLog) Slog.e(TAG, "Needed decryption algorithm unavailable!");
+ } catch (NoSuchPaddingException e) {
+ if (doLog) Slog.e(TAG, "Needed padding mechanism unavailable!");
+ } catch (InvalidKeyException e) {
+ if (doLog) Slog.w(TAG, "Illegal password; aborting");
+ }
+
+ return result;
+ }
+
+ InputStream decodeAesHeaderAndInitialize(String encryptionName, boolean pbkdf2Fallback,
+ InputStream rawInStream) {
InputStream result = null;
try {
if (encryptionName.equals(ENCRYPTION_ALGORITHM_NAME)) {
@@ -3356,59 +3487,13 @@
String masterKeyBlobHex = readHeaderLine(rawInStream); // 9
// decrypt the master key blob
- Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
- SecretKey userKey = buildPasswordKey(mDecryptPassword, userSalt,
- rounds);
- byte[] IV = hexToByteArray(userIvHex);
- IvParameterSpec ivSpec = new IvParameterSpec(IV);
- c.init(Cipher.DECRYPT_MODE,
- new SecretKeySpec(userKey.getEncoded(), "AES"),
- ivSpec);
- byte[] mkCipher = hexToByteArray(masterKeyBlobHex);
- byte[] mkBlob = c.doFinal(mkCipher);
-
- // first, the master key IV
- int offset = 0;
- int len = mkBlob[offset++];
- IV = Arrays.copyOfRange(mkBlob, offset, offset + len);
- offset += len;
- // then the master key itself
- len = mkBlob[offset++];
- byte[] mk = Arrays.copyOfRange(mkBlob,
- offset, offset + len);
- offset += len;
- // and finally the master key checksum hash
- len = mkBlob[offset++];
- byte[] mkChecksum = Arrays.copyOfRange(mkBlob,
- offset, offset + len);
-
- // now validate the decrypted master key against the checksum
- byte[] calculatedCk = makeKeyChecksum(mk, ckSalt, rounds);
- if (Arrays.equals(calculatedCk, mkChecksum)) {
- ivSpec = new IvParameterSpec(IV);
- c.init(Cipher.DECRYPT_MODE,
- new SecretKeySpec(mk, "AES"),
- ivSpec);
- // Only if all of the above worked properly will 'result' be assigned
- result = new CipherInputStream(rawInStream, c);
- } else Slog.w(TAG, "Incorrect password");
+ result = attemptMasterKeyDecryption(PBKDF_CURRENT, userSalt, ckSalt,
+ rounds, userIvHex, masterKeyBlobHex, rawInStream, false);
+ if (result == null && pbkdf2Fallback) {
+ result = attemptMasterKeyDecryption(PBKDF_FALLBACK, userSalt, ckSalt,
+ rounds, userIvHex, masterKeyBlobHex, rawInStream, true);
+ }
} else Slog.w(TAG, "Unsupported encryption method: " + encryptionName);
- } catch (InvalidAlgorithmParameterException e) {
- Slog.e(TAG, "Needed parameter spec unavailable!", e);
- } catch (BadPaddingException e) {
- // This case frequently occurs when the wrong password is used to decrypt
- // the master key. Use the identical "incorrect password" log text as is
- // used in the checksum failure log in order to avoid providing additional
- // information to an attacker.
- Slog.w(TAG, "Incorrect password");
- } catch (IllegalBlockSizeException e) {
- Slog.w(TAG, "Invalid block size in master key");
- } catch (NoSuchAlgorithmException e) {
- Slog.e(TAG, "Needed decryption algorithm unavailable!");
- } catch (NoSuchPaddingException e) {
- Slog.e(TAG, "Needed padding mechanism unavailable!");
- } catch (InvalidKeyException e) {
- Slog.w(TAG, "Illegal password; aborting");
} catch (NumberFormatException e) {
Slog.w(TAG, "Can't parse restore data header");
} catch (IOException e) {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 8d158cf..560ec54 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2312,9 +2312,9 @@
mInetConditionChangeInFlight = false;
// Don't do this - if we never sign in stay, grey
//reportNetworkCondition(mActiveDefaultNetwork, 100);
+ updateNetworkSettings(thisNet);
}
thisNet.setTeardownRequested(false);
- updateNetworkSettings(thisNet);
updateMtuSizeSettings(thisNet);
handleConnectivityChange(newNetType, false);
sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
@@ -3041,7 +3041,7 @@
case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED: {
info = (NetworkInfo) msg.obj;
int type = info.getType();
- updateNetworkSettings(mNetTrackers[type]);
+ if (mNetConfigs[type].isDefault()) updateNetworkSettings(mNetTrackers[type]);
break;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index da0c38d..c90978a 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -868,7 +868,7 @@
int[] uidArray = new int[] { res.pkg.applicationInfo.uid };
ArrayList<String> pkgList = new ArrayList<String>(1);
pkgList.add(res.pkg.applicationInfo.packageName);
- sendResourcesChangedBroadcast(true, false,
+ sendResourcesChangedBroadcast(true, true,
pkgList,uidArray, null);
}
}
@@ -10617,7 +10617,8 @@
DumpState dumpState = new DumpState();
boolean fullPreferred = false;
-
+ boolean checkin = false;
+
String packageName = null;
int opti = 0;
@@ -10631,7 +10632,8 @@
// Right now we only know how to print all.
} else if ("-h".equals(opt)) {
pw.println("Package manager dump options:");
- pw.println(" [-h] [-f] [cmd] ...");
+ pw.println(" [-h] [-f] [--checkin] [cmd] ...");
+ pw.println(" --checkin: dump for a checkin");
pw.println(" -f: print details of intent filters");
pw.println(" -h: print this help");
pw.println(" cmd may be one of:");
@@ -10649,13 +10651,15 @@
pw.println(" <package.name>: info about given package");
pw.println(" k[eysets]: print known keysets");
return;
+ } else if ("--checkin".equals(opt)) {
+ checkin = true;
} else if ("-f".equals(opt)) {
dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
} else {
pw.println("Unknown argument: " + opt + "; use -h for help");
}
}
-
+
// Is the caller requesting to dump a particular piece of data?
if (opti < args.length) {
String cmd = args[opti];
@@ -10697,17 +10701,26 @@
}
}
+ if (checkin) {
+ pw.println("vers,1");
+ }
+
// reader
synchronized (mPackages) {
if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) {
- if (dumpState.onTitlePrinted())
- pw.println();
- pw.println("Verifiers:");
- pw.print(" Required: ");
- pw.print(mRequiredVerifierPackage);
- pw.print(" (uid=");
- pw.print(getPackageUid(mRequiredVerifierPackage, 0));
- pw.println(")");
+ if (!checkin) {
+ if (dumpState.onTitlePrinted())
+ pw.println();
+ pw.println("Verifiers:");
+ pw.print(" Required: ");
+ pw.print(mRequiredVerifierPackage);
+ pw.print(" (uid=");
+ pw.print(getPackageUid(mRequiredVerifierPackage, 0));
+ pw.println(")");
+ } else if (mRequiredVerifierPackage != null) {
+ pw.print("vrfy,"); pw.print(mRequiredVerifierPackage);
+ pw.print(","); pw.println(getPackageUid(mRequiredVerifierPackage, 0));
+ }
}
if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) {
@@ -10716,21 +10729,37 @@
while (it.hasNext()) {
String name = it.next();
SharedLibraryEntry ent = mSharedLibraries.get(name);
- if (!printedHeader) {
- if (dumpState.onTitlePrinted())
- pw.println();
- pw.println("Libraries:");
- printedHeader = true;
- }
- pw.print(" ");
- pw.print(name);
- pw.print(" -> ");
- if (ent.path != null) {
- pw.print("(jar) ");
- pw.print(ent.path);
+ if (!checkin) {
+ if (!printedHeader) {
+ if (dumpState.onTitlePrinted())
+ pw.println();
+ pw.println("Libraries:");
+ printedHeader = true;
+ }
+ pw.print(" ");
} else {
- pw.print("(apk) ");
- pw.print(ent.apk);
+ pw.print("lib,");
+ }
+ pw.print(name);
+ if (!checkin) {
+ pw.print(" -> ");
+ }
+ if (ent.path != null) {
+ if (!checkin) {
+ pw.print("(jar) ");
+ pw.print(ent.path);
+ } else {
+ pw.print(",jar,");
+ pw.print(ent.path);
+ }
+ } else {
+ if (!checkin) {
+ pw.print("(apk) ");
+ pw.print(ent.apk);
+ } else {
+ pw.print(",apk,");
+ pw.print(ent.apk);
+ }
}
pw.println();
}
@@ -10739,16 +10768,22 @@
if (dumpState.isDumping(DumpState.DUMP_FEATURES) && packageName == null) {
if (dumpState.onTitlePrinted())
pw.println();
- pw.println("Features:");
+ if (!checkin) {
+ pw.println("Features:");
+ }
Iterator<String> it = mAvailableFeatures.keySet().iterator();
while (it.hasNext()) {
String name = it.next();
- pw.print(" ");
+ if (!checkin) {
+ pw.print(" ");
+ } else {
+ pw.print("feat,");
+ }
pw.println(name);
}
}
- if (dumpState.isDumping(DumpState.DUMP_RESOLVERS)) {
+ if (!checkin && dumpState.isDumping(DumpState.DUMP_RESOLVERS)) {
if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
: "Activity Resolver Table:", " ", packageName,
dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
@@ -10771,7 +10806,7 @@
}
}
- if (dumpState.isDumping(DumpState.DUMP_PREFERRED)) {
+ if (!checkin && dumpState.isDumping(DumpState.DUMP_PREFERRED)) {
for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
int user = mSettings.mPreferredActivities.keyAt(i);
@@ -10785,7 +10820,7 @@
}
}
- if (dumpState.isDumping(DumpState.DUMP_PREFERRED_XML)) {
+ if (!checkin && dumpState.isDumping(DumpState.DUMP_PREFERRED_XML)) {
pw.flush();
FileOutputStream fout = new FileOutputStream(fd);
BufferedOutputStream str = new BufferedOutputStream(fout);
@@ -10807,11 +10842,11 @@
}
}
- if (dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
+ if (!checkin && dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
mSettings.dumpPermissionsLPr(pw, packageName, dumpState);
}
- if (dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
+ if (!checkin && dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
boolean printedSomething = false;
for (PackageParser.Provider p : mProviders.mProviders.values()) {
if (packageName != null && !packageName.equals(p.info.packageName)) {
@@ -10848,19 +10883,19 @@
}
}
- if (dumpState.isDumping(DumpState.DUMP_KEYSETS)) {
+ if (!checkin && dumpState.isDumping(DumpState.DUMP_KEYSETS)) {
mSettings.mKeySetManager.dump(pw, packageName, dumpState);
}
if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) {
- mSettings.dumpPackagesLPr(pw, packageName, dumpState);
+ mSettings.dumpPackagesLPr(pw, packageName, dumpState, checkin);
}
- if (dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) {
+ if (!checkin && dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) {
mSettings.dumpSharedUsersLPr(pw, packageName, dumpState);
}
- if (dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
+ if (!checkin && dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
if (dumpState.onTitlePrinted())
pw.println();
mSettings.dumpReadMessagesLPr(pw, dumpState);
@@ -11099,7 +11134,7 @@
if (uidArr != null) {
extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
}
- if (replacing && !mediaStatus) {
+ if (replacing) {
extras.putBoolean(Intent.EXTRA_REPLACING, replacing);
}
String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index e599409..8f18b23 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2892,8 +2892,44 @@
ApplicationInfo.FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE",
};
- void dumpPackageLPr(PrintWriter pw, String prefix, PackageSetting ps, SimpleDateFormat sdf,
- Date date, List<UserInfo> users) {
+ void dumpPackageLPr(PrintWriter pw, String prefix, String checkinTag, PackageSetting ps,
+ SimpleDateFormat sdf, Date date, List<UserInfo> users) {
+ if (checkinTag != null) {
+ pw.print(checkinTag);
+ pw.print(",");
+ pw.print(ps.realName != null ? ps.realName : ps.name);
+ pw.print(",");
+ pw.print(ps.appId);
+ pw.print(",");
+ pw.print(ps.versionCode);
+ pw.print(",");
+ pw.print(ps.firstInstallTime);
+ pw.print(",");
+ pw.print(ps.lastUpdateTime);
+ pw.print(",");
+ pw.print(ps.installerPackageName != null ? ps.installerPackageName : "?");
+ pw.println();
+ for (UserInfo user : users) {
+ pw.print(checkinTag);
+ pw.print("-");
+ pw.print("usr");
+ pw.print(",");
+ pw.print(user.id);
+ pw.print(",");
+ pw.print(ps.getInstalled(user.id) ? "I" : "i");
+ pw.print(ps.getBlocked(user.id) ? "B" : "b");
+ pw.print(ps.getStopped(user.id) ? "S" : "s");
+ pw.print(ps.getNotLaunched(user.id) ? "l" : "L");
+ pw.print(",");
+ pw.print(ps.getEnabled(user.id));
+ String lastDisabledAppCaller = ps.getLastDisabledAppCaller(user.id);
+ pw.print(",");
+ pw.print(lastDisabledAppCaller != null ? lastDisabledAppCaller : "?");
+ pw.println();
+ }
+ return;
+ }
+
pw.print(prefix); pw.print("Package [");
pw.print(ps.realName != null ? ps.realName : ps.name);
pw.print("] (");
@@ -3055,7 +3091,7 @@
}
}
- void dumpPackagesLPr(PrintWriter pw, String packageName, DumpState dumpState) {
+ void dumpPackagesLPr(PrintWriter pw, String packageName, DumpState dumpState, boolean checkin) {
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
final Date date = new Date();
boolean printedSomething = false;
@@ -3066,35 +3102,39 @@
continue;
}
- if (packageName != null) {
+ if (!checkin && packageName != null) {
dumpState.setSharedUser(ps.sharedUser);
}
- if (!printedSomething) {
+ if (!checkin && !printedSomething) {
if (dumpState.onTitlePrinted())
pw.println();
pw.println("Packages:");
printedSomething = true;
}
- dumpPackageLPr(pw, " ", ps, sdf, date, users);
+ dumpPackageLPr(pw, " ", checkin ? "pkg" : null, ps, sdf, date, users);
}
printedSomething = false;
- if (mRenamedPackages.size() > 0) {
+ if (!checkin && mRenamedPackages.size() > 0) {
for (final Map.Entry<String, String> e : mRenamedPackages.entrySet()) {
if (packageName != null && !packageName.equals(e.getKey())
&& !packageName.equals(e.getValue())) {
continue;
}
- if (!printedSomething) {
- if (dumpState.onTitlePrinted())
- pw.println();
- pw.println("Renamed packages:");
- printedSomething = true;
+ if (!checkin) {
+ if (!printedSomething) {
+ if (dumpState.onTitlePrinted())
+ pw.println();
+ pw.println("Renamed packages:");
+ printedSomething = true;
+ }
+ pw.print(" ");
+ } else {
+ pw.print("ren,");
}
- pw.print(" ");
pw.print(e.getKey());
- pw.print(" -> ");
+ pw.print(checkin ? " -> " : ",");
pw.println(e.getValue());
}
}
@@ -3106,13 +3146,13 @@
&& !packageName.equals(ps.name)) {
continue;
}
- if (!printedSomething) {
+ if (!checkin && !printedSomething) {
if (dumpState.onTitlePrinted())
pw.println();
pw.println("Hidden system packages:");
printedSomething = true;
}
- dumpPackageLPr(pw, " ", ps, sdf, date, users);
+ dumpPackageLPr(pw, " ", checkin ? "dis" : null, ps, sdf, date, users);
}
}
}
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 62f6aff..dfb8070 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -85,11 +85,13 @@
// do initial app launch, without force stopping
for (String app : mNameToResultKey.keySet()) {
long launchTime = startApp(app, false);
- if (launchTime <=0 ) {
+ if (launchTime <= 0) {
mNameToLaunchTime.put(app, -1L);
// simply pass the app if launch isn't successful
// error should have already been logged by startApp
continue;
+ } else {
+ mNameToLaunchTime.put(app, launchTime);
}
sleep(INITIAL_LAUNCH_IDLE_TIMEOUT);
closeApp(app, false);
@@ -98,9 +100,9 @@
// do the real app launch now
for (int i = 0; i < mLaunchIterations; i++) {
for (String app : mNameToResultKey.keySet()) {
- long totalLaunchTime = mNameToLaunchTime.get(app);
+ long prevLaunchTime = mNameToLaunchTime.get(app);
long launchTime = 0;
- if (totalLaunchTime < 0) {
+ if (prevLaunchTime < 0) {
// skip if the app has previous failures
continue;
}
@@ -110,18 +112,19 @@
mNameToLaunchTime.put(app, -1L);
continue;
}
- totalLaunchTime += launchTime;
- mNameToLaunchTime.put(app, totalLaunchTime);
+ // keep the min launch time
+ if (launchTime < prevLaunchTime) {
+ mNameToLaunchTime.put(app, launchTime);
+ }
sleep(POST_LAUNCH_IDLE_TIMEOUT);
closeApp(app, true);
sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
}
}
for (String app : mNameToResultKey.keySet()) {
- long totalLaunchTime = mNameToLaunchTime.get(app);
- if (totalLaunchTime != -1) {
- mResult.putDouble(mNameToResultKey.get(app),
- ((double) totalLaunchTime) / mLaunchIterations);
+ long launchTime = mNameToLaunchTime.get(app);
+ if (launchTime != -1) {
+ mResult.putLong(mNameToResultKey.get(app), launchTime);
}
}
instrumentation.sendStatus(0, mResult);
diff --git a/tests/LegacyRestoreTest/README b/tests/LegacyRestoreTest/README
new file mode 100644
index 0000000..cdd157e
--- /dev/null
+++ b/tests/LegacyRestoreTest/README
@@ -0,0 +1,18 @@
+The file "jbmr2-encrypted-settings-abcd.ab" in this directory is an encrypted
+"adb backup" archive of the settings provider package. It was generated on a
+Nexus 4 running Android 4.3 (API 18), and so predates the Android 4.4 changes
+to the PBKDF2 implementation. The archive's encryption password, entered on-screen,
+is "abcd" (with no quotation marks).
+
+'adb restore' decrypts and applies the restored archive successfully on a device
+running Android 4.3, but fails to restore correctly on a device running Android 4.4,
+reporting an invalid password in logcat. This is the situation reported in bug
+<https://code.google.com/p/android/issues/detail?id=63880>.
+
+The file "kk-fixed-encrypted-settings-abcd.ab" is a similar encrypted "adb backup"
+archive, using the same key, generated on a Nexus 4 running Android 4.4 with a fix
+to this bug in place. This archive should be successfully restorable on any
+version of Android which incorporates the fix.
+
+These archives can be used as an ongoing test to verify that historical encrypted
+archives from various points in Android's history can be successfully restored.
diff --git a/tests/LegacyRestoreTest/jbmr2-encrypted-settings-abcd.ab b/tests/LegacyRestoreTest/jbmr2-encrypted-settings-abcd.ab
new file mode 100644
index 0000000..192dcf5
--- /dev/null
+++ b/tests/LegacyRestoreTest/jbmr2-encrypted-settings-abcd.ab
Binary files differ
diff --git a/tests/LegacyRestoreTest/kk-fixed-encrypted-settings-abcd.ab b/tests/LegacyRestoreTest/kk-fixed-encrypted-settings-abcd.ab
new file mode 100644
index 0000000..bf2b558
--- /dev/null
+++ b/tests/LegacyRestoreTest/kk-fixed-encrypted-settings-abcd.ab
Binary files differ