Merge "No clicking on volume icon in volume dialog." into ics-mr1
diff --git a/api/current.txt b/api/current.txt
index 23b441b..de8cab1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5502,7 +5502,16 @@
field public static final java.lang.String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED";
field public static final java.lang.String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";
field public static final java.lang.String CATEGORY_ALTERNATIVE = "android.intent.category.ALTERNATIVE";
+ field public static final java.lang.String CATEGORY_APP_BROWSER = "android.intent.category.APP_BROWSER";
+ field public static final java.lang.String CATEGORY_APP_CALCULATOR = "android.intent.category.APP_CALCULATOR";
+ field public static final java.lang.String CATEGORY_APP_CALENDAR = "android.intent.category.APP_CALENDAR";
+ field public static final java.lang.String CATEGORY_APP_CONTACTS = "android.intent.category.APP_CONTACTS";
+ field public static final java.lang.String CATEGORY_APP_EMAIL = "android.intent.category.APP_EMAIL";
+ field public static final java.lang.String CATEGORY_APP_GALLERY = "android.intent.category.APP_GALLERY";
+ field public static final java.lang.String CATEGORY_APP_MAPS = "android.intent.category.APP_MAPS";
field public static final java.lang.String CATEGORY_APP_MARKET = "android.intent.category.APP_MARKET";
+ field public static final java.lang.String CATEGORY_APP_MESSAGING = "android.intent.category.APP_MESSAGING";
+ field public static final java.lang.String CATEGORY_APP_MUSIC = "android.intent.category.APP_MUSIC";
field public static final java.lang.String CATEGORY_BROWSABLE = "android.intent.category.BROWSABLE";
field public static final java.lang.String CATEGORY_CAR_DOCK = "android.intent.category.CAR_DOCK";
field public static final java.lang.String CATEGORY_CAR_MODE = "android.intent.category.CAR_MODE";
@@ -17056,7 +17065,7 @@
field public static final java.lang.String EXTRA_VIDEO_QUALITY = "android.intent.extra.videoQuality";
field public static final java.lang.String INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH = "android.media.action.MEDIA_PLAY_FROM_SEARCH";
field public static final java.lang.String INTENT_ACTION_MEDIA_SEARCH = "android.intent.action.MEDIA_SEARCH";
- field public static final java.lang.String INTENT_ACTION_MUSIC_PLAYER = "android.intent.action.MUSIC_PLAYER";
+ field public static final deprecated java.lang.String INTENT_ACTION_MUSIC_PLAYER = "android.intent.action.MUSIC_PLAYER";
field public static final java.lang.String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA";
field public static final java.lang.String INTENT_ACTION_VIDEO_CAMERA = "android.media.action.VIDEO_CAMERA";
field public static final java.lang.String MEDIA_IGNORE_FILENAME = ".nomedia";
@@ -22215,6 +22224,8 @@
field public static final int KEYCODE_BUTTON_Y = 100; // 0x64
field public static final int KEYCODE_BUTTON_Z = 101; // 0x65
field public static final int KEYCODE_C = 31; // 0x1f
+ field public static final int KEYCODE_CALCULATOR = 210; // 0xd2
+ field public static final int KEYCODE_CALENDAR = 208; // 0xd0
field public static final int KEYCODE_CALL = 5; // 0x5
field public static final int KEYCODE_CAMERA = 27; // 0x1b
field public static final int KEYCODE_CAPS_LOCK = 115; // 0x73
@@ -22223,6 +22234,7 @@
field public static final int KEYCODE_CHANNEL_UP = 166; // 0xa6
field public static final int KEYCODE_CLEAR = 28; // 0x1c
field public static final int KEYCODE_COMMA = 55; // 0x37
+ field public static final int KEYCODE_CONTACTS = 207; // 0xcf
field public static final int KEYCODE_CTRL_LEFT = 113; // 0x71
field public static final int KEYCODE_CTRL_RIGHT = 114; // 0x72
field public static final int KEYCODE_D = 32; // 0x20
@@ -22290,6 +22302,7 @@
field public static final int KEYCODE_MINUS = 69; // 0x45
field public static final int KEYCODE_MOVE_END = 123; // 0x7b
field public static final int KEYCODE_MOVE_HOME = 122; // 0x7a
+ field public static final int KEYCODE_MUSIC = 209; // 0xd1
field public static final int KEYCODE_MUTE = 91; // 0x5b
field public static final int KEYCODE_N = 42; // 0x2a
field public static final int KEYCODE_NOTIFICATION = 83; // 0x53
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 64a2755..211be52 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -16,8 +16,6 @@
package android.accessibilityservice;
-import com.android.internal.os.HandlerCaller;
-
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
@@ -25,8 +23,11 @@
import android.os.RemoteException;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityNodeInfo;
+import com.android.internal.os.HandlerCaller;
+
/**
* An accessibility service runs in the background and receives callbacks by the system
* when {@link AccessibilityEvent}s are fired. Such events denote some state transition
@@ -219,7 +220,7 @@
private AccessibilityServiceInfo mInfo;
- IAccessibilityServiceConnection mConnection;
+ private int mConnectionId;
/**
* Callback for {@link android.view.accessibility.AccessibilityEvent}s.
@@ -264,9 +265,11 @@
* AccessibilityManagerService.
*/
private void sendServiceInfo() {
- if (mInfo != null && mConnection != null) {
+ IAccessibilityServiceConnection connection =
+ AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
+ if (mInfo != null && connection != null) {
try {
- mConnection.setServiceInfo(mInfo);
+ connection.setServiceInfo(mInfo);
} catch (RemoteException re) {
Log.w(LOG_TAG, "Error while setting AccessibilityServiceInfo", re);
}
@@ -302,8 +305,9 @@
mCaller = new HandlerCaller(context, this);
}
- public void setConnection(IAccessibilityServiceConnection connection) {
- Message message = mCaller.obtainMessageO(DO_SET_SET_CONNECTION, connection);
+ public void setConnection(IAccessibilityServiceConnection connection, int connectionId) {
+ Message message = mCaller.obtainMessageIO(DO_SET_SET_CONNECTION, connectionId,
+ connection);
mCaller.sendMessage(message);
}
@@ -330,8 +334,19 @@
mTarget.onInterrupt();
return;
case DO_SET_SET_CONNECTION :
- mConnection = ((IAccessibilityServiceConnection) message.obj);
- mTarget.onServiceConnected();
+ final int connectionId = message.arg1;
+ IAccessibilityServiceConnection connection =
+ (IAccessibilityServiceConnection) message.obj;
+ if (connection != null) {
+ AccessibilityInteractionClient.getInstance().addConnection(connectionId,
+ connection);
+ mConnectionId = connectionId;
+ mTarget.onServiceConnected();
+ } else {
+ AccessibilityInteractionClient.getInstance().removeConnection(connectionId);
+ mConnectionId = AccessibilityInteractionClient.NO_ID;
+ // TODO: Do we need a onServiceDisconnected callback?
+ }
return;
default :
Log.w(LOG_TAG, "Unknown message type " + message.what);
diff --git a/core/java/android/accessibilityservice/IEventListener.aidl b/core/java/android/accessibilityservice/IEventListener.aidl
index 5b849f1..5536b3c 100644
--- a/core/java/android/accessibilityservice/IEventListener.aidl
+++ b/core/java/android/accessibilityservice/IEventListener.aidl
@@ -26,7 +26,7 @@
*/
oneway interface IEventListener {
- void setConnection(in IAccessibilityServiceConnection connection);
+ void setConnection(in IAccessibilityServiceConnection connection, int connectionId);
void onAccessibilityEvent(in AccessibilityEvent event);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 303f81b..0c761fc 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -175,11 +175,11 @@
// These can be accessed by multiple threads; mPackages is the lock.
// XXX For now we keep around information about all packages we have
// seen, not removing entries from this map.
- // NOTE: The activity manager in its process needs to call in to
+ // NOTE: The activity and window managers need to call in to
// ActivityThread to do things like update resource configurations,
- // which means this lock gets held while the activity manager holds its
- // own lock. Thus you MUST NEVER call back into the activity manager
- // or anything that depends on it while holding this lock.
+ // which means this lock gets held while the activity and window managers
+ // holds their own lock. Thus you MUST NEVER call back into the activity manager
+ // or window manager or anything that depends on them while holding this lock.
final HashMap<String, WeakReference<LoadedApk>> mPackages
= new HashMap<String, WeakReference<LoadedApk>>();
final HashMap<String, WeakReference<LoadedApk>> mResourcePackages
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 8ed7481..180a442 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -625,7 +625,7 @@
return info.activityInfo.loadIcon(this);
}
- throw new NameNotFoundException(intent.toURI());
+ throw new NameNotFoundException(intent.toUri(0));
}
@Override public Drawable getDefaultActivityIcon() {
@@ -728,15 +728,22 @@
private Drawable getCachedIcon(ResourceName name) {
synchronized (sSync) {
- WeakReference<Drawable> wr = sIconCache.get(name);
+ WeakReference<Drawable.ConstantState> wr = sIconCache.get(name);
if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
+ name + ": " + wr);
if (wr != null) { // we have the activity
- Drawable dr = wr.get();
- if (dr != null) {
- if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for "
- + name + ": " + dr);
- return dr;
+ Drawable.ConstantState state = wr.get();
+ if (state != null) {
+ if (DEBUG_ICONS) {
+ Log.v(TAG, "Get cached drawable state for " + name + ": " + state);
+ }
+ // Note: It's okay here to not use the newDrawable(Resources) variant
+ // of the API. The ConstantState comes from a drawable that was
+ // originally created by passing the proper app Resources instance
+ // which means the state should already contain the proper
+ // resources specific information (like density.) See
+ // BitmapDrawable.BitmapState for instance.
+ return state.newDrawable();
}
// our entry has been purged
sIconCache.remove(name);
@@ -747,14 +754,12 @@
private void putCachedIcon(ResourceName name, Drawable dr) {
synchronized (sSync) {
- sIconCache.put(name, new WeakReference<Drawable>(dr));
- if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
- + name + ": " + dr);
+ sIconCache.put(name, new WeakReference<Drawable.ConstantState>(dr.getConstantState()));
+ if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable state for " + name + ": " + dr);
}
}
- static final void handlePackageBroadcast(int cmd, String[] pkgList,
- boolean hasPkgInfo) {
+ static void handlePackageBroadcast(int cmd, String[] pkgList, boolean hasPkgInfo) {
boolean immediateGc = false;
if (cmd == IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE) {
immediateGc = true;
@@ -1226,8 +1231,8 @@
private final IPackageManager mPM;
private static final Object sSync = new Object();
- private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
- = new HashMap<ResourceName, WeakReference<Drawable> >();
- private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache
- = new HashMap<ResourceName, WeakReference<CharSequence> >();
+ private static HashMap<ResourceName, WeakReference<Drawable.ConstantState>> sIconCache
+ = new HashMap<ResourceName, WeakReference<Drawable.ConstantState>>();
+ private static HashMap<ResourceName, WeakReference<CharSequence>> sStringCache
+ = new HashMap<ResourceName, WeakReference<CharSequence>>();
}
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java
index 8b70370..bf8fde0 100644
--- a/core/java/android/app/DatePickerDialog.java
+++ b/core/java/android/app/DatePickerDialog.java
@@ -91,13 +91,14 @@
mCallBack = callBack;
- setButton(BUTTON_POSITIVE, context.getText(R.string.date_time_set), this);
- setButton(BUTTON_NEGATIVE, context.getText(R.string.cancel), (OnClickListener) null);
+ Context themeContext = getContext();
+ setButton(BUTTON_POSITIVE, themeContext.getText(R.string.date_time_set), this);
+ setButton(BUTTON_NEGATIVE, themeContext.getText(R.string.cancel), (OnClickListener) null);
setIcon(0);
setTitle(R.string.date_picker_dialog_title);
LayoutInflater inflater =
- (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ (LayoutInflater) themeContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.date_picker_dialog, null);
setView(view);
mDatePicker = (DatePicker) view.findViewById(R.id.datePicker);
diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java
index a990ee9..353b415 100644
--- a/core/java/android/app/TimePickerDialog.java
+++ b/core/java/android/app/TimePickerDialog.java
@@ -92,16 +92,16 @@
mInitialMinute = minute;
mIs24HourView = is24HourView;
- setCanceledOnTouchOutside(false);
setIcon(0);
setTitle(R.string.time_picker_dialog_title);
- setButton(BUTTON_POSITIVE, context.getText(R.string.date_time_set), this);
- setButton(BUTTON_NEGATIVE, context.getText(R.string.cancel),
+ Context themeContext = getContext();
+ setButton(BUTTON_POSITIVE, themeContext.getText(R.string.date_time_set), this);
+ setButton(BUTTON_NEGATIVE, themeContext.getText(R.string.cancel),
(OnClickListener) null);
LayoutInflater inflater =
- (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ (LayoutInflater) themeContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.time_picker_dialog, null);
setView(view);
mTimePicker = (TimePicker) view.findViewById(R.id.timePicker);
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 96f32901..7300107 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -129,6 +129,10 @@
}
}
+ /*package*/ void close() {
+ mServiceListener = null;
+ }
+
/**
* Initiate connection to a profile of the remote bluetooth device.
*
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index d971652..5f5ba50 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1180,11 +1180,29 @@
* @param proxy Profile proxy object
*/
public void closeProfileProxy(int profile, BluetoothProfile proxy) {
- if (profile == BluetoothProfile.HEADSET) {
- BluetoothHeadset headset = (BluetoothHeadset)proxy;
- if (headset != null) {
+ if (proxy == null) return;
+
+ switch (profile) {
+ case BluetoothProfile.HEADSET:
+ BluetoothHeadset headset = (BluetoothHeadset)proxy;
headset.close();
- }
+ break;
+ case BluetoothProfile.A2DP:
+ BluetoothA2dp a2dp = (BluetoothA2dp)proxy;
+ a2dp.close();
+ break;
+ case BluetoothProfile.INPUT_DEVICE:
+ BluetoothInputDevice iDev = (BluetoothInputDevice)proxy;
+ iDev.close();
+ break;
+ case BluetoothProfile.PAN:
+ BluetoothPan pan = (BluetoothPan)proxy;
+ pan.close();
+ break;
+ case BluetoothProfile.HEALTH:
+ BluetoothHealth health = (BluetoothHealth)proxy;
+ health.close();
+ break;
}
}
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index b1d0070..c9603bf 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -109,6 +109,8 @@
private BluetoothA2dpService mA2dpService;
private BluetoothHeadset mHeadsetService;
private BluetoothPbap mPbapService;
+ private PbapServiceListener mPbap;
+ private BluetoothAdapter mAdapter;
private boolean mPbapServiceConnected;
private boolean mAutoConnectionPending;
private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
@@ -249,11 +251,11 @@
mContext.registerReceiver(mBroadcastReceiver, filter);
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
+ mAdapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
BluetoothProfile.HEADSET);
// TODO(): Convert PBAP to the new Profile APIs.
- PbapServiceListener p = new PbapServiceListener();
+ mPbap = new PbapServiceListener();
mIncomingConnections = mService.getIncomingState(address);
mIncomingRejectTimer = readTimerValue();
@@ -414,6 +416,26 @@
case TRANSITION_TO_STABLE:
// ignore.
break;
+ case SM_QUIT_CMD:
+ mContext.unregisterReceiver(mBroadcastReceiver);
+ mBroadcastReceiver = null;
+ mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mHeadsetService);
+ mBluetoothProfileServiceListener = null;
+ mOutgoingHandsfree = null;
+ mPbap = null;
+ mPbapService.close();
+ mPbapService = null;
+ mIncomingHid = null;
+ mOutgoingHid = null;
+ mIncomingHandsfree = null;
+ mOutgoingHandsfree = null;
+ mIncomingA2dp = null;
+ mOutgoingA2dp = null;
+ mBondedDevice = null;
+ // There is a problem in the State Machine code
+ // where things are not cleaned up properly, when quit message
+ // is handled so return NOT_HANDLED as a workaround.
+ return NOT_HANDLED;
default:
return NOT_HANDLED;
}
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 8f2b3d8..2bbf008 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -245,6 +245,7 @@
mContext.unbindService(mConnection);
mConnection = null;
}
+ mServiceListener = null;
}
/**
diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java
index 9b2b8ca..f850c02 100644
--- a/core/java/android/bluetooth/BluetoothHealth.java
+++ b/core/java/android/bluetooth/BluetoothHealth.java
@@ -452,6 +452,10 @@
}
}
+ /*package*/ void close() {
+ mServiceListener = null;
+ }
+
private boolean isEnabled() {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index 282b70a..1a9e011 100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -118,6 +118,10 @@
}
}
+ /*package*/ void close() {
+ mServiceListener = null;
+ }
+
/**
* Initiate connection to a profile of the remote bluetooth device.
*
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 7490f9e..5d9d8be 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -139,6 +139,10 @@
}
}
+ /*package*/ void close() {
+ mServiceListener = null;
+ }
+
/**
* Initiate connection to a profile of the remote bluetooth device.
*
@@ -299,4 +303,4 @@
private static void log(String msg) {
Log.d(TAG, msg);
}
-}
\ No newline at end of file
+}
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index 4be077c..2683bef 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -69,7 +69,7 @@
private IBluetoothPbap mService;
private final Context mContext;
- private final ServiceListener mServiceListener;
+ private ServiceListener mServiceListener;
/** There was an error trying to obtain the state */
public static final int STATE_ERROR = -1;
@@ -138,6 +138,7 @@
mContext.unbindService(mConnection);
mConnection = null;
}
+ mServiceListener = null;
}
/**
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 45a42e4..9948985 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2310,6 +2310,74 @@
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
+ // Application launch intent categories (see addCategory()).
+
+ /**
+ * Used with {@link #ACTION_MAIN} to launch the browser application.
+ * The activity should be able to browse the Internet.
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_APP_BROWSER = "android.intent.category.APP_BROWSER";
+
+ /**
+ * Used with {@link #ACTION_MAIN} to launch the calculator application.
+ * The activity should be able to perform standard arithmetic operations.
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_APP_CALCULATOR = "android.intent.category.APP_CALCULATOR";
+
+ /**
+ * Used with {@link #ACTION_MAIN} to launch the calendar application.
+ * The activity should be able to view and manipulate calendar entries.
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_APP_CALENDAR = "android.intent.category.APP_CALENDAR";
+
+ /**
+ * Used with {@link #ACTION_MAIN} to launch the contacts application.
+ * The activity should be able to view and manipulate address book entries.
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_APP_CONTACTS = "android.intent.category.APP_CONTACTS";
+
+ /**
+ * Used with {@link #ACTION_MAIN} to launch the email application.
+ * The activity should be able to send and receive email.
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_APP_EMAIL = "android.intent.category.APP_EMAIL";
+
+ /**
+ * Used with {@link #ACTION_MAIN} to launch the gallery application.
+ * The activity should be able to view and manipulate image and video files
+ * stored on the device.
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_APP_GALLERY = "android.intent.category.APP_GALLERY";
+
+ /**
+ * Used with {@link #ACTION_MAIN} to launch the maps application.
+ * The activity should be able to show the user's current location and surroundings.
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_APP_MAPS = "android.intent.category.APP_MAPS";
+
+ /**
+ * Used with {@link #ACTION_MAIN} to launch the messaging application.
+ * The activity should be able to send and receive text messages.
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_APP_MESSAGING = "android.intent.category.APP_MESSAGING";
+
+ /**
+ * Used with {@link #ACTION_MAIN} to launch the music application.
+ * The activity should be able to play, browse, or manipulate music files stored on the device.
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_APP_MUSIC = "android.intent.category.APP_MUSIC";
+
+ // ---------------------------------------------------------------------
+ // ---------------------------------------------------------------------
// Standard extra data keys.
/**
diff --git a/core/java/android/inputmethodservice/ExtractEditText.java b/core/java/android/inputmethodservice/ExtractEditText.java
index 4fc63ed..72431f3 100644
--- a/core/java/android/inputmethodservice/ExtractEditText.java
+++ b/core/java/android/inputmethodservice/ExtractEditText.java
@@ -156,4 +156,27 @@
mIME.onViewClicked(false);
}
}
+
+ /**
+ * Delete the range of text, supposedly valid
+ * @hide
+ */
+ @Override
+ protected void deleteText_internal(int start, int end) {
+ // Do not call the super method. This will change the source TextView instead, which
+ // will update the ExtractTextView.
+ mIME.onExtractedDeleteText(start, end);
+ }
+
+ /**
+ * Replaces the range of text [start, end[ by replacement text
+ * @hide
+ */
+ @Override
+ protected void replaceText_internal(int start, int end, CharSequence text) {
+ // Do not call the super method. This will change the source TextView instead, which
+ // will update the ExtractTextView.
+ mIME.onExtractedReplaceText(start, end, text);
+ }
+
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 60188ea..02839db 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1982,7 +1982,29 @@
conn.setSelection(start, end);
}
}
-
+
+ /**
+ * @hide
+ */
+ public void onExtractedDeleteText(int start, int end) {
+ InputConnection conn = getCurrentInputConnection();
+ if (conn != null) {
+ conn.setSelection(start, start);
+ conn.deleteSurroundingText(0, end-start);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void onExtractedReplaceText(int start, int end, CharSequence text) {
+ InputConnection conn = getCurrentInputConnection();
+ if (conn != null) {
+ conn.setComposingRegion(start, end);
+ conn.commitText(text, 1);
+ }
+ }
+
/**
* This is called when the user has clicked on the extracted text view,
* when running in fullscreen mode. The default implementation hides
@@ -1998,7 +2020,7 @@
setCandidatesViewShown(false);
}
}
-
+
/**
* This is called when the user has performed a cursor movement in the
* extracted text view, when it is running in fullscreen mode. The default
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 5f111eb..4e01672 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -40,8 +40,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.text.Collator;
/**
* The Media provider contains meta data for all available media on both internal
@@ -66,7 +64,10 @@
/**
* Activity Action: Launch a music player.
* The activity should be able to play, browse, or manipulate music files stored on the device.
+ *
+ * @deprecated Use {@link android.content.Intent#CATEGORY_APP_MUSIC} instead.
*/
+ @Deprecated
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String INTENT_ACTION_MUSIC_PLAYER = "android.intent.action.MUSIC_PLAYER";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ee3215c..15e4438 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4019,28 +4019,6 @@
public static final String SETUP_PREPAID_DETECTION_REDIR_HOST =
"setup_prepaid_detection_redir_host";
- /**
- * Whether the screensaver is enabled.
- * @hide
- */
- public static final String SCREENSAVER_ENABLED = "screensaver_enabled";
-
- /**
- * The user's chosen screensaver component.
- *
- * This component will be launched by the PhoneWindowManager after a timeout when not on
- * battery, or upon dock insertion (if SCREENSAVER_ACTIVATE_ON_DOCK is set to 1).
- * @hide
- */
- public static final String SCREENSAVER_COMPONENT = "screensaver_component";
-
- /**
- * Whether the screensaver should be automatically launched when the device is inserted
- * into a (desk) dock.
- * @hide
- */
- public static final String SCREENSAVER_ACTIVATE_ON_DOCK = "screensaver_activate_on_dock";
-
/** {@hide} */
public static final String NETSTATS_ENABLED = "netstats_enabled";
/** {@hide} */
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 28e231e..a7d8cac 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -2374,16 +2374,18 @@
}
BluetoothDeviceProfileState addProfileState(String address, boolean setTrust) {
- BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
- if (state != null) return state;
-
- state = new BluetoothDeviceProfileState(mContext, address, this, mA2dpService, setTrust);
+ BluetoothDeviceProfileState state =
+ new BluetoothDeviceProfileState(mContext, address, this, mA2dpService, setTrust);
mDeviceProfileState.put(address, state);
state.start();
return state;
}
void removeProfileState(String address) {
+ BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
+ if (state == null) return;
+
+ state.quit();
mDeviceProfileState.remove(address);
}
diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java
index fd00dce..46a78dc 100644
--- a/core/java/android/speech/tts/AudioPlaybackHandler.java
+++ b/core/java/android/speech/tts/AudioPlaybackHandler.java
@@ -428,7 +428,8 @@
final AudioTrack audioTrack = params.getAudioTrack();
if (audioTrack == null) {
- params.getDispatcher().dispatchOnError();
+ // There was already a call to handleSynthesisDone for
+ // this token.
return;
}
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index 7cf4579..366abd3 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -134,6 +134,7 @@
if (i != o) {
keys[o] = keys[i];
values[o] = val;
+ values[i] = null;
}
o++;
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 6c3d387..f53e42c 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -579,8 +579,20 @@
/** Key code constant: 3D Mode key.
* Toggles the display between 2D and 3D mode. */
public static final int KEYCODE_3D_MODE = 206;
+ /** Key code constant: Contacts special function key.
+ * Used to launch an address book application. */
+ public static final int KEYCODE_CONTACTS = 207;
+ /** Key code constant: Calendar special function key.
+ * Used to launch a calendar application. */
+ public static final int KEYCODE_CALENDAR = 208;
+ /** Key code constant: Music special function key.
+ * Used to launch a music player application. */
+ public static final int KEYCODE_MUSIC = 209;
+ /** Key code constant: Calculator special function key.
+ * Used to launch a calculator application. */
+ public static final int KEYCODE_CALCULATOR = 210;
- private static final int LAST_KEYCODE = KEYCODE_BUTTON_16;
+ private static final int LAST_KEYCODE = KEYCODE_CALCULATOR;
// NOTE: If you add a new keycode here you must also add it to:
// isSystem()
@@ -589,6 +601,8 @@
// external/webkit/WebKit/android/plugins/ANPKeyCodes.h
// frameworks/base/core/res/res/values/attrs.xml
// emulator?
+ // LAST_KEYCODE
+ // KEYCODE_SYMBOLIC_NAMES
//
// Also Android currently does not reserve code ranges for vendor-
// specific key codes. If you have new key codes to have, you
@@ -807,6 +821,10 @@
names.append(KEYCODE_LANGUAGE_SWITCH, "KEYCODE_LANGUAGE_SWITCH");
names.append(KEYCODE_MANNER_MODE, "KEYCODE_MANNER_MODE");
names.append(KEYCODE_3D_MODE, "KEYCODE_3D_MODE");
+ names.append(KEYCODE_CONTACTS, "KEYCODE_CONTACTS");
+ names.append(KEYCODE_CALENDAR, "KEYCODE_CALENDAR");
+ names.append(KEYCODE_MUSIC, "KEYCODE_MUSIC");
+ names.append(KEYCODE_CALCULATOR, "KEYCODE_CALCULATOR");
};
// Symbolic names of all metakeys in bit order from least significant to most significant.
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 7bf0c83..91dcac8 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -16,7 +16,6 @@
package android.view.accessibility;
-import android.accessibilityservice.IAccessibilityServiceConnection;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -590,24 +589,6 @@
}
/**
- * Sets the connection for interacting with the AccessibilityManagerService.
- *
- * @param connection The connection.
- *
- * @hide
- */
- @Override
- public void setConnection(IAccessibilityServiceConnection connection) {
- super.setConnection(connection);
- List<AccessibilityRecord> records = mRecords;
- final int recordCount = records.size();
- for (int i = 0; i < recordCount; i++) {
- AccessibilityRecord record = records.get(i);
- record.setConnection(connection);
- }
- }
-
- /**
* Sets if this instance is sealed.
*
* @param sealed Whether is sealed.
@@ -821,23 +802,19 @@
* @param parcel A parcel containing the state of a {@link AccessibilityEvent}.
*/
public void initFromParcel(Parcel parcel) {
- if (parcel.readInt() == 1) {
- mConnection = IAccessibilityServiceConnection.Stub.asInterface(
- parcel.readStrongBinder());
- }
- setSealed(parcel.readInt() == 1);
+ mSealed = (parcel.readInt() == 1);
mEventType = parcel.readInt();
mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
mEventTime = parcel.readLong();
+ mConnectionId = parcel.readInt();
readAccessibilityRecordFromParcel(this, parcel);
// Read the records.
final int recordCount = parcel.readInt();
for (int i = 0; i < recordCount; i++) {
AccessibilityRecord record = AccessibilityRecord.obtain();
- // Do this to write the connection only once.
- record.setConnection(mConnection);
readAccessibilityRecordFromParcel(record, parcel);
+ record.mConnectionId = mConnectionId;
mRecords.add(record);
}
}
@@ -875,16 +852,11 @@
* {@inheritDoc}
*/
public void writeToParcel(Parcel parcel, int flags) {
- if (mConnection == null) {
- parcel.writeInt(0);
- } else {
- parcel.writeInt(1);
- parcel.writeStrongBinder(mConnection.asBinder());
- }
parcel.writeInt(isSealed() ? 1 : 0);
parcel.writeInt(mEventType);
TextUtils.writeToParcel(mPackageName, parcel, 0);
parcel.writeLong(mEventTime);
+ parcel.writeInt(mConnectionId);
writeAccessibilityRecordToParcel(this, parcel, flags);
// Write the records.
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 25b980b..00a7c87 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -21,6 +21,8 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.util.Log;
+import android.util.SparseArray;
import java.util.Collections;
import java.util.List;
@@ -61,6 +63,12 @@
public final class AccessibilityInteractionClient
extends IAccessibilityInteractionConnectionCallback.Stub {
+ public static final int NO_ID = -1;
+
+ private static final String LOG_TAG = "AccessibilityInteractionClient";
+
+ private static final boolean DEBUG = false;
+
private static final long TIMEOUT_INTERACTION_MILLIS = 5000;
private static final Object sStaticLock = new Object();
@@ -83,6 +91,9 @@
private final Rect mTempBounds = new Rect();
+ private final SparseArray<IAccessibilityServiceConnection> mConnectionCache =
+ new SparseArray<IAccessibilityServiceConnection>();
+
/**
* @return The singleton of this class.
*/
@@ -111,28 +122,37 @@
/**
* Finds an {@link AccessibilityNodeInfo} by accessibility id.
*
- * @param connection A connection for interacting with the system.
+ * @param connectionId The id of a connection for interacting with the system.
* @param accessibilityWindowId A unique window id.
* @param accessibilityViewId A unique View accessibility id.
* @return An {@link AccessibilityNodeInfo} if found, null otherwise.
*/
- public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(
- IAccessibilityServiceConnection connection, int accessibilityWindowId,
- int accessibilityViewId) {
+ public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(int connectionId,
+ int accessibilityWindowId, int accessibilityViewId) {
try {
- final int interactionId = mInteractionIdCounter.getAndIncrement();
- final float windowScale = connection.findAccessibilityNodeInfoByAccessibilityId(
- accessibilityWindowId, accessibilityViewId, interactionId, this,
- Thread.currentThread().getId());
- // If the scale is zero the call has failed.
- if (windowScale > 0) {
- AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
- interactionId);
- finalizeAccessibilityNodeInfo(info, connection, windowScale);
- return info;
+ IAccessibilityServiceConnection connection = getConnection(connectionId);
+ if (connection != null) {
+ final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final float windowScale = connection.findAccessibilityNodeInfoByAccessibilityId(
+ accessibilityWindowId, accessibilityViewId, interactionId, this,
+ Thread.currentThread().getId());
+ // If the scale is zero the call has failed.
+ if (windowScale > 0) {
+ AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
+ interactionId);
+ finalizeAccessibilityNodeInfo(info, connectionId, windowScale);
+ return info;
+ }
+ } else {
+ if (DEBUG) {
+ Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+ }
}
} catch (RemoteException re) {
- /* ignore */
+ if (DEBUG) {
+ Log.w(LOG_TAG, "Error while calling remote"
+ + " findAccessibilityNodeInfoByAccessibilityId", re);
+ }
}
return null;
}
@@ -141,25 +161,36 @@
* Finds an {@link AccessibilityNodeInfo} by View id. The search is performed
* in the currently active window and starts from the root View in the window.
*
- * @param connection A connection for interacting with the system.
+ * @param connectionId The id of a connection for interacting with the system.
* @param viewId The id of the view.
* @return An {@link AccessibilityNodeInfo} if found, null otherwise.
*/
- public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(
- IAccessibilityServiceConnection connection, int viewId) {
+ public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(int connectionId,
+ int viewId) {
try {
- final int interactionId = mInteractionIdCounter.getAndIncrement();
- final float windowScale = connection.findAccessibilityNodeInfoByViewIdInActiveWindow(
- viewId, interactionId, this, Thread.currentThread().getId());
- // If the scale is zero the call has failed.
- if (windowScale > 0) {
- AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
- interactionId);
- finalizeAccessibilityNodeInfo(info, connection, windowScale);
- return info;
+ IAccessibilityServiceConnection connection = getConnection(connectionId);
+ if (connection != null) {
+ final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final float windowScale =
+ connection.findAccessibilityNodeInfoByViewIdInActiveWindow(viewId,
+ interactionId, this, Thread.currentThread().getId());
+ // If the scale is zero the call has failed.
+ if (windowScale > 0) {
+ AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
+ interactionId);
+ finalizeAccessibilityNodeInfo(info, connectionId, windowScale);
+ return info;
+ }
+ } else {
+ if (DEBUG) {
+ Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+ }
}
} catch (RemoteException re) {
- /* ignore */
+ if (DEBUG) {
+ Log.w(LOG_TAG, "Error while calling remote"
+ + " findAccessibilityNodeInfoByViewIdInActiveWindow", re);
+ }
}
return null;
}
@@ -169,25 +200,36 @@
* insensitive containment. The search is performed in the currently
* active window and starts from the root View in the window.
*
- * @param connection A connection for interacting with the system.
+ * @param connectionId The id of a connection for interacting with the system.
* @param text The searched text.
* @return A list of found {@link AccessibilityNodeInfo}s.
*/
public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewTextInActiveWindow(
- IAccessibilityServiceConnection connection, String text) {
+ int connectionId, String text) {
try {
- final int interactionId = mInteractionIdCounter.getAndIncrement();
- final float windowScale = connection.findAccessibilityNodeInfosByViewTextInActiveWindow(
- text, interactionId, this, Thread.currentThread().getId());
- // If the scale is zero the call has failed.
- if (windowScale > 0) {
- List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
- interactionId);
- finalizeAccessibilityNodeInfos(infos, connection, windowScale);
- return infos;
+ IAccessibilityServiceConnection connection = getConnection(connectionId);
+ if (connection != null) {
+ final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final float windowScale =
+ connection.findAccessibilityNodeInfosByViewTextInActiveWindow(text,
+ interactionId, this, Thread.currentThread().getId());
+ // If the scale is zero the call has failed.
+ if (windowScale > 0) {
+ List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
+ interactionId);
+ finalizeAccessibilityNodeInfos(infos, connectionId, windowScale);
+ return infos;
+ }
+ } else {
+ if (DEBUG) {
+ Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+ }
}
} catch (RemoteException re) {
- /* ignore */
+ if (DEBUG) {
+ Log.w(LOG_TAG, "Error while calling remote"
+ + " findAccessibilityNodeInfosByViewTextInActiveWindow", re);
+ }
}
return null;
}
@@ -198,30 +240,39 @@
* id is specified and starts from the View whose accessibility id is
* specified.
*
- * @param connection A connection for interacting with the system.
+ * @param connectionId The id of a connection for interacting with the system.
* @param text The searched text.
* @param accessibilityWindowId A unique window id.
* @param accessibilityViewId A unique View accessibility id from where to start the search.
* Use {@link android.view.View#NO_ID} to start from the root.
* @return A list of found {@link AccessibilityNodeInfo}s.
*/
- public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(
- IAccessibilityServiceConnection connection, String text, int accessibilityWindowId,
- int accessibilityViewId) {
+ public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(int connectionId,
+ String text, int accessibilityWindowId, int accessibilityViewId) {
try {
- final int interactionId = mInteractionIdCounter.getAndIncrement();
- final float windowScale = connection.findAccessibilityNodeInfosByViewText(text,
- accessibilityWindowId, accessibilityViewId, interactionId, this,
- Thread.currentThread().getId());
- // If the scale is zero the call has failed.
- if (windowScale > 0) {
- List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
- interactionId);
- finalizeAccessibilityNodeInfos(infos, connection, windowScale);
- return infos;
+ IAccessibilityServiceConnection connection = getConnection(connectionId);
+ if (connection != null) {
+ final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final float windowScale = connection.findAccessibilityNodeInfosByViewText(text,
+ accessibilityWindowId, accessibilityViewId, interactionId, this,
+ Thread.currentThread().getId());
+ // If the scale is zero the call has failed.
+ if (windowScale > 0) {
+ List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
+ interactionId);
+ finalizeAccessibilityNodeInfos(infos, connectionId, windowScale);
+ return infos;
+ }
+ } else {
+ if (DEBUG) {
+ Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+ }
}
} catch (RemoteException re) {
- /* ignore */
+ if (DEBUG) {
+ Log.w(LOG_TAG, "Error while calling remote"
+ + " findAccessibilityNodeInfosByViewText", re);
+ }
}
return Collections.emptyList();
}
@@ -229,24 +280,33 @@
/**
* Performs an accessibility action on an {@link AccessibilityNodeInfo}.
*
- * @param connection A connection for interacting with the system.
+ * @param connectionId The id of a connection for interacting with the system.
* @param accessibilityWindowId The id of the window.
* @param accessibilityViewId A unique View accessibility id.
* @param action The action to perform.
* @return Whether the action was performed.
*/
- public boolean performAccessibilityAction(IAccessibilityServiceConnection connection,
- int accessibilityWindowId, int accessibilityViewId, int action) {
+ public boolean performAccessibilityAction(int connectionId, int accessibilityWindowId,
+ int accessibilityViewId, int action) {
try {
- final int interactionId = mInteractionIdCounter.getAndIncrement();
- final boolean success = connection.performAccessibilityAction(
- accessibilityWindowId, accessibilityViewId, action, interactionId, this,
- Thread.currentThread().getId());
- if (success) {
- return getPerformAccessibilityActionResult(interactionId);
+ IAccessibilityServiceConnection connection = getConnection(connectionId);
+ if (connection != null) {
+ final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final boolean success = connection.performAccessibilityAction(
+ accessibilityWindowId, accessibilityViewId, action, interactionId, this,
+ Thread.currentThread().getId());
+ if (success) {
+ return getPerformAccessibilityActionResult(interactionId);
+ }
+ } else {
+ if (DEBUG) {
+ Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+ }
}
} catch (RemoteException re) {
- /* ignore */
+ if (DEBUG) {
+ Log.w(LOG_TAG, "Error while calling remote performAccessibilityAction", re);
+ }
}
return false;
}
@@ -406,14 +466,14 @@
* Finalize an {@link AccessibilityNodeInfo} before passing it to the client.
*
* @param info The info.
- * @param connection The current connection to the system.
+ * @param connectionId The id of the connection to the system.
* @param windowScale The source window compatibility scale.
*/
- private void finalizeAccessibilityNodeInfo(AccessibilityNodeInfo info,
- IAccessibilityServiceConnection connection, float windowScale) {
+ private void finalizeAccessibilityNodeInfo(AccessibilityNodeInfo info, int connectionId,
+ float windowScale) {
if (info != null) {
applyCompatibilityScaleIfNeeded(info, windowScale);
- info.setConnection(connection);
+ info.setConnectionId(connectionId);
info.setSealed(true);
}
}
@@ -422,16 +482,16 @@
* Finalize {@link AccessibilityNodeInfo}s before passing them to the client.
*
* @param infos The {@link AccessibilityNodeInfo}s.
- * @param connection The current connection to the system.
+ * @param connectionId The id of the connection to the system.
* @param windowScale The source window compatibility scale.
*/
private void finalizeAccessibilityNodeInfos(List<AccessibilityNodeInfo> infos,
- IAccessibilityServiceConnection connection, float windowScale) {
+ int connectionId, float windowScale) {
if (infos != null) {
final int infosCount = infos.size();
for (int i = 0; i < infosCount; i++) {
AccessibilityNodeInfo info = infos.get(i);
- finalizeAccessibilityNodeInfo(info, connection, windowScale);
+ finalizeAccessibilityNodeInfo(info, connectionId, windowScale);
}
}
}
@@ -449,4 +509,39 @@
return result;
}
}
+
+ /**
+ * Gets a cached accessibility service connection.
+ *
+ * @param connectionId The connection id.
+ * @return The cached connection if such.
+ */
+ public IAccessibilityServiceConnection getConnection(int connectionId) {
+ synchronized (mConnectionCache) {
+ return mConnectionCache.get(connectionId);
+ }
+ }
+
+ /**
+ * Adds a cached accessibility service connection.
+ *
+ * @param connectionId The connection id.
+ * @param connection The connection.
+ */
+ public void addConnection(int connectionId, IAccessibilityServiceConnection connection) {
+ synchronized (mConnectionCache) {
+ mConnectionCache.put(connectionId, connection);
+ }
+ }
+
+ /**
+ * Removes a cached accessibility service connection.
+ *
+ * @param connectionId The connection id.
+ */
+ public void removeConnection(int connectionId) {
+ synchronized (mConnectionCache) {
+ mConnectionCache.remove(connectionId);
+ }
+ }
}
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index fa34ee7..9b0f44a 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -16,7 +16,6 @@
package android.view.accessibility;
-import android.accessibilityservice.IAccessibilityServiceConnection;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
@@ -53,6 +52,8 @@
private static final boolean DEBUG = false;
+ private static final int UNDEFINED = -1;
+
// Actions.
/**
@@ -107,9 +108,9 @@
private boolean mSealed;
// Data.
- private int mAccessibilityViewId = View.NO_ID;
- private int mAccessibilityWindowId = View.NO_ID;
- private int mParentAccessibilityViewId = View.NO_ID;
+ private int mAccessibilityViewId = UNDEFINED;
+ private int mAccessibilityWindowId = UNDEFINED;
+ private int mParentAccessibilityViewId = UNDEFINED;
private int mBooleanProperties;
private final Rect mBoundsInParent = new Rect();
private final Rect mBoundsInScreen = new Rect();
@@ -122,7 +123,7 @@
private SparseIntArray mChildAccessibilityIds = new SparseIntArray();
private int mActions;
- private IAccessibilityServiceConnection mConnection;
+ private int mConnectionId = UNDEFINED;
/**
* Hide constructor from clients.
@@ -181,7 +182,7 @@
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfoByAccessibilityId(mConnection,
+ return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
mAccessibilityWindowId, childAccessibilityViewId);
}
@@ -253,7 +254,7 @@
return false;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.performAccessibilityAction(mConnection, mAccessibilityWindowId,
+ return client.performAccessibilityAction(mConnectionId, mAccessibilityWindowId,
mAccessibilityViewId, action);
}
@@ -277,7 +278,7 @@
return Collections.emptyList();
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfosByViewText(mConnection, text,
+ return client.findAccessibilityNodeInfosByViewText(mConnectionId, text,
mAccessibilityWindowId, mAccessibilityViewId);
}
@@ -297,7 +298,7 @@
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfoByAccessibilityId(mConnection,
+ return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
mAccessibilityWindowId, mParentAccessibilityViewId);
}
@@ -755,15 +756,16 @@
}
/**
- * Sets the connection for interacting with the system.
+ * Sets the unique id of the IAccessibilityServiceConnection over which
+ * this instance can send requests to the system.
*
- * @param connection The client token.
+ * @param connectionId The connection id.
*
* @hide
*/
- public final void setConnection(IAccessibilityServiceConnection connection) {
+ public void setConnectionId(int connectionId) {
enforceNotSealed();
- mConnection = connection;
+ mConnectionId = connectionId;
}
/**
@@ -900,16 +902,11 @@
* </p>
*/
public void writeToParcel(Parcel parcel, int flags) {
- if (mConnection == null) {
- parcel.writeInt(0);
- } else {
- parcel.writeInt(1);
- parcel.writeStrongBinder(mConnection.asBinder());
- }
parcel.writeInt(isSealed() ? 1 : 0);
parcel.writeInt(mAccessibilityViewId);
parcel.writeInt(mAccessibilityWindowId);
parcel.writeInt(mParentAccessibilityViewId);
+ parcel.writeInt(mConnectionId);
SparseIntArray childIds = mChildAccessibilityIds;
final int childIdsSize = childIds.size();
@@ -949,10 +946,10 @@
*/
private void init(AccessibilityNodeInfo other) {
mSealed = other.mSealed;
- mConnection = other.mConnection;
mAccessibilityViewId = other.mAccessibilityViewId;
mParentAccessibilityViewId = other.mParentAccessibilityViewId;
mAccessibilityWindowId = other.mAccessibilityWindowId;
+ mConnectionId = other.mConnectionId;
mBoundsInParent.set(other.mBoundsInParent);
mBoundsInScreen.set(other.mBoundsInScreen);
mPackageName = other.mPackageName;
@@ -970,14 +967,11 @@
* @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}.
*/
private void initFromParcel(Parcel parcel) {
- if (parcel.readInt() == 1) {
- mConnection = IAccessibilityServiceConnection.Stub.asInterface(
- parcel.readStrongBinder());
- }
mSealed = (parcel.readInt() == 1);
mAccessibilityViewId = parcel.readInt();
mAccessibilityWindowId = parcel.readInt();
mParentAccessibilityViewId = parcel.readInt();
+ mConnectionId = parcel.readInt();
SparseIntArray childIds = mChildAccessibilityIds;
final int childrenSize = parcel.readInt();
@@ -1011,10 +1005,10 @@
*/
private void clear() {
mSealed = false;
- mConnection = null;
- mAccessibilityViewId = View.NO_ID;
- mParentAccessibilityViewId = View.NO_ID;
- mAccessibilityWindowId = View.NO_ID;
+ mAccessibilityViewId = UNDEFINED;
+ mParentAccessibilityViewId = UNDEFINED;
+ mAccessibilityWindowId = UNDEFINED;
+ mConnectionId = UNDEFINED;
mChildAccessibilityIds.clear();
mBoundsInParent.set(0, 0, 0, 0);
mBoundsInScreen.set(0, 0, 0, 0);
@@ -1048,9 +1042,8 @@
}
private boolean canPerformRequestOverConnection(int accessibilityViewId) {
- return (mAccessibilityWindowId != View.NO_ID
- && accessibilityViewId != View.NO_ID
- && mConnection != null);
+ return (mConnectionId != UNDEFINED && mAccessibilityWindowId != UNDEFINED
+ && accessibilityViewId != UNDEFINED);
}
@Override
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index a4e0688..18d0f6f 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -16,7 +16,6 @@
package android.view.accessibility;
-import android.accessibilityservice.IAccessibilityServiceConnection;
import android.os.Parcelable;
import android.view.View;
@@ -78,8 +77,8 @@
int mAddedCount= UNDEFINED;
int mRemovedCount = UNDEFINED;
- int mSourceViewId = View.NO_ID;
- int mSourceWindowId = View.NO_ID;
+ int mSourceViewId = UNDEFINED;
+ int mSourceWindowId = UNDEFINED;
CharSequence mClassName;
CharSequence mContentDescription;
@@ -87,7 +86,8 @@
Parcelable mParcelableData;
final List<CharSequence> mText = new ArrayList<CharSequence>();
- IAccessibilityServiceConnection mConnection;
+
+ int mConnectionId = UNDEFINED;
/*
* Hide constructor.
@@ -108,8 +108,8 @@
mSourceWindowId = source.getAccessibilityWindowId();
mSourceViewId = source.getAccessibilityViewId();
} else {
- mSourceWindowId = View.NO_ID;
- mSourceViewId = View.NO_ID;
+ mSourceWindowId = UNDEFINED;
+ mSourceViewId = UNDEFINED;
}
}
@@ -119,33 +119,21 @@
* <strong>Note:</strong> It is a client responsibility to recycle the received info
* by calling {@link AccessibilityNodeInfo#recycle() AccessibilityNodeInfo#recycle()}
* to avoid creating of multiple instances.
- *
* </p>
* @return The info of the source.
*/
public AccessibilityNodeInfo getSource() {
enforceSealed();
- if (mSourceWindowId == View.NO_ID || mSourceViewId == View.NO_ID || mConnection == null) {
+ if (mConnectionId == UNDEFINED || mSourceWindowId == UNDEFINED
+ || mSourceViewId == UNDEFINED) {
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfoByAccessibilityId(mConnection, mSourceWindowId,
+ return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mSourceWindowId,
mSourceViewId);
}
/**
- * Sets the connection for interacting with the AccessibilityManagerService.
- *
- * @param connection The connection.
- *
- * @hide
- */
- public void setConnection(IAccessibilityServiceConnection connection) {
- enforceNotSealed();
- mConnection = connection;
- }
-
- /**
* Gets the id of the window from which the event comes from.
*
* @return The window id.
@@ -561,6 +549,19 @@
}
/**
+ * Sets the unique id of the IAccessibilityServiceConnection over which
+ * this instance can send requests to the system.
+ *
+ * @param connectionId The connection id.
+ *
+ * @hide
+ */
+ public void setConnectionId(int connectionId) {
+ enforceNotSealed();
+ mConnectionId = connectionId;
+ }
+
+ /**
* Sets if this instance is sealed.
*
* @param sealed Whether is sealed.
@@ -708,7 +709,7 @@
mText.addAll(record.mText);
mSourceWindowId = record.mSourceWindowId;
mSourceViewId = record.mSourceViewId;
- mConnection = record.mConnection;
+ mConnectionId = record.mConnectionId;
}
/**
@@ -732,8 +733,9 @@
mBeforeText = null;
mParcelableData = null;
mText.clear();
- mSourceViewId = View.NO_ID;
- mSourceWindowId = View.NO_ID;
+ mSourceViewId = UNDEFINED;
+ mSourceWindowId = UNDEFINED;
+ mConnectionId = UNDEFINED;
}
@Override
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index c621ff6..c3794be 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -49,5 +49,5 @@
void removeAccessibilityInteractionConnection(IWindow windowToken);
- IAccessibilityServiceConnection registerEventListener(IEventListener client);
+ void registerEventListener(IEventListener client);
}
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index d6e36bb..9fa5593 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -345,6 +345,11 @@
* a system private class.
*/
public synchronized void setCookie(WebAddress uri, String value) {
+ if (JniUtil.useChromiumHttpStack()) {
+ nativeSetCookie(uri.toString(), value, false);
+ return;
+ }
+
if (value != null && value.length() > MAX_COOKIE_LENGTH) {
return;
}
@@ -500,6 +505,10 @@
* is a system private class.
*/
public synchronized String getCookie(WebAddress uri) {
+ if (JniUtil.useChromiumHttpStack()) {
+ return nativeGetCookie(uri.toString(), false);
+ }
+
if (!mAcceptCookie || uri == null) {
return null;
}
@@ -573,6 +582,8 @@
* {@hide} Too late to release publically.
*/
public void waitForCookieOperationsToComplete() {
+ // Note that this function is applicable for both the java
+ // and native http stacks, and works correctly with either.
synchronized (this) {
while (pendingCookieOperations > 0) {
try {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 2af6e3b..24eebd7 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -507,7 +507,7 @@
private float mLastVelY;
// The id of the native layer being scrolled.
- private int mScrollingLayer;
+ private int mCurrentScrollingLayerId;
private Rect mScrollingLayerRect = new Rect();
// only trigger accelerated fling if the new velocity is at least
@@ -3665,7 +3665,7 @@
if (x == mScrollingLayerRect.left && y == mScrollingLayerRect.top) {
return;
}
- nativeScrollLayer(mScrollingLayer, x, y);
+ nativeScrollLayer(mCurrentScrollingLayerId, x, y);
mScrollingLayerRect.left = x;
mScrollingLayerRect.top = y;
onScrollChanged(mScrollX, mScrollY, mScrollX, mScrollY);
@@ -4470,6 +4470,7 @@
Rect vBox = contentToViewRect(contentBounds);
Rect visibleRect = new Rect();
calcOurVisibleRect(visibleRect);
+ offsetByLayerScrollPosition(vBox);
// If the textfield is on screen, place the WebTextView in
// its new place, accounting for our new scroll/zoom values,
// and adjust its textsize.
@@ -4505,6 +4506,14 @@
}
}
+ private void offsetByLayerScrollPosition(Rect box) {
+ if ((mCurrentScrollingLayerId != 0)
+ && (mCurrentScrollingLayerId == nativeFocusCandidateLayerId())) {
+ box.offsetTo(box.left - mScrollingLayerRect.left,
+ box.top - mScrollingLayerRect.top);
+ }
+ }
+
void setBaseLayer(int layer, Region invalRegion, boolean showVisualIndicator,
boolean isPictureAfterFirstLayout, boolean registerPageSwapCallback) {
if (mNativeClass == 0)
@@ -4604,14 +4613,15 @@
boolean UIAnimationsRunning = false;
// Currently for each draw we compute the animation values;
// We may in the future decide to do that independently.
- if (mNativeClass != 0 && nativeEvaluateLayersAnimations(mNativeClass)) {
+ if (mNativeClass != 0 && !canvas.isHardwareAccelerated()
+ && nativeEvaluateLayersAnimations(mNativeClass)) {
UIAnimationsRunning = true;
// If we have unfinished (or unstarted) animations,
// we ask for a repaint. We only need to do this in software
// rendering (with hardware rendering we already have a different
// method of requesting a repaint)
- if (!canvas.isHardwareAccelerated())
- invalidate();
+ mWebViewCore.sendMessage(EventHub.NOTIFY_ANIMATION_STARTED);
+ invalidate();
}
// decide which adornments to draw
@@ -4922,6 +4932,7 @@
// should be in content coordinates.
Rect bounds = nativeFocusCandidateNodeBounds();
Rect vBox = contentToViewRect(bounds);
+ offsetByLayerScrollPosition(vBox);
mWebTextView.setRect(vBox.left, vBox.top, vBox.width(), vBox.height());
if (!Rect.intersects(bounds, visibleRect)) {
revealSelection();
@@ -5513,10 +5524,10 @@
mMaxAutoScrollX = getViewWidth();
mMinAutoScrollY = 0;
mMaxAutoScrollY = getViewHeightWithTitle();
- mScrollingLayer = nativeScrollableLayer(viewToContentX(mSelectX),
+ mCurrentScrollingLayerId = nativeScrollableLayer(viewToContentX(mSelectX),
viewToContentY(mSelectY), mScrollingLayerRect,
mScrollingLayerBounds);
- if (mScrollingLayer != 0) {
+ if (mCurrentScrollingLayerId != 0) {
if (mScrollingLayerRect.left != mScrollingLayerRect.right) {
mMinAutoScrollX = Math.max(mMinAutoScrollX,
contentToViewX(mScrollingLayerBounds.left));
@@ -6002,9 +6013,9 @@
private void startScrollingLayer(float x, float y) {
int contentX = viewToContentX((int) x + mScrollX);
int contentY = viewToContentY((int) y + mScrollY);
- mScrollingLayer = nativeScrollableLayer(contentX, contentY,
+ mCurrentScrollingLayerId = nativeScrollableLayer(contentX, contentY,
mScrollingLayerRect, mScrollingLayerBounds);
- if (mScrollingLayer != 0) {
+ if (mCurrentScrollingLayerId != 0) {
mTouchMode = TOUCH_DRAG_LAYER_MODE;
}
}
@@ -6235,7 +6246,7 @@
ted.mPointsInView[0] = new Point(x, y);
ted.mMetaState = ev.getMetaState();
ted.mReprocess = mDeferTouchProcess;
- ted.mNativeLayer = mScrollingLayer;
+ ted.mNativeLayer = mCurrentScrollingLayerId;
ted.mNativeLayerRect.set(mScrollingLayerRect);
ted.mSequence = mTouchEventQueue.nextTouchSequence();
mTouchEventQueue.preQueueTouchEventData(ted);
@@ -6426,7 +6437,7 @@
ted.mPointsInView[0] = new Point(x, y);
ted.mMetaState = ev.getMetaState();
ted.mReprocess = mDeferTouchProcess;
- ted.mNativeLayer = mScrollingLayer;
+ ted.mNativeLayer = mCurrentScrollingLayerId;
ted.mNativeLayerRect.set(mScrollingLayerRect);
ted.mSequence = mTouchEventQueue.nextTouchSequence();
mTouchEventQueue.preQueueTouchEventData(ted);
@@ -6735,7 +6746,7 @@
// directions. mTouchMode might be TOUCH_DRAG_MODE if we have
// reached the edge of a layer but mScrollingLayer will be non-zero
// if we initiated the drag on a layer.
- if (mScrollingLayer != 0) {
+ if (mCurrentScrollingLayerId != 0) {
final int contentX = viewToContentDimension(deltaX);
final int contentY = viewToContentDimension(deltaY);
@@ -7257,7 +7268,7 @@
+ " vx=" + vx + " vy=" + vy
+ " maxX=" + maxX + " maxY=" + maxY
+ " scrollX=" + scrollX + " scrollY=" + scrollY
- + " layer=" + mScrollingLayer);
+ + " layer=" + mCurrentScrollingLayerId);
}
// Allow sloppy flings without overscrolling at the edges.
@@ -8366,7 +8377,7 @@
mSentAutoScrollMessage = false;
break;
}
- if (mScrollingLayer == 0) {
+ if (mCurrentScrollingLayerId == 0) {
pinScrollBy(mAutoScrollX, mAutoScrollY, true, 0);
} else {
scrollLayerTo(mScrollingLayerRect.left + mAutoScrollX,
@@ -8796,10 +8807,13 @@
/** @hide Called by JNI when pages are swapped (only occurs with hardware
* acceleration) */
- protected void pageSwapCallback() {
+ protected void pageSwapCallback(boolean notifyAnimationStarted) {
if (inEditingMode()) {
didUpdateWebTextViewDimensions(ANYWHERE);
}
+ if (notifyAnimationStarted) {
+ mWebViewCore.sendMessage(EventHub.NOTIFY_ANIMATION_STARTED);
+ }
}
void setNewPicture(final WebViewCore.DrawData draw, boolean updateBaseLayer) {
@@ -9577,6 +9591,7 @@
* See WebTextView.setType()
*/
private native int nativeFocusCandidateType();
+ private native int nativeFocusCandidateLayerId();
private native boolean nativeFocusIsPlugin();
private native Rect nativeFocusNodeBounds();
/* package */ native int nativeFocusNodePointer();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 2ad866b..d136004 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -519,7 +519,12 @@
/**
* Update the layers' content
*/
- private native boolean nativeUpdateLayers(int baseLayer);
+ private native boolean nativeUpdateLayers(int nativeClass, int baseLayer);
+
+ /**
+ * Notify webkit that animations have begun (on the hardware accelerated content)
+ */
+ private native void nativeNotifyAnimationStarted(int nativeClass);
private native boolean nativeFocusBoundsChanged();
@@ -1035,6 +1040,8 @@
static final int PLUGIN_SURFACE_READY = 195;
+ static final int NOTIFY_ANIMATION_STARTED = 196;
+
// private message ids
private static final int DESTROY = 200;
@@ -1594,6 +1601,10 @@
nativePluginSurfaceReady();
break;
+ case NOTIFY_ANIMATION_STARTED:
+ nativeNotifyAnimationStarted(mNativeClass);
+ break;
+
case ADD_PACKAGE_NAMES:
if (BrowserFrame.sJavaBridge == null) {
throw new IllegalStateException("No WebView " +
@@ -2015,7 +2026,7 @@
return;
}
// Directly update the layers we last passed to the UI side
- if (nativeUpdateLayers(mLastDrawData.mBaseLayer)) {
+ if (nativeUpdateLayers(mNativeClass, mLastDrawData.mBaseLayer)) {
// If anything more complex than position has been touched, let's do a full draw
webkitDraw();
}
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index cf2c8a6..8c57265 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -493,6 +493,9 @@
if (mHardwareAccelerated) {
mWebView.updateScrollCoordinates(mWebView.getScrollX() - tx, mWebView.getScrollY() - ty);
+ // By adding webView matrix, we need to offset the canvas a bit
+ // to make the animation smooth.
+ canvas.translate(tx, ty);
setZoomScale(zoomScale, false);
if (mZoomScale == 0) {
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 1a1b8d0..d185370 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -165,6 +165,11 @@
};
/**
+ * Constant for unspecified size.
+ */
+ private static final int SIZE_UNSPECIFIED = -1;
+
+ /**
* Use a custom NumberPicker formatting callback to use two-digit minutes
* strings like "01". Keeping a static formatter etc. is the most efficient
* way to do this; it avoids creating temporary objects on every call to
@@ -542,16 +547,20 @@
getResources().getDisplayMetrics());
mSelectionDividerHeight = attributesArray.getDimensionPixelSize(
R.styleable.NumberPicker_selectionDividerHeight, defSelectionDividerHeight);
- mMinHeight = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_minHeight, 0);
+ mMinHeight = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_minHeight,
+ SIZE_UNSPECIFIED);
mMaxHeight = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_maxHeight,
- Integer.MAX_VALUE);
- if (mMinHeight > mMaxHeight) {
+ SIZE_UNSPECIFIED);
+ if (mMinHeight != SIZE_UNSPECIFIED && mMaxHeight != SIZE_UNSPECIFIED
+ && mMinHeight > mMaxHeight) {
throw new IllegalArgumentException("minHeight > maxHeight");
}
- mMinWidth = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_minWidth, 0);
+ mMinWidth = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_minWidth,
+ SIZE_UNSPECIFIED);
mMaxWidth = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_maxWidth,
- Integer.MAX_VALUE);
- if (mMinWidth > mMaxWidth) {
+ SIZE_UNSPECIFIED);
+ if (mMinWidth != SIZE_UNSPECIFIED && mMaxWidth != SIZE_UNSPECIFIED
+ && mMinWidth > mMaxWidth) {
throw new IllegalArgumentException("minWidth > maxWidth");
}
mComputeMaxWidth = (mMaxWidth == Integer.MAX_VALUE);
@@ -746,10 +755,10 @@
final int newHeightMeasureSpec = makeMeasureSpec(heightMeasureSpec, mMaxHeight);
super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec);
// Flag if we are measured with width or height less than the respective min.
- final int desiredWidth = Math.max(mMinWidth, getMeasuredWidth());
- final int desiredHeight = Math.max(mMinHeight, getMeasuredHeight());
- final int widthSize = resolveSizeAndState(desiredWidth, newWidthMeasureSpec, 0);
- final int heightSize = resolveSizeAndState(desiredHeight, newHeightMeasureSpec, 0);
+ final int widthSize = resolveSizeAndStateRespectingMinSize(mMinWidth, getMeasuredWidth(),
+ widthMeasureSpec);
+ final int heightSize = resolveSizeAndStateRespectingMinSize(mMinHeight, getMeasuredHeight(),
+ heightMeasureSpec);
setMeasuredDimension(widthSize, heightSize);
}
@@ -1243,6 +1252,7 @@
}
updateInputTextView();
initializeSelectorWheelIndices();
+ tryComputeMaxWidth();
}
@Override
@@ -1368,6 +1378,9 @@
* @return A measure spec greedily imposing the max size.
*/
private int makeMeasureSpec(int measureSpec, int maxSize) {
+ if (maxSize == SIZE_UNSPECIFIED) {
+ return measureSpec;
+ }
final int size = MeasureSpec.getSize(measureSpec);
final int mode = MeasureSpec.getMode(measureSpec);
switch (mode) {
@@ -1383,6 +1396,26 @@
}
/**
+ * Utility to reconcile a desired size and state, with constraints imposed by
+ * a MeasureSpec. Tries to respect the min size, unless a different size is
+ * imposed by the constraints.
+ *
+ * @param minSize The minimal desired size.
+ * @param measuredSize The currently measured size.
+ * @param measureSpec The current measure spec.
+ * @return The resolved size and state.
+ */
+ private int resolveSizeAndStateRespectingMinSize(int minSize, int measuredSize,
+ int measureSpec) {
+ if (minSize != SIZE_UNSPECIFIED) {
+ final int desiredWidth = Math.max(minSize, measuredSize);
+ return resolveSizeAndState(desiredWidth, measureSpec, 0);
+ } else {
+ return measuredSize;
+ }
+ }
+
+ /**
* Resets the selector indices and clear the cached
* string representation of these indices.
*/
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 185cfa9..cbd0808 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3816,7 +3816,6 @@
if (imm != null && imm.isActive(this)) {
imm.hideSoftInputFromWindow(getWindowToken(), 0);
}
- clearFocus();
return;
}
}
@@ -3838,7 +3837,7 @@
| KeyEvent.FLAG_EDITOR_ACTION)));
}
}
-
+
/**
* Set the private content type of the text, which is the
* {@link EditorInfo#privateImeOptions EditorInfo.privateImeOptions}
@@ -5594,8 +5593,6 @@
outAttrs.extras = mInputContentType.extras;
} else {
outAttrs.imeOptions = EditorInfo.IME_NULL;
- // May not be defined otherwise and needed by onEditorAction
- mInputContentType = new InputContentType();
}
if (focusSearch(FOCUS_DOWN) != null) {
outAttrs.imeOptions |= EditorInfo.IME_FLAG_NAVIGATE_NEXT;
@@ -7613,6 +7610,13 @@
list.get(i).onTextChanged(text, start, before, after);
}
}
+
+ updateSpellCheckSpans(start, start + after);
+
+ // Hide the controllers as soon as text is modified (typing, procedural...)
+ // We do not hide the span controllers, since they can be added when a new text is
+ // inserted into the text view (voice IME).
+ hideCursorControllers();
}
/**
@@ -7652,15 +7656,6 @@
sendOnTextChanged(buffer, start, before, after);
onTextChanged(buffer, start, before, after);
-
- updateSpellCheckSpans(start, start + after);
-
- // Hide the controllers if the amount of content changed
- if (before != after) {
- // We do not hide the span controllers, as they can be added when a new text is
- // inserted into the text view
- hideCursorControllers();
- }
}
/**
@@ -7963,16 +7958,12 @@
@Override
public void onClick(View view) {
if (view == mDeleteTextView) {
- deleteText();
- }
- }
-
- private void deleteText() {
- Editable editable = (Editable) mText;
- int start = editable.getSpanStart(mEasyEditSpan);
- int end = editable.getSpanEnd(mEasyEditSpan);
- if (start >= 0 && end >= 0) {
- editable.delete(start, end);
+ Editable editable = (Editable) mText;
+ int start = editable.getSpanStart(mEasyEditSpan);
+ int end = editable.getSpanEnd(mEasyEditSpan);
+ if (start >= 0 && end >= 0) {
+ deleteText_internal(start, end);
+ }
}
}
@@ -9096,7 +9087,7 @@
case ID_CUT:
setPrimaryClip(ClipData.newPlainText(null, getTransformedText(min, max)));
- ((Editable) mText).delete(min, max);
+ deleteText_internal(min, max);
stopSelectionActionMode();
return true;
@@ -9127,7 +9118,7 @@
if (Character.isSpaceChar(charBefore) && Character.isSpaceChar(charAfter)) {
// Two spaces at beginning of paste: remove one
final int originalLength = mText.length();
- ((Editable) mText).delete(min - 1, min);
+ deleteText_internal(min - 1, min);
// Due to filters, there is no guarantee that exactly one character was
// removed: count instead.
final int delta = mText.length() - originalLength;
@@ -9137,7 +9128,7 @@
!Character.isSpaceChar(charAfter) && charAfter != '\n') {
// No space at beginning of paste: add one
final int originalLength = mText.length();
- ((Editable) mText).replace(min, min, " ");
+ replaceText_internal(min, min, " ");
// Taking possible filters into account as above.
final int delta = mText.length() - originalLength;
min += delta;
@@ -9151,11 +9142,11 @@
if (Character.isSpaceChar(charBefore) && Character.isSpaceChar(charAfter)) {
// Two spaces at end of paste: remove one
- ((Editable) mText).delete(max, max + 1);
+ deleteText_internal(max, max + 1);
} else if (!Character.isSpaceChar(charBefore) && charBefore != '\n' &&
!Character.isSpaceChar(charAfter) && charAfter != '\n') {
// No space at end of paste: add one
- ((Editable) mText).replace(max, max, " ");
+ replaceText_internal(max, max, " ");
}
}
}
@@ -9867,9 +9858,7 @@
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- TextView textView = (TextView) view;
Editable editable = (Editable) mText;
-
SuggestionInfo suggestionInfo = mSuggestionInfos[position];
if (suggestionInfo.suggestionIndex == DELETE_TEXT) {
@@ -9883,7 +9872,7 @@
Character.isSpaceChar(editable.charAt(spanUnionStart - 1)))) {
spanUnionEnd = spanUnionEnd + 1;
}
- editable.replace(spanUnionStart, spanUnionEnd, "");
+ deleteText_internal(spanUnionStart, spanUnionEnd);
}
hide();
return;
@@ -9904,6 +9893,7 @@
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().startActivity(intent);
// There is no way to know if the word was indeed added. Re-check.
+ // TODO The ExtractEditText should remove the span in the original text instead
editable.removeSpan(suggestionInfo.suggestionSpan);
updateSpellCheckSpans(spanStart, spanEnd);
} else {
@@ -9931,9 +9921,9 @@
final int suggestionStart = suggestionInfo.suggestionStart;
final int suggestionEnd = suggestionInfo.suggestionEnd;
- final String suggestion = textView.getText().subSequence(
+ final String suggestion = suggestionInfo.text.subSequence(
suggestionStart, suggestionEnd).toString();
- editable.replace(spanStart, spanEnd, suggestion);
+ replaceText_internal(spanStart, spanEnd, suggestion);
// Notify source IME of the suggestion pick. Do this before swaping texts.
if (!TextUtils.isEmpty(
@@ -9957,6 +9947,7 @@
// way to assign them a valid range after replacement
if (suggestionSpansStarts[i] <= spanStart &&
suggestionSpansEnds[i] >= spanEnd) {
+ // TODO The ExtractEditText should restore these spans in the original text
editable.setSpan(suggestionSpans[i], suggestionSpansStarts[i],
suggestionSpansEnds[i] + lengthDifference, suggestionSpansFlags[i]);
}
@@ -10823,7 +10814,7 @@
// Handles can not cross and selection is at least one character
final int selectionEnd = getSelectionEnd();
- if (offset >= selectionEnd) offset = selectionEnd - 1;
+ if (offset >= selectionEnd) offset = Math.max(0, selectionEnd - 1);
positionAtCursorOffset(offset, false);
}
@@ -10865,7 +10856,7 @@
// Handles can not cross and selection is at least one character
final int selectionStart = getSelectionStart();
- if (offset <= selectionStart) offset = selectionStart + 1;
+ if (offset <= selectionStart) offset = Math.min(selectionStart + 1, mText.length());
positionAtCursorOffset(offset, false);
}
@@ -11237,7 +11228,7 @@
int max = extractRangeEndFromLong(minMax);
Selection.setSelection((Spannable) mText, max);
- ((Editable) mText).replace(min, max, content);
+ replaceText_internal(min, max, content);
if (dragDropIntoItself) {
int dragSourceStart = dragLocalState.start;
@@ -11250,7 +11241,7 @@
}
// Delete original selection
- ((Editable) mText).delete(dragSourceStart, dragSourceEnd);
+ deleteText_internal(dragSourceStart, dragSourceEnd);
// Make sure we do not leave two adjacent spaces.
if ((dragSourceStart == 0 ||
@@ -11259,7 +11250,7 @@
Character.isSpaceChar(mTransformed.charAt(dragSourceStart)))) {
final int pos = dragSourceStart == mText.length() ?
dragSourceStart - 1 : dragSourceStart;
- ((Editable) mText).delete(pos, pos + 1);
+ deleteText_internal(pos, pos + 1);
}
}
}
@@ -11420,6 +11411,22 @@
}
}
+ /**
+ * Deletes the range of text [start, end[.
+ * @hide
+ */
+ protected void deleteText_internal(int start, int end) {
+ ((Editable) mText).delete(start, end);
+ }
+
+ /**
+ * Replaces the range of text [start, end[ by replacement text
+ * @hide
+ */
+ protected void replaceText_internal(int start, int end, CharSequence text) {
+ ((Editable) mText).replace(start, end, text);
+ }
+
@ViewDebug.ExportedProperty(category = "text")
private CharSequence mText;
private CharSequence mTransformed;
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index 36f0246..72489a2 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -418,7 +418,7 @@
public static final int SM_QUIT_CMD = -1;
/** Message.what value when initializing */
- public static final int SM_INIT_CMD = -1;
+ public static final int SM_INIT_CMD = -2;
/**
* Convenience constant that maybe returned by processMessage
@@ -569,6 +569,13 @@
}
/**
+ * Clear the list of Processed Message Info.
+ */
+ void cleanup() {
+ mMessages.clear();
+ }
+
+ /**
* @return the information on a particular record. 0 is the oldest
* record and size()-1 is the newest record. If the index is to
* large null is returned.
@@ -608,6 +615,7 @@
}
}
+
private static class SmHandler extends Handler {
/** The debug flag */
@@ -782,15 +790,8 @@
*/
if (destState != null) {
if (destState == mQuittingState) {
- /**
- * We are quitting so ignore all messages.
- */
- mSm.quitting();
- if (mSm.mSmThread != null) {
- // If we made the thread then quit looper which stops the thread.
- getLooper().quit();
- mSm.mSmThread = null;
- }
+ cleanupAfterQuitting();
+
} else if (destState == mHaltingState) {
/**
* Call halting() if we've transitioned to the halting
@@ -803,6 +804,29 @@
}
/**
+ * Cleanup all the static variables and the looper after the SM has been quit.
+ */
+ private final void cleanupAfterQuitting() {
+ mSm.quitting();
+ if (mSm.mSmThread != null) {
+ // If we made the thread then quit looper which stops the thread.
+ getLooper().quit();
+ mSm.mSmThread = null;
+ }
+
+ mSm.mSmHandler = null;
+ mSm = null;
+ mMsg = null;
+ mProcessedMessages.cleanup();
+ mStateStack = null;
+ mTempStateStack = null;
+ mStateInfo.clear();
+ mInitialState = null;
+ mDestState = null;
+ mDeferredMessages.clear();
+ }
+
+ /**
* Complete the construction of the state machine.
*/
private final void completeConstruction() {
diff --git a/core/res/res/layout/date_picker.xml b/core/res/res/layout/date_picker.xml
index 6f0517d..9c1def2 100644
--- a/core/res/res/layout/date_picker.xml
+++ b/core/res/res/layout/date_picker.xml
@@ -32,7 +32,6 @@
<LinearLayout android:id="@+id/pickers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginRight="22dip"
android:layout_weight="1"
android:orientation="horizontal"
android:gravity="center">
@@ -77,7 +76,7 @@
android:id="@+id/calendar_view"
android:layout_width="245dip"
android:layout_height="280dip"
- android:layout_marginLeft="22dip"
+ android:layout_marginLeft="44dip"
android:layout_weight="1"
android:focusable="true"
android:focusableInTouchMode="true"
diff --git a/core/res/res/layout/global_actions_item.xml b/core/res/res/layout/global_actions_item.xml
index 67b1644..13ab985 100644
--- a/core/res/res/layout/global_actions_item.xml
+++ b/core/res/res/layout/global_actions_item.xml
@@ -14,48 +14,46 @@
limitations under the License.
-->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<!-- RelativeLayouts have an issue enforcing minimum heights, so just
+ work around this for now with LinearLayouts. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:orientation="horizontal"
android:paddingLeft="11dip"
android:paddingTop="6dip"
android:paddingBottom="6dip"
>
-
<ImageView android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_alignParentTop="true"
- android:layout_alignParentBottom="true"
+ android:layout_gravity="center"
android:layout_marginRight="9dip"
- />
-
-
- <TextView android:id="@+id/status"
- android:layout_width="match_parent"
- android:layout_height="26dip"
-
- android:layout_toRightOf="@id/icon"
- android:layout_alignParentBottom="true"
- android:layout_alignParentRight="true"
-
- android:textAppearance="?android:attr/textAppearanceSmall"
/>
-
- <TextView android:id="@+id/message"
+ <LinearLayout
+ android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ >
+ <TextView android:id="@+id/message"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
- android:layout_toRightOf="@id/icon"
- android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"
- android:layout_above="@id/status"
- android:layout_alignWithParentIfMissing="true"
- android:gravity="center_vertical"
- android:textAppearance="?android:attr/textAppearanceLarge"
- />
+ android:gravity="center_vertical"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ />
+ <TextView android:id="@+id/status"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:minHeight="26dp"
-
-</RelativeLayout>
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ />
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 42f3d8c..a5bb864 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -634,7 +634,7 @@
<string name="relationTypeParent" msgid="4755635567562925226">"Ouer"</string>
<string name="relationTypePartner" msgid="7266490285120262781">"Vennoot"</string>
<string name="relationTypeReferredBy" msgid="101573059844135524">"Verwys deur"</string>
- <string name="relationTypeRelative" msgid="1799819930085610271">"Relatief"</string>
+ <string name="relationTypeRelative" msgid="1799819930085610271">"Familielid"</string>
<string name="relationTypeSister" msgid="1735983554479076481">"Suster"</string>
<string name="relationTypeSpouse" msgid="394136939428698117">"Eggenoot"</string>
<string name="sipAddressTypeCustom" msgid="2473580593111590945">"Gepasmaakte"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 53c4f30..0ab7194 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -409,9 +409,9 @@
<string name="permlab_bindGadget" msgid="776905339015863471">"Widgets auswählen"</string>
<string name="permdesc_bindGadget" msgid="2098697834497452046">"Ermöglicht der App, dem System zu melden, welche Widgets von welcher Anwendung verwendet werden können. Mit dieser Berechtigung können Anwendungen anderen Anwendungen Zugriff auf persönliche Daten gewähren. Nicht für normale Apps vorgesehen."</string>
<string name="permlab_modifyPhoneState" msgid="8423923777659292228">"Telefonstatus ändern"</string>
- <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Ermöglicht einer App, die Telefonfunktionen des Gerätes zu steuern. Eine Anwendung mit dieser Berechtigung kann unter anderem das Netzwerk wechseln oder die Mobilfunkverbindung des Telefons ein- und ausschalten, ohne Sie darüber zu informieren."</string>
+ <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Ermöglicht einer App, die Telefonfunktionen des Geräts zu steuern. Eine Anwendung mit dieser Berechtigung kann unter anderem das Netzwerk wechseln oder die Mobilfunkverbindung des Telefons ein- und ausschalten, ohne Sie darüber zu informieren."</string>
<string name="permlab_readPhoneState" msgid="2326172951448691631">"Telefonstatus lesen und identifizieren"</string>
- <string name="permdesc_readPhoneState" msgid="188877305147626781">"Ermöglicht der App, auf die Telefonfunktionen des Gerätes zuzugreifen. Eine Anwendung mit dieser Berechtigung kann unter anderem bestimmen, welche Telefonnummer dieses Telefon verwendet, ob ein Anruf aktiv ist oder mit welcher Nummer der Anrufer verbunden ist."</string>
+ <string name="permdesc_readPhoneState" msgid="188877305147626781">"Ermöglicht der App, auf die Telefonfunktionen des Geräts zuzugreifen. Eine App mit dieser Berechtigung kann unter anderem bestimmen, welche Telefonnummer dieses Telefon verwendet, ob ein Anruf aktiv ist oder mit welcher Nummer der Anrufer verbunden ist."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"Standby-Modus des Tablets deaktivieren"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"Standby-Modus deaktivieren"</string>
<string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Ermöglicht einer App, den Standby-Modus des Tablets zu deaktivieren."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index db9dab0..fd91ee3 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -793,7 +793,7 @@
<string name="last_month" msgid="3959346739979055432">"El mes pasado"</string>
<string name="older" msgid="5211975022815554840">"Anterior"</string>
<plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"ayer"</item>
+ <item quantity="one" msgid="861358534398115820">"Ayer"</item>
<item quantity="other" msgid="2479586466153314633">"Hace <xliff:g id="COUNT">%d</xliff:g> días"</item>
</plurals>
<plurals name="in_num_seconds">
@@ -825,7 +825,7 @@
<item quantity="other" msgid="6889970745748538901">"hace <xliff:g id="COUNT">%d</xliff:g> horas"</item>
</plurals>
<plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"ayer"</item>
+ <item quantity="one" msgid="8463161711492680309">"Ayer"</item>
<item quantity="other" msgid="3453342639616481191">"hace <xliff:g id="COUNT">%d</xliff:g> días"</item>
</plurals>
<plurals name="abbrev_in_num_seconds">
@@ -919,10 +919,10 @@
<string name="screen_compat_mode_hint" msgid="2953716574198046484">"Vuelve a habilitar esta opción en Ajustes > Aplicaciones > Administrar aplicaciones."</string>
<string name="smv_application" msgid="295583804361236288">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> (proceso <xliff:g id="PROCESS">%2$s</xliff:g>) ha infringido su política StrictMode autoaplicable."</string>
<string name="smv_process" msgid="5120397012047462446">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> ha infringido su política StrictMode autoaplicable."</string>
- <string name="android_upgrading_title" msgid="378740715658358071">"Actualizando Android..."</string>
- <string name="android_upgrading_apk" msgid="274409861603566003">"Optimizando aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
+ <string name="android_upgrading_title" msgid="378740715658358071">"Actualizando Android"</string>
+ <string name="android_upgrading_apk" msgid="274409861603566003">"Optimizando aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>..."</string>
<string name="android_upgrading_starting_apps" msgid="7959542881906488763">"Iniciando aplicaciones"</string>
- <string name="android_upgrading_complete" msgid="1405954754112999229">"Finalizando arranque"</string>
+ <string name="android_upgrading_complete" msgid="1405954754112999229">"Finalizando inicio..."</string>
<string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> en ejecución"</string>
<string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Seleccionar para cambiar a la aplicación"</string>
<string name="heavy_weight_switcher_title" msgid="1135403633766694316">"¿Cambiar de aplicación?"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index f2726d8b..830bd69 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -20,7 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="byteShort" msgid="8340973892742019101">"O"</string>
+ <string name="byteShort" msgid="8340973892742019101">"o"</string>
<string name="kilobyteShort" msgid="5973789783504771878">"Ko"</string>
<string name="megabyteShort" msgid="6355851576770428922">"Mo"</string>
<string name="gigabyteShort" msgid="3259882455212193214">"Go"</string>
@@ -1219,6 +1219,6 @@
<string name="status_bar_device_locked" msgid="3092703448690669768">"Appareil verrouillé"</string>
<string name="list_delimeter" msgid="3975117572185494152">", "</string>
<string name="sending" msgid="8715108995741758718">"Envoi en cours…"</string>
- <string name="launchBrowserDefault" msgid="2057951947297614725">"Lancer l\'application Navigateur ?"</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"Lancer le navigateur ?"</string>
<string name="SetupCallDefault" msgid="6870275517518479651">"Prendre l\'appel ?"</string>
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 679d73d..022a520 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -51,7 +51,7 @@
<string name="needPuk" msgid="919668385956251611">"O seu cartão SIM está bloqueado com PUK. Introduza o código PUK para desbloqueá-lo."</string>
<string name="needPuk2" msgid="4526033371987193070">"Introduza o PUK2 para desbloquear o cartão SIM."</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID do Autor da Chamada"</string>
- <string name="ClirMmi" msgid="7784673673446833091">"ID do autor da chamada efectuada"</string>
+ <string name="ClirMmi" msgid="7784673673446833091">"ID do autor da chamada efetuada"</string>
<string name="CfMmi" msgid="5123218989141573515">"Encaminhamento de chamadas"</string>
<string name="CwMmi" msgid="9129678056795016867">"Chamada em espera"</string>
<string name="BaMmi" msgid="455193067926770581">"Barramento de chamadas"</string>
@@ -170,7 +170,7 @@
<string name="permgrouplab_accounts" msgid="3359646291125325519">"As suas contas"</string>
<string name="permgroupdesc_accounts" msgid="4948732641827091312">"Aceda às contas disponíveis."</string>
<string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Controlos de hardware"</string>
- <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Aceda directamente ao hardware no telefone."</string>
+ <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Aceda diretamente ao hardware no telefone."</string>
<string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Chamadas telefónicas"</string>
<string name="permgroupdesc_phoneCalls" msgid="7489701620446183770">"Monitorize, grave e processe chamadas telefónicas."</string>
<string name="permgrouplab_systemTools" msgid="4652191644082714048">"Ferramentas do sistema"</string>
@@ -291,7 +291,7 @@
<string name="permdesc_deleteCacheFiles" msgid="2283074077168165971">"Permite a uma aplicação eliminar ficheiros em cache."</string>
<string name="permlab_getPackageSize" msgid="4799785352306641460">"medir espaço de armazenamento da aplicação"</string>
<string name="permdesc_getPackageSize" msgid="5557253039670753437">"Permite a uma aplicação obter os respectivos código, dados e tamanhos de cache"</string>
- <string name="permlab_installPackages" msgid="335800214119051089">"instalar aplicações directamente"</string>
+ <string name="permlab_installPackages" msgid="335800214119051089">"instalar aplicações diretamente"</string>
<string name="permdesc_installPackages" msgid="526669220850066132">"Permite a uma aplicação instalar pacotes novos ou actualizados do Android. Algumas aplicações maliciosas podem utilizar este item para adicionar novas aplicações com autorizações arbitrariamente fortes."</string>
<string name="permlab_clearAppCache" msgid="4747698311163766540">"eliminar todos os dados da aplicações"</string>
<string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Permite a uma aplicação libertar espaço de armazenamento no tablet eliminando ficheiros no directório da cache da aplicação. Geralmente, o acesso é muito limitado para processamento do sistema."</string>
@@ -395,12 +395,12 @@
<string name="permdesc_accessMtp" msgid="6532961200486791570">"Permite o acesso ao controlador MTP de kernel para implementar o protocolo MTP USB."</string>
<string name="permlab_hardware_test" msgid="4148290860400659146">"testar hardware"</string>
<string name="permdesc_hardware_test" msgid="3668894686500081699">"Permite à aplicação controlar vários periféricos para fins de teste de hardware."</string>
- <string name="permlab_callPhone" msgid="3925836347681847954">"marcar números de telefone directamente"</string>
+ <string name="permlab_callPhone" msgid="3925836347681847954">"marcar números de telefone diretamente"</string>
<string name="permdesc_callPhone" msgid="3369867353692722456">"Permite à aplicação marcar números de telefone sem a intervenção do utilizador. Algumas aplicações maliciosas podem provocar o aparecimento de chamadas inesperadas na sua conta telefónica. Tenha em atenção que isto não permite à aplicação marcar números de emergência."</string>
- <string name="permlab_callPrivileged" msgid="4198349211108497879">"marcar directamente quaisquer números de telefone"</string>
+ <string name="permlab_callPrivileged" msgid="4198349211108497879">"marcar diretamente quaisquer números de telefone"</string>
<string name="permdesc_callPrivileged" msgid="244405067160028452">"Permite à aplicação marcar qualquer número de telefone, incluindo números de emergência, sem a intervenção do utilizador. Algumas aplicações maliciosas podem efectuar chamadas desnecessárias e ilegais para serviços de emergência."</string>
- <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"iniciar directamente a configuração do tablet CDMA"</string>
- <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"iniciar directamente a configuração do telefone CDMA"</string>
+ <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"iniciar diretamente a configuração do tablet CDMA"</string>
+ <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"iniciar diretamente a configuração do telefone CDMA"</string>
<string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Permite que a aplicação inicie o aprovisionamento CDMA. As aplicações mal intencionadas podem iniciar o aprovisionamento CDMA desnecessariamente"</string>
<string name="permlab_locationUpdates" msgid="7785408253364335740">"controlar notificações de actualização de localização"</string>
<string name="permdesc_locationUpdates" msgid="2300018303720930256">"Permite a activação/desactivação de notificações de actualização de localização a partir do rádio. Não se destina a utilização por aplicações normais."</string>
@@ -463,7 +463,7 @@
<string name="permlab_changeWifiState" msgid="7280632711057112137">"alterar estado de Wi-Fi"</string>
<string name="permdesc_changeWifiState" msgid="2950383153656873267">"Permite a uma aplicação ligar e desligar de pontos de acesso de Wi-Fi, bem como efectuar alterações a redes Wi-Fi configuradas."</string>
<string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"permitir recepção Multicast Wi-Fi"</string>
- <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Permite que uma aplicação receba pacotes não enviados directamente para o dispositivo. Esta opção pode ser útil para descobrir serviços oferecidos na vizinhança. Utiliza mais energia do que o modo não multicast."</string>
+ <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Permite que uma aplicação receba pacotes não enviados diretamente para o dispositivo. Esta opção pode ser útil para descobrir serviços oferecidos na vizinhança. Utiliza mais energia do que o modo não multicast."</string>
<string name="permlab_accessWimaxState" msgid="2800410363171809280">"ver estado do WiMAX"</string>
<string name="permdesc_accessWimaxState" msgid="8298035866227524023">"Permite a uma aplicação ver as informações acerca do estado do Wi-Fi."</string>
<string name="permlab_changeWimaxState" msgid="340465839241528618">"alterar estado do WiMAX"</string>
@@ -935,7 +935,7 @@
<string name="volume_ringtone" msgid="6885421406845734650">"Volume da campainha"</string>
<string name="volume_music" msgid="5421651157138628171">"Volume de multimédia"</string>
<string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"A reproduzir através de Bluetooth"</string>
- <string name="volume_music_hint_silent_ringtone_selected" msgid="6158339745293431194">"Toque silencioso seleccionado"</string>
+ <string name="volume_music_hint_silent_ringtone_selected" msgid="6158339745293431194">"Toque silencioso selecionado"</string>
<string name="volume_call" msgid="3941680041282788711">"Volume da chamada recebida"</string>
<string name="volume_bluetooth_call" msgid="2002891926351151534">"Volume de chamada recebida em Bluetooth"</string>
<string name="volume_alarm" msgid="1985191616042689100">"Volume do alarme"</string>
@@ -1081,7 +1081,7 @@
<string name="vpn_text" msgid="1610714069627824309">"Toque para gerir a rede."</string>
<string name="vpn_text_long" msgid="4907843483284977618">"Ligado a <xliff:g id="SESSION">%s</xliff:g>. Toque para gerir a rede."</string>
<string name="upload_file" msgid="2897957172366730416">"Escolher ficheiro"</string>
- <string name="no_file_chosen" msgid="6363648562170759465">"Não foi seleccionado nenhum ficheiro"</string>
+ <string name="no_file_chosen" msgid="6363648562170759465">"Não foi selecionado nenhum ficheiro"</string>
<string name="reset" msgid="2448168080964209908">"Repor"</string>
<string name="submit" msgid="1602335572089911941">"Enviar"</string>
<string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Modo automóvel activado"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 58b027c..1224d77 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1189,7 +1189,7 @@
<string name="data_usage_warning_body" msgid="7217480745540055170">"Проверить трафик и настройки"</string>
<string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Передача данных 2G/3G отключена"</string>
<string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Передача данных 4G отключена"</string>
- <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Мобильный Интернет отключен"</string>
+ <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Моб. Интернет отключен"</string>
<string name="data_usage_wifi_limit_title" msgid="8992154736441284865">"Передача данных через Wi-Fi отключена"</string>
<string name="data_usage_limit_body" msgid="4313857592916426843">"Нажмите, чтобы включить"</string>
<string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Превышен лимита трафика 2G и 3G"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 5334bfc..5c69718 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -49,7 +49,7 @@
<string name="invalidPin" msgid="3850018445187475377">"Chapisha PIN ambayo ina nambari 4 hadi 8."</string>
<string name="invalidPuk" msgid="8761456210898036513">"Andika PUK ambayo ina urefu wa nambari 8 au zaidi."</string>
<string name="needPuk" msgid="919668385956251611">"Kadi yako ya SIM imefungwa na PUK. Anika msimbo wa PUK ili kuifungua."</string>
- <string name="needPuk2" msgid="4526033371987193070">"Chapisha PUK2 ili kufungua kadi ya SIM."</string>
+ <string name="needPuk2" msgid="4526033371987193070">"Chapisha PUK2 ili kufungua SIM kadi."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Kitambulisho cha Mpigaji wa Simu Inayoingia"</string>
<string name="ClirMmi" msgid="7784673673446833091">"ID ya Mpigaji simu Inayotoka nje"</string>
<string name="CfMmi" msgid="5123218989141573515">"Kusambaza simu"</string>
@@ -199,11 +199,11 @@
<string name="permlab_sendSmsNoConfirmation" msgid="4781483105951730228">"Tuma ujumbe wa SMS bila ya thibitisho"</string>
<string name="permdesc_sendSmsNoConfirmation" msgid="4477752891276276168">"Huruhusu programu kutuma ujumbe wa SMS. Programu hatari huenda zikagharimu pesa kwa kutuma ujumbe bila ya uthibitishaji wako."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"soma SMS au MMS"</string>
- <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Huruhusu programu kusoma SMS zilizohifadhiwa kwenye kompyuta yako ndogo au kadi ya SIM. Huenda programu hasidi zikasoma SMS zako za siri."</string>
- <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Huruhusu programu kusoma ujumbe wa SMS uliohifadhiwa kwenye simu yako au kadi ya SIM. Programu mbaya za kompyuta huenda zikasoma ujumbe wako wa siri."</string>
+ <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Huruhusu programu kusoma SMS zilizohifadhiwa kwenye kompyuta yako ndogo au SIM kadi. Huenda programu hasidi zikasoma SMS zako za siri."</string>
+ <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Huruhusu programu kusoma ujumbe wa SMS uliohifadhiwa kwenye simu yako au SIM kadi. Programu mbaya za kompyuta huenda zikasoma ujumbe wako wa siri."</string>
<string name="permlab_writeSms" msgid="6881122575154940744">"hariri SMS au MMS"</string>
- <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Huruhusu programu kuandika ujumbe wa SMS uliohifadhiwa kwenye kompyuta yako au kadi ya SIM. Huenda programu hasidi zikafuta ujumbe wako."</string>
- <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Huruhusu programu kuandika kwa ujumbe wa SMS uliohifadhiwa kwenye simu yako au kadi ya SIM. Programu mbaya za kompyuta huenda zikafuta ujumbe wako."</string>
+ <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Huruhusu programu kuandika ujumbe wa SMS uliohifadhiwa kwenye kompyuta yako au SIM kadi. Huenda programu hasidi zikafuta ujumbe wako."</string>
+ <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Huruhusu programu kuandika kwa ujumbe wa SMS uliohifadhiwa kwenye simu yako au SIM kadi. Programu mbaya za kompyuta huenda zikafuta ujumbe wako."</string>
<string name="permlab_receiveWapPush" msgid="8258226427716551388">"pokea WAP"</string>
<string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Huruhusu programu kupokea na kuchakata ujumbe wa WAP. Programu mbaya za kompyuta huenda zikafuatilia ujumbe wako au kuzifuta bila kukuonyesha."</string>
<string name="permlab_getTasks" msgid="5005277531132573353">"epua programu zinazoendeshwa"</string>
@@ -333,9 +333,9 @@
<string name="permlab_writeProfile" msgid="4679878325177177400">"andika kwenye data ya maelezo yako mafupi"</string>
<string name="permdesc_writeProfile" product="default" msgid="6431297330378229453">"Inaruhusu programu kubadilisha au kuongeza maelezo binafsi ya maelezo yako mafupi yaliyohifadhiwa kwenye kifaa chako, kama vile jina lako na maelezo ya anwani. Hii ina maanisha programu nyingine ziweze kukutambua na kutuma maelezo ya maelezo yako mafupi kwa wengine."</string>
<string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"soma mkondo wako wa kijamii"</string>
- <string name="permdesc_readSocialStream" product="default" msgid="6619997662735851111">"Inaruhusu programuramu kufikia na kulandanisha usasisho kutoka kwako na marafiki wako. Prog hasidi zinaweza kutumia hizi kusoma mawasiliano ya kibinafsi kati yako na marafiki wako kwenye mitandao ya kijamii."</string>
+ <string name="permdesc_readSocialStream" product="default" msgid="6619997662735851111">"Inaruhusu programu kufikia na kulandanisha usasisho kutoka kwako na marafiki wako. Prog hasidi zinaweza kutumia hizi kusoma mawasiliano ya kibinafsi kati yako na marafiki wako kwenye mitandao ya kijamii."</string>
<string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"andika kwa mkondo wako wa kijamii"</string>
- <string name="permdesc_writeSocialStream" product="default" msgid="2689083745826002521">"Inaruhusu programuramu kuonyesha usasisho ya kijamii kutoka kwa marafiki wako. Prog hasidi zinaweza kutumia hizi zikijifanya kuwa rafiki na kukuhadaa kuonyesha nenosiri au taarifa zingine za siri."</string>
+ <string name="permdesc_writeSocialStream" product="default" msgid="2689083745826002521">"Inaruhusu programu kuonyesha usasisho ya kijamii kutoka kwa marafiki wako. Prog hasidi zinaweza kutumia hizi zikijifanya kuwa rafiki na kukuhadaa kuonyesha nenosiri au taarifa zingine za siri."</string>
<string name="permlab_readCalendar" msgid="5972727560257612398">"soma matukio ya kalenda pamoja na maelezo ya siri"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5665520896961671949">"Huruhusu programu kusoma matukio yote ya kalenda yaliyohifadhiwa kwenye kompyuta yako ndogo, pamoja na za marafiki au wafanyakazi wenza. Programu hasidi yenye kibali hiki kinaweza kuchukua maelezo ya kibinagsi kutoka kwa kalenda hizi bila ufahamu wa mmiliki."</string>
<string name="permdesc_readCalendar" product="default" msgid="2915879965326930312">"Huruhusu programu kusoma matukio yote ya kalenda yaliyohifadhiwa kwenye simu yako, pamoja na za marafiki au marafiki wenza. Programu hasidi yenye kibali hiki inaweza kuchukua maelezo ya kibinafsi kutoka kwa kalenda hizi bila ufahamu wa mmiliki."</string>
@@ -665,11 +665,11 @@
<string name="lockscreen_charged" msgid="4938930459620989972">"Imechajiwa."</string>
<string name="lockscreen_battery_short" msgid="3617549178603354656">"Kishika nafasi<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
<string name="lockscreen_low_battery" msgid="1482873981919249740">"Unganisha chaja yako"</string>
- <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Hakuna kadi ya SIM."</string>
- <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Hakuna kadi ya SIM katika kompyuta ndogo."</string>
- <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Hakuna kadi ya SIM kwenye simu."</string>
- <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Tafadhali ingiza kadi ya SIM."</string>
- <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Kadi ya SIM inakosekana au haisomekani. Tafadhali ingiza kadi ya SIM."</string>
+ <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Hakuna SIM kadi."</string>
+ <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Hakuna SIM kadi katika kompyuta ndogo."</string>
+ <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Hakuna SIM kadi kwenye simu."</string>
+ <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Tafadhali ingiza SIM kadi."</string>
+ <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Kadi ya SIM inakosekana au haisomekani. Tafadhali ingiza SIM kadi."</string>
<string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Kadi yako ya SIM imelemazwa kabisa. "\n" tafadhali wasiliana na mtoa huduma wako wa psiwaya ili kupata kadi nyingine ya SIM."</string>
<string name="lockscreen_transport_prev_description" msgid="201594905152746886">"Kitufe cha awali cha wimbo"</string>
<string name="lockscreen_transport_next_description" msgid="6089297650481292363">"Kitufe cha wimbo unaofuata"</string>
@@ -681,7 +681,7 @@
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Kadi ya SIM imefungwa na PUK."</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="635967534992394321">"Tafadhali angalia Mwongozo wa Mtumiaji au wasiliana na Huduma kwa Wateja."</string>
<string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Kadi ya SIM imefungwa."</string>
- <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Inafungua kadi ya SIM..."</string>
+ <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Inafungua SIM kadi..."</string>
<string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Umechora vibaya ruwaza yako ya kufungua mara <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n" Tafadhali jaribu tena kati ya sekunde <xliff:g id="NUMBER_1">%d</xliff:g>."</string>
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Haujaingiza nenosiri yako kwa usahihi mara<xliff:g id="NUMBER_0">%d</xliff:g>Tafadhali jaribu tena. "\n\n"baada ya sekunde<xliff:g id="NUMBER_1">%d</xliff:g>."</string>
<string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Haujaingiza PIN yako kwa usahihi mara<xliff:g id="NUMBER_0">%d</xliff:g>tafadhali jaribu tena. "\n\n"baada ya sekunde<xliff:g id="NUMBER_1">%d</xliff:g>."</string>
@@ -892,7 +892,7 @@
<string name="no" msgid="5141531044935541497">"Ghairi"</string>
<string name="dialog_alert_title" msgid="2049658708609043103">"Zingatia"</string>
<string name="loading" msgid="1760724998928255250">"Inapakia..."</string>
- <string name="capital_on" msgid="1544682755514494298">"Mnamo"</string>
+ <string name="capital_on" msgid="1544682755514494298">"Washa"</string>
<string name="capital_off" msgid="6815870386972805832">"ZIMA"</string>
<string name="whichApplication" msgid="4533185947064773386">"Kamilisha kitendo kwa kutumia"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Tumia kama chaguo-msingi la kitendo hiki."</string>
@@ -976,7 +976,7 @@
<string name="sms_control_yes" msgid="2532062172402615953">"Sawa"</string>
<string name="sms_control_no" msgid="1715320703137199869">"Ghairi"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Kadi ya SIM imeondolewa"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"mtandao wa simu hutapatika hadi uanzishe upya na kadi ya SIM halali iliyoingizwa."</string>
+ <string name="sim_removed_message" msgid="2333164559970958645">"mtandao wa simu hutapatika hadi uanzishe upya na SIM kadi halali iliyoingizwa."</string>
<string name="sim_done_button" msgid="827949989369963775">"Kwisha"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Kadi ya SIM imeongezwa"</string>
<string name="sim_added_message" msgid="1209265974048554242">"Lazima uwashe upya kifaa chako ili kufikia mtandao wa simu."</string>
@@ -1152,7 +1152,7 @@
<string name="checkbox_not_checked" msgid="5174639551134444056">"haijakaguliwa"</string>
<string name="radiobutton_selected" msgid="8603599808486581511">"Iliyochaguliwa"</string>
<string name="radiobutton_not_selected" msgid="2908760184307722393">"Haijachaguliwa"</string>
- <string name="switch_on" msgid="551417728476977311">"Mnamo"</string>
+ <string name="switch_on" msgid="551417728476977311">"Washa"</string>
<string name="switch_off" msgid="7249798614327155088">"zima"</string>
<string name="togglebutton_pressed" msgid="4180411746647422233">"iliyobonyezwa"</string>
<string name="togglebutton_not_pressed" msgid="4495147725636134425">"Haijabonyezwa"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 8213008..c46e0e9 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -359,8 +359,8 @@
<string name="permdesc_readFrameBuffer" msgid="7530020370469942528">"Cho phép ứng dụng đọc nội dung của bộ đệm khung."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"thay đổi cài đặt âm thanh của bạn"</string>
<string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Cho phép ứng dụng sửa đổi cài đặt âm thanh chung chẳng hạn như âm lượng và định tuyến."</string>
- <string name="permlab_recordAudio" msgid="3876049771427466323">"ghi âm thanh"</string>
- <string name="permdesc_recordAudio" msgid="6493228261176552356">"Cho phép ứng dụng truy cập vào đường dẫn bản ghi âm thanh."</string>
+ <string name="permlab_recordAudio" msgid="3876049771427466323">"ghi âm"</string>
+ <string name="permdesc_recordAudio" msgid="6493228261176552356">"Cho phép ứng dụng truy cập vào đường dẫn bản ghi âm."</string>
<string name="permlab_camera" msgid="3616391919559751192">"chụp ảnh và quay video"</string>
<string name="permdesc_camera" msgid="6004878235852154239">"Cho phép ứng dụng chụp ảnh và quay video bằng máy ảnh. Quyền này cho phép ứng dụng thu thập ảnh mà máy ảnh chụp vào bất kỳ thời điểm nào."</string>
<string name="permlab_brick" product="tablet" msgid="2961292205764488304">"vô hiệu hóa vĩnh viễn máy tính bảng"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 12b1784..cc4ff67 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -319,7 +319,7 @@
<string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"开机时自动启动"</string>
<string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"允许应用程序在系统完成启动后立即自行启动。这样会延长平板电脑的启动时间,而且如果应用程序一直运行,会降低平板电脑的整体速度。"</string>
<string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"允许应用程序在系统完成启动后即自行启动。这样会延长手机的启动时间,而且如果应用程序一直运行,会降低手机的整体速度。"</string>
- <string name="permlab_broadcastSticky" msgid="7919126372606881614">"发送置顶广播"</string>
+ <string name="permlab_broadcastSticky" msgid="7919126372606881614">"发送持久广播"</string>
<string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"允许应用程序发送顽固广播,这些广播在结束后仍会保留。恶意应用程序可借此让平板电脑耗用太多内存,从而降低其速度或稳定性。"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"允许应用程序发送顽固广播,这些广播在结束后仍会保留。恶意应用程序可能会借此使手机耗用太多内存,从而降低其速度或稳定性。"</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"读取联系人数据"</string>
@@ -904,9 +904,9 @@
<string name="aerr_application" msgid="932628488013092776">"很抱歉,“<xliff:g id="APPLICATION">%1$s</xliff:g>”已停止运行。"</string>
<string name="aerr_process" msgid="4507058997035697579">"抱歉,进程“<xliff:g id="PROCESS">%1$s</xliff:g>”已停止运行。"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
- <string name="anr_activity_application" msgid="8339738283149696827">"“<xliff:g id="APPLICATION">%2$s</xliff:g>”无响应。"\n\n"要将它关闭吗?"</string>
- <string name="anr_activity_process" msgid="7018289416670457797">"活动“<xliff:g id="ACTIVITY">%1$s</xliff:g>”无响应。"\n\n"要将它关闭吗?"</string>
- <string name="anr_application_process" msgid="7208175830253210526">"“<xliff:g id="APPLICATION">%1$s</xliff:g>”无响应。要将它关闭吗?"</string>
+ <string name="anr_activity_application" msgid="8339738283149696827">"<xliff:g id="APPLICATION">%2$s</xliff:g> 无响应。"\n\n"要将它关闭吗?"</string>
+ <string name="anr_activity_process" msgid="7018289416670457797">"活动 <xliff:g id="ACTIVITY">%1$s</xliff:g> 无响应。"\n\n"要将它关闭吗?"</string>
+ <string name="anr_application_process" msgid="7208175830253210526">"<xliff:g id="APPLICATION">%1$s</xliff:g> 无响应。要将它关闭吗?"</string>
<string name="anr_process" msgid="306819947562555821">"进程 <xliff:g id="PROCESS">%1$s</xliff:g> 无响应。"\n\n"要将它关闭吗?"</string>
<string name="force_close" msgid="8346072094521265605">"确定"</string>
<string name="report" msgid="4060218260984795706">"报告"</string>
@@ -1181,7 +1181,7 @@
<string name="action_bar_home_description" msgid="5293600496601490216">"导航首页"</string>
<string name="action_bar_up_description" msgid="2237496562952152589">"向上导航"</string>
<string name="action_menu_overflow_description" msgid="2295659037509008453">"更多选项"</string>
- <string name="storage_internal" msgid="7556050805474115618">"内存空间"</string>
+ <string name="storage_internal" msgid="7556050805474115618">"内部存储空间"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD 卡"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB 存储器"</string>
<string name="extract_edit_menu_button" msgid="302060189057163906">"编辑..."</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 1252ba1..20b353d 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1219,6 +1219,6 @@
<string name="status_bar_device_locked" msgid="3092703448690669768">"裝置已鎖定。"</string>
<string name="list_delimeter" msgid="3975117572185494152">"、 "</string>
<string name="sending" msgid="8715108995741758718">"傳送中..."</string>
- <string name="launchBrowserDefault" msgid="2057951947297614725">"要啟動「瀏覽器」嗎?"</string>
- <string name="SetupCallDefault" msgid="6870275517518479651">"要接受通話嗎?"</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"啟動「瀏覽器」嗎?"</string>
+ <string name="SetupCallDefault" msgid="6870275517518479651">"接聽電話嗎?"</string>
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index eb9e660..0345bf0 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -698,7 +698,7 @@
<string name="lockscreen_glogin_instructions" msgid="1816635201812207709">"Ukuvula, ngena ngemvumekwi-akhawunti ye-Google"</string>
<string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Igama lomsebenzisi (i-imeyli)"</string>
<string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"Iphasiwedi"</string>
- <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Ngena ngemvume"</string>
+ <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Ngena"</string>
<string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Igama lomsebezisi elingalungile noma iphasiwedi."</string>
<string name="lockscreen_glogin_account_recovery_hint" msgid="8253152905532900548">"Ukhohlwe igama lomsebenzisi noma iphasiwedi?"\n"Vakashela"<b>"google.com/accounts/recovery"</b></string>
<string name="lockscreen_glogin_checking_password" msgid="6758890536332363322">"Iyahlola..."</string>
@@ -768,8 +768,8 @@
<string name="menu_enter_shortcut_label" msgid="2743362785111309668">"faka"</string>
<string name="menu_delete_shortcut_label" msgid="3658178007202748164">"susa"</string>
<string name="search_go" msgid="8298016669822141719">"Sesha"</string>
- <string name="searchview_description_search" msgid="6749826639098512120">"Cinga"</string>
- <string name="searchview_description_query" msgid="5911778593125355124">"Cinga umbuzo"</string>
+ <string name="searchview_description_search" msgid="6749826639098512120">"Sesha"</string>
+ <string name="searchview_description_query" msgid="5911778593125355124">"Umbuzo wosesho"</string>
<string name="searchview_description_clear" msgid="1330281990951833033">"xazulula umbuzo"</string>
<string name="searchview_description_submit" msgid="2688450133297983542">"Thumela umbuzo"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"Ukusesha ngezwi"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d0ab8b1..af59198 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1493,6 +1493,10 @@
<enum name="KEYCODE_LANGUAGE_SWITCH" value="204" />
<enum name="KEYCODE_MANNER_MODE" value="205" />
<enum name="KEYCODE_3D_MODE" value="206" />
+ <enum name="KEYCODE_CONTACTS" value="207" />
+ <enum name="KEYCODE_CALENDAR" value="208" />
+ <enum name="KEYCODE_MUSIC" value="209" />
+ <enum name="KEYCODE_CALCULATOR" value="210" />
</attr>
<!-- ***************************************************************** -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 25f7d25..767cafe 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -741,7 +741,4 @@
<string name="config_wimaxServiceClassname"></string>
<!-- Name of the wimax state tracker clas -->
<string name="config_wimaxStateTrackerClassname"></string>
-
- <!-- Name of screensaver components to look for if none has been chosen by the user -->
- <string name="config_defaultDreamComponent">com.google.android.deskclock/com.android.deskclock.Screensaver</string>
</resources>
diff --git a/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java b/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
index 3521296..ec12124 100644
--- a/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
+++ b/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
@@ -26,6 +26,7 @@
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
+import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityManager;
@@ -54,28 +55,31 @@
// Timeout before give up wait for the system to process an accessibility setting change.
private static final int TIMEOUT_PROPAGATE_ACCESSIBLITY_SETTING = 2000;
+ // Timeout for the accessibility state of an Activity to be fully initialized.
+ private static final int TIMEOUT_ACCESSIBLITY_STATE_INITIALIZED_MILLIS = 100;
+
// Handle to a connection to the AccessibilityManagerService
- private static IAccessibilityServiceConnection sConnection;
+ private static int sConnectionId = View.NO_ID;
// The last received accessibility event
- private static volatile AccessibilityEvent sLastFocusAccessibilityEvent;
+ private volatile AccessibilityEvent mLastAccessibilityEvent;
public InterrogationActivityTest() {
super(InterrogationActivity.class);
}
+ @Override
+ public void setUp() throws Exception {
+ ensureConnection();
+ bringUpActivityWithInitalizedAccessbility();
+ }
+
@LargeTest
public void testFindAccessibilityNodeInfoByViewId() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertNotNull(button);
assertEquals(0, button.getChildCount());
@@ -120,15 +124,9 @@
public void testFindAccessibilityNodeInfoByViewText() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
// find a view by text
- List<AccessibilityNodeInfo> buttons = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfosByViewTextInActiveWindow(connection, "butto");
+ List<AccessibilityNodeInfo> buttons = AccessibilityInteractionClient.getInstance()
+ .findAccessibilityNodeInfosByViewTextInActiveWindow(sConnectionId, "butto");
assertEquals(9, buttons.size());
} finally {
if (DEBUG) {
@@ -143,15 +141,11 @@
public void testFindAccessibilityNodeInfoByViewTextContentDescription() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
+ bringUpActivityWithInitalizedAccessbility();
// find a view by text
- List<AccessibilityNodeInfo> buttons = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfosByViewTextInActiveWindow(connection,
+ List<AccessibilityNodeInfo> buttons = AccessibilityInteractionClient.getInstance()
+ .findAccessibilityNodeInfosByViewTextInActiveWindow(sConnectionId,
"contentDescription");
assertEquals(1, buttons.size());
} finally {
@@ -167,12 +161,6 @@
public void testTraverseAllViews() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
// make list of expected nodes
List<String> classNameAndTextList = new ArrayList<String>();
classNameAndTextList.add("android.widget.LinearLayout");
@@ -190,7 +178,7 @@
classNameAndTextList.add("android.widget.ButtonButton9");
AccessibilityNodeInfo root = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.root);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.root);
assertNotNull("We must find the existing root.", root);
Queue<AccessibilityNodeInfo> fringe = new LinkedList<AccessibilityNodeInfo>();
@@ -227,23 +215,17 @@
public void testPerformAccessibilityActionFocus() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
// find a view and make sure it is not focused
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertFalse(button.isFocused());
// focus the view
assertTrue(button.performAction(ACTION_FOCUS));
// find the view again and make sure it is focused
- button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ button = AccessibilityInteractionClient.getInstance()
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertTrue(button.isFocused());
} finally {
if (DEBUG) {
@@ -257,15 +239,9 @@
public void testPerformAccessibilityActionClearFocus() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
// find a view and make sure it is not focused
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertFalse(button.isFocused());
// focus the view
@@ -273,7 +249,7 @@
// find the view again and make sure it is focused
button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertTrue(button.isFocused());
// unfocus the view
@@ -281,7 +257,7 @@
// find the view again and make sure it is not focused
button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertFalse(button.isFocused());
} finally {
if (DEBUG) {
@@ -296,15 +272,9 @@
public void testPerformAccessibilityActionSelect() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
// find a view and make sure it is not selected
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertFalse(button.isSelected());
// select the view
@@ -312,7 +282,7 @@
// find the view again and make sure it is selected
button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertTrue(button.isSelected());
} finally {
if (DEBUG) {
@@ -326,15 +296,9 @@
public void testPerformAccessibilityActionClearSelection() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
// find a view and make sure it is not selected
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertFalse(button.isSelected());
// select the view
@@ -342,15 +306,15 @@
// find the view again and make sure it is selected
button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertTrue(button.isSelected());
// unselect the view
assertTrue(button.performAction(ACTION_CLEAR_SELECTION));
// find the view again and make sure it is not selected
- button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ button = AccessibilityInteractionClient.getInstance()
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertFalse(button.isSelected());
} finally {
if (DEBUG) {
@@ -365,30 +329,24 @@
public void testAccessibilityEventGetSource() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
// find a view and make sure it is not focused
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertFalse(button.isSelected());
// focus the view
assertTrue(button.performAction(ACTION_FOCUS));
- synchronized (sConnection) {
+ synchronized (this) {
try {
- sConnection.wait(500);
+ wait(TIMEOUT_ACCESSIBLITY_STATE_INITIALIZED_MILLIS);
} catch (InterruptedException ie) {
/* ignore */
}
}
// check that last event source
- AccessibilityNodeInfo source = sLastFocusAccessibilityEvent.getSource();
+ AccessibilityNodeInfo source = mLastAccessibilityEvent.getSource();
assertNotNull(source);
// bounds
@@ -430,15 +388,9 @@
public void testObjectContract() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
// find a view and make sure it is not focused
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
AccessibilityNodeInfo parent = button.getParent();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
@@ -459,24 +411,57 @@
}
}
- @Override
- protected void scrubClass(Class<?> testCaseClass) {
- /* intentionally do not scrub */
+ private void bringUpActivityWithInitalizedAccessbility() {
+ mLastAccessibilityEvent = null;
+ // bring up the activity
+ getActivity();
+
+ final long startTimeMillis = SystemClock.uptimeMillis();
+ while (true) {
+ if (mLastAccessibilityEvent != null) {
+ final int eventType = mLastAccessibilityEvent.getEventType();
+ if (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+ return;
+ }
+ }
+ final long remainingTimeMillis = TIMEOUT_ACCESSIBLITY_STATE_INITIALIZED_MILLIS
+ - (SystemClock.uptimeMillis() - startTimeMillis);
+ if (remainingTimeMillis <= 0) {
+ return;
+ }
+ synchronized (this) {
+ try {
+ wait(remainingTimeMillis);
+ } catch (InterruptedException e) {
+ /* ignore */
+ }
+ }
+ }
}
- private IAccessibilityServiceConnection getConnection() throws Exception {
- if (sConnection == null) {
+ private void ensureConnection() throws Exception {
+ if (sConnectionId == View.NO_ID) {
IEventListener listener = new IEventListener.Stub() {
- public void setConnection(IAccessibilityServiceConnection connection) {}
+ public void setConnection(IAccessibilityServiceConnection connection,
+ int connectionId) {
+ sConnectionId = connectionId;
+ if (connection != null) {
+ AccessibilityInteractionClient.getInstance().addConnection(connectionId,
+ connection);
+ } else {
+ AccessibilityInteractionClient.getInstance().removeConnection(connectionId);
+ }
+ synchronized (this) {
+ notifyAll();
+ }
+ }
public void onInterrupt() {}
public void onAccessibilityEvent(AccessibilityEvent event) {
- if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
- sLastFocusAccessibilityEvent = AccessibilityEvent.obtain(event);
- }
- synchronized (sConnection) {
- sConnection.notifyAll();
+ mLastAccessibilityEvent = AccessibilityEvent.obtain(event);
+ synchronized (this) {
+ notifyAll();
}
}
};
@@ -485,28 +470,11 @@
AccessibilityManager.getInstance(getInstrumentation().getContext());
synchronized (this) {
- if (!accessibilityManager.isEnabled()) {
- // Make sure we wake ourselves as the desired state is propagated.
- accessibilityManager.addAccessibilityStateChangeListener(
- new AccessibilityManager.AccessibilityStateChangeListener() {
- public void onAccessibilityStateChanged(boolean enabled) {
- synchronized (this) {
- notifyAll();
- }
- }
- });
- IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
+ IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
ServiceManager.getService(Context.ACCESSIBILITY_SERVICE));
- sConnection = manager.registerEventListener(listener);
-
- wait(TIMEOUT_PROPAGATE_ACCESSIBLITY_SETTING);
- } else {
- IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
- ServiceManager.getService(Context.ACCESSIBILITY_SERVICE));
- sConnection = manager.registerEventListener(listener);
- }
+ manager.registerEventListener(listener);
+ wait(TIMEOUT_PROPAGATE_ACCESSIBLITY_SETTING);
}
}
- return sConnection;
}
}
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 10de6ac..fdd9040 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -159,7 +159,7 @@
# key 137 "KEY_CUT"
# key 138 "KEY_HELP"
key 139 MENU WAKE_DROPPED
-# key 140 "KEY_CALC"
+key 140 CALCULATOR
# key 141 "KEY_SETUP"
key 142 POWER WAKE
key 143 POWER WAKE
@@ -190,7 +190,7 @@
key 168 MEDIA_REWIND
key 169 CALL
# key 170 "KEY_ISO"
-# key 171 "KEY_CONFIG"
+key 171 MUSIC
key 172 HOME
# key 173 "KEY_REFRESH"
# key 174 "KEY_EXIT"
@@ -232,7 +232,7 @@
# key 210 "KEY_PRINT"
# key 211 "KEY_HP"
key 212 CAMERA
-# key 213 "KEY_SOUND"
+key 213 MUSIC
# key 214 "KEY_QUESTION"
key 215 ENVELOPE
# key 216 "KEY_CHAT"
@@ -344,7 +344,7 @@
# key 394 "KEY_DIRECTORY"
# key 395 "KEY_LIST"
# key 396 "KEY_MEMO"
-# key 397 "KEY_CALENDAR"
+key 397 CALENDAR
# key 398 "KEY_RED"
# key 399 "KEY_GREEN"
# key 400 "KEY_YELLOW"
@@ -364,6 +364,7 @@
# key 414 "KEY_TEEN"
# key 415 "KEY_TWEN"
+key 429 CONTACTS
# key 448 "KEY_DEL_EOL"
# key 449 "KEY_DEL_EOS"
diff --git a/docs/html/guide/topics/renderscript/index.jd b/docs/html/guide/topics/renderscript/index.jd
index eb77310..148705c 100644
--- a/docs/html/guide/topics/renderscript/index.jd
+++ b/docs/html/guide/topics/renderscript/index.jd
@@ -151,10 +151,9 @@
defining two-, three-, or four-vectors.</li>
</ul>
- <p>The <a href="{@docRoot}guide/topics/renderscript/rs-api/files.html">RenderScript header files</a>
- and LLVM front-end libraries are located in the <code>include</code> and
- <code>clang-include</code> directories in the
- <code><sdk_root>/platforms/android-11/renderscript</code> directory of the Android SDK. The
+ <p>The RenderScript header files and LLVM front-end libraries are located in the <code>include/</code> and
+ <code>clang-include/</code> directories in the
+ <code><sdk_root>/platforms/android-11/renderscript/</code> directory of the Android SDK. The
headers are automatically included for you, except for the RenderScript graphics specific header file, which
you can include as follows:</p>
<pre>
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 15c2bab..a8c7672 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -60,10 +60,16 @@
virtual void onFrameAvailable() = 0;
};
- // tex indicates the name OpenGL texture to which images are to be streamed.
- // This texture name cannot be changed once the SurfaceTexture is created.
+ // SurfaceTexture constructs a new SurfaceTexture object. tex indicates the
+ // name of the OpenGL ES texture to which images are to be streamed. This
+ // texture name cannot be changed once the SurfaceTexture is created.
+ // allowSynchronousMode specifies whether or not synchronous mode can be
+ // enabled. texTarget specifies the OpenGL ES texture target to which the
+ // texture will be bound in updateTexImage. useFenceSync specifies whether
+ // fences should be used to synchronize access to buffers if that behavior
+ // is enabled at compile-time.
SurfaceTexture(GLuint tex, bool allowSynchronousMode = true,
- GLenum texTarget = GL_TEXTURE_EXTERNAL_OES);
+ GLenum texTarget = GL_TEXTURE_EXTERNAL_OES, bool useFenceSync = true);
virtual ~SurfaceTexture();
@@ -276,7 +282,8 @@
mTransform(0),
mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
mTimestamp(0),
- mFrameNumber(0) {
+ mFrameNumber(0),
+ mFence(EGL_NO_SYNC_KHR) {
mCrop.makeInvalid();
}
@@ -349,6 +356,11 @@
// mFrameNumber is the number of the queued frame for this slot.
uint64_t mFrameNumber;
+ // mFence is the EGL sync object that must signal before the buffer
+ // associated with this buffer slot may be dequeued. It is initialized
+ // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
+ // on a compile-time option) set to a new sync object in updateTexImage.
+ EGLSyncKHR mFence;
};
// mSlots is the array of buffer slots that must be mirrored on the client
@@ -472,6 +484,12 @@
// It is set by the setName method.
String8 mName;
+ // mUseFenceSync indicates whether creation of the EGL_KHR_fence_sync
+ // extension should be used to prevent buffers from being dequeued before
+ // it's safe for them to be written. It gets set at construction time and
+ // never changes.
+ const bool mUseFenceSync;
+
// mMutex is the mutex used to prevent concurrent access to the member
// variables of SurfaceTexture objects. It must be locked whenever the
// member variables are accessed.
diff --git a/include/media/IStreamSource.h b/include/media/IStreamSource.h
index cc63356..19646b0 100644
--- a/include/media/IStreamSource.h
+++ b/include/media/IStreamSource.h
@@ -52,15 +52,20 @@
static const char *const kKeyResumeAtPTS;
// When signalling a discontinuity you can optionally
- // signal that this is a "hard" discontinuity, i.e. the format
- // or configuration of subsequent stream data differs from that
- // currently active. To do so, include a non-zero int32_t value
- // under the key "kKeyFormatChange" when issuing the DISCONTINUITY
+ // specify the type(s) of discontinuity, i.e. if the
+ // audio format has changed, the video format has changed,
+ // time has jumped or any combination thereof.
+ // To do so, include a non-zero int32_t value
+ // under the key "kKeyDiscontinuityMask" when issuing the DISCONTINUITY
// command.
- // The new logical stream must start with proper codec initialization
+ // If there is a change in audio/video format, The new logical stream
+ // must start with proper codec initialization
// information for playback to continue, i.e. SPS and PPS in the case
// of AVC video etc.
- static const char *const kKeyFormatChange;
+ // If this key is not present, only a time discontinuity is assumed.
+ // The value should be a bitmask of values from
+ // ATSParser::DiscontinuityType.
+ static const char *const kKeyDiscontinuityMask;
virtual void issueCommand(
Command cmd, bool synchronous, const sp<AMessage> &msg = NULL) = 0;
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 5822877..3963d9c 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -166,6 +166,8 @@
bool allYourBuffersAreBelongToUs();
+ size_t countBuffersOwnedByComponent(OMX_U32 portIndex) const;
+
void deferMessage(const sp<AMessage> &msg);
void processDeferredMessages();
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index b9deafc..6ab01f4 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -63,6 +63,7 @@
USAGE_HW_RENDER = GRALLOC_USAGE_HW_RENDER,
USAGE_HW_2D = GRALLOC_USAGE_HW_2D,
USAGE_HW_COMPOSER = GRALLOC_USAGE_HW_COMPOSER,
+ USAGE_HW_VIDEO_ENCODER = GRALLOC_USAGE_HW_VIDEO_ENCODER,
USAGE_HW_MASK = GRALLOC_USAGE_HW_MASK
};
diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h
index 2efe8ca..c5bd0c5 100755
--- a/include/ui/KeycodeLabels.h
+++ b/include/ui/KeycodeLabels.h
@@ -231,6 +231,10 @@
{ "LANGUAGE_SWITCH", 204 },
{ "MANNER_MODE", 205 },
{ "3D_MODE", 206 },
+ { "CONTACTS", 207 },
+ { "CALENDAR", 208 },
+ { "MUSIC", 209 },
+ { "CALCULATOR", 210 },
// NOTE: If you add a new keycode here you must also add it to several other files.
// Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index beb23f6..fcd287c 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -36,6 +36,12 @@
#include <utils/Log.h>
#include <utils/String8.h>
+// This compile option causes SurfaceTexture to return the buffer that is currently
+// attached to the GL texture from dequeueBuffer when no other buffers are
+// available. It requires the drivers (Gralloc, GL, OMX IL, and Camera) to do
+// implicit cross-process synchronization to prevent the buffer from being
+// written to before the buffer has (a) been detached from the GL texture and
+// (b) all GL reads from the buffer have completed.
#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER true
#warning "ALLOW_DEQUEUE_CURRENT_BUFFER enabled"
@@ -43,6 +49,16 @@
#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER false
#endif
+// This compile option makes SurfaceTexture use the EGL_KHR_fence_sync extension
+// to synchronize access to the buffers. It will cause dequeueBuffer to stall,
+// waiting for the GL reads for the buffer being dequeued to complete before
+// allowing the buffer to be dequeued.
+#ifdef USE_FENCE_SYNC
+#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
+#error "USE_FENCE_SYNC and ALLOW_DEQUEUE_CURRENT_BUFFER are incompatible"
+#endif
+#endif
+
// Macros for including the SurfaceTexture name in log messages
#define ST_LOGV(x, ...) LOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
#define ST_LOGD(x, ...) LOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
@@ -99,7 +115,7 @@
}
SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
- GLenum texTarget) :
+ GLenum texTarget, bool useFenceSync) :
mDefaultWidth(1),
mDefaultHeight(1),
mPixelFormat(PIXEL_FORMAT_RGBA_8888),
@@ -116,6 +132,11 @@
mAllowSynchronousMode(allowSynchronousMode),
mConnectedApi(NO_CONNECTED_API),
mAbandoned(false),
+#ifdef USE_FENCE_SYNC
+ mUseFenceSync(useFenceSync),
+#else
+ mUseFenceSync(false),
+#endif
mTexTarget(texTarget),
mFrameCounter(0) {
// Choose a name using the PID and a process-unique ID.
@@ -261,195 +282,225 @@
return BAD_VALUE;
}
- Mutex::Autolock lock(mMutex);
-
status_t returnFlags(OK);
+ EGLDisplay dpy = EGL_NO_DISPLAY;
+ EGLSyncKHR fence = EGL_NO_SYNC_KHR;
- int found = -1;
- int foundSync = -1;
- int dequeuedCount = 0;
- bool tryAgain = true;
- while (tryAgain) {
- if (mAbandoned) {
- ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
+ { // Scope for the lock
+ Mutex::Autolock lock(mMutex);
- // We need to wait for the FIFO to drain if the number of buffer
- // needs to change.
- //
- // The condition "number of buffers needs to change" is true if
- // - the client doesn't care about how many buffers there are
- // - AND the actual number of buffer is different from what was
- // set in the last setBufferCountServer()
- // - OR -
- // setBufferCountServer() was set to a value incompatible with
- // the synchronization mode (for instance because the sync mode
- // changed since)
- //
- // As long as this condition is true AND the FIFO is not empty, we
- // wait on mDequeueCondition.
-
- const int minBufferCountNeeded = mSynchronousMode ?
- MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
-
- const bool numberOfBuffersNeedsToChange = !mClientBufferCount &&
- ((mServerBufferCount != mBufferCount) ||
- (mServerBufferCount < minBufferCountNeeded));
-
- if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {
- // wait for the FIFO to drain
- mDequeueCondition.wait(mMutex);
- // NOTE: we continue here because we need to reevaluate our
- // whole state (eg: we could be abandoned or disconnected)
- continue;
- }
-
- if (numberOfBuffersNeedsToChange) {
- // here we're guaranteed that mQueue is empty
- freeAllBuffersLocked();
- mBufferCount = mServerBufferCount;
- if (mBufferCount < minBufferCountNeeded)
- mBufferCount = minBufferCountNeeded;
- mCurrentTexture = INVALID_BUFFER_SLOT;
- returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
- }
-
- // look for a free buffer to give to the client
- found = INVALID_BUFFER_SLOT;
- foundSync = INVALID_BUFFER_SLOT;
- dequeuedCount = 0;
- for (int i = 0; i < mBufferCount; i++) {
- const int state = mSlots[i].mBufferState;
- if (state == BufferSlot::DEQUEUED) {
- dequeuedCount++;
+ int found = -1;
+ int foundSync = -1;
+ int dequeuedCount = 0;
+ bool tryAgain = true;
+ while (tryAgain) {
+ if (mAbandoned) {
+ ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
+ return NO_INIT;
}
- // if buffer is FREE it CANNOT be current
- LOGW_IF((state == BufferSlot::FREE) && (mCurrentTexture==i),
- "dequeueBuffer: buffer %d is both FREE and current!", i);
+ // We need to wait for the FIFO to drain if the number of buffer
+ // needs to change.
+ //
+ // The condition "number of buffers needs to change" is true if
+ // - the client doesn't care about how many buffers there are
+ // - AND the actual number of buffer is different from what was
+ // set in the last setBufferCountServer()
+ // - OR -
+ // setBufferCountServer() was set to a value incompatible with
+ // the synchronization mode (for instance because the sync mode
+ // changed since)
+ //
+ // As long as this condition is true AND the FIFO is not empty, we
+ // wait on mDequeueCondition.
- if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER) {
- if (state == BufferSlot::FREE || i == mCurrentTexture) {
- foundSync = i;
- if (i != mCurrentTexture) {
- found = i;
- break;
- }
+ const int minBufferCountNeeded = mSynchronousMode ?
+ MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
+
+ const bool numberOfBuffersNeedsToChange = !mClientBufferCount &&
+ ((mServerBufferCount != mBufferCount) ||
+ (mServerBufferCount < minBufferCountNeeded));
+
+ if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {
+ // wait for the FIFO to drain
+ mDequeueCondition.wait(mMutex);
+ // NOTE: we continue here because we need to reevaluate our
+ // whole state (eg: we could be abandoned or disconnected)
+ continue;
+ }
+
+ if (numberOfBuffersNeedsToChange) {
+ // here we're guaranteed that mQueue is empty
+ freeAllBuffersLocked();
+ mBufferCount = mServerBufferCount;
+ if (mBufferCount < minBufferCountNeeded)
+ mBufferCount = minBufferCountNeeded;
+ mCurrentTexture = INVALID_BUFFER_SLOT;
+ returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
+ }
+
+ // look for a free buffer to give to the client
+ found = INVALID_BUFFER_SLOT;
+ foundSync = INVALID_BUFFER_SLOT;
+ dequeuedCount = 0;
+ for (int i = 0; i < mBufferCount; i++) {
+ const int state = mSlots[i].mBufferState;
+ if (state == BufferSlot::DEQUEUED) {
+ dequeuedCount++;
}
- } else {
- if (state == BufferSlot::FREE) {
- /** For Asynchronous mode, we need to return the oldest of free buffers
- * There is only one instance when the Framecounter overflows, this logic
- * might return the earlier buffer to client. Which is a negligible impact
- **/
- if (found < 0 || mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
+
+ // if buffer is FREE it CANNOT be current
+ LOGW_IF((state == BufferSlot::FREE) && (mCurrentTexture==i),
+ "dequeueBuffer: buffer %d is both FREE and current!",
+ i);
+
+ if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER) {
+ if (state == BufferSlot::FREE || i == mCurrentTexture) {
foundSync = i;
- found = i;
+ if (i != mCurrentTexture) {
+ found = i;
+ break;
+ }
+ }
+ } else {
+ if (state == BufferSlot::FREE) {
+ /* We return the oldest of the free buffers to avoid
+ * stalling the producer if possible. This is because
+ * the consumer may still have pending reads of the
+ * buffers in flight.
+ */
+ bool isOlder = mSlots[i].mFrameNumber <
+ mSlots[found].mFrameNumber;
+ if (found < 0 || isOlder) {
+ foundSync = i;
+ found = i;
+ }
}
}
}
- }
- // clients are not allowed to dequeue more than one buffer
- // if they didn't set a buffer count.
- if (!mClientBufferCount && dequeuedCount) {
- ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
- "setting the buffer count");
- return -EINVAL;
- }
+ // clients are not allowed to dequeue more than one buffer
+ // if they didn't set a buffer count.
+ if (!mClientBufferCount && dequeuedCount) {
+ ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
+ "setting the buffer count");
+ return -EINVAL;
+ }
- // See whether a buffer has been queued since the last setBufferCount so
- // we know whether to perform the MIN_UNDEQUEUED_BUFFERS check below.
- bool bufferHasBeenQueued = mCurrentTexture != INVALID_BUFFER_SLOT;
- if (bufferHasBeenQueued) {
- // make sure the client is not trying to dequeue more buffers
- // than allowed.
- const int avail = mBufferCount - (dequeuedCount+1);
- if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
- ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded "
- "(dequeued=%d)",
- MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
- dequeuedCount);
- return -EBUSY;
+ // See whether a buffer has been queued since the last
+ // setBufferCount so we know whether to perform the
+ // MIN_UNDEQUEUED_BUFFERS check below.
+ bool bufferHasBeenQueued = mCurrentTexture != INVALID_BUFFER_SLOT;
+ if (bufferHasBeenQueued) {
+ // make sure the client is not trying to dequeue more buffers
+ // than allowed.
+ const int avail = mBufferCount - (dequeuedCount+1);
+ if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
+ ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded "
+ "(dequeued=%d)",
+ MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
+ dequeuedCount);
+ return -EBUSY;
+ }
+ }
+
+ // we're in synchronous mode and didn't find a buffer, we need to
+ // wait for some buffers to be consumed
+ tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
+ if (tryAgain) {
+ mDequeueCondition.wait(mMutex);
}
}
- // we're in synchronous mode and didn't find a buffer, we need to wait
- // for some buffers to be consumed
- tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
- if (tryAgain) {
- mDequeueCondition.wait(mMutex);
+ if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
+ // foundSync guaranteed to be != INVALID_BUFFER_SLOT
+ found = foundSync;
}
- }
- if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
- // foundSync guaranteed to be != INVALID_BUFFER_SLOT
- found = foundSync;
- }
-
- if (found == INVALID_BUFFER_SLOT) {
- // This should not happen.
- ST_LOGE("dequeueBuffer: no available buffer slots");
- return -EBUSY;
- }
-
- const int buf = found;
- *outBuf = found;
-
- const bool useDefaultSize = !w && !h;
- if (useDefaultSize) {
- // use the default size
- w = mDefaultWidth;
- h = mDefaultHeight;
- }
-
- const bool updateFormat = (format != 0);
- if (!updateFormat) {
- // keep the current (or default) format
- format = mPixelFormat;
- }
-
- // buffer is now in DEQUEUED (but can also be current at the same time,
- // if we're in synchronous mode)
- mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
-
- const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
- if ((buffer == NULL) ||
- (uint32_t(buffer->width) != w) ||
- (uint32_t(buffer->height) != h) ||
- (uint32_t(buffer->format) != format) ||
- ((uint32_t(buffer->usage) & usage) != usage))
- {
- usage |= GraphicBuffer::USAGE_HW_TEXTURE;
- status_t error;
- sp<GraphicBuffer> graphicBuffer(
- mGraphicBufferAlloc->createGraphicBuffer(
- w, h, format, usage, &error));
- if (graphicBuffer == 0) {
- ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
- "failed");
- return error;
+ if (found == INVALID_BUFFER_SLOT) {
+ // This should not happen.
+ ST_LOGE("dequeueBuffer: no available buffer slots");
+ return -EBUSY;
}
- if (updateFormat) {
- mPixelFormat = format;
+
+ const int buf = found;
+ *outBuf = found;
+
+ const bool useDefaultSize = !w && !h;
+ if (useDefaultSize) {
+ // use the default size
+ w = mDefaultWidth;
+ h = mDefaultHeight;
}
- mSlots[buf].mGraphicBuffer = graphicBuffer;
- mSlots[buf].mRequestBufferCalled = false;
- if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(mSlots[buf].mEglDisplay, mSlots[buf].mEglImage);
- mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
- mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
+
+ const bool updateFormat = (format != 0);
+ if (!updateFormat) {
+ // keep the current (or default) format
+ format = mPixelFormat;
}
- if (mCurrentTexture == buf) {
- // The current texture no longer references the buffer in this slot
- // since we just allocated a new buffer.
- mCurrentTexture = INVALID_BUFFER_SLOT;
+
+ // buffer is now in DEQUEUED (but can also be current at the same time,
+ // if we're in synchronous mode)
+ mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
+
+ const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
+ if ((buffer == NULL) ||
+ (uint32_t(buffer->width) != w) ||
+ (uint32_t(buffer->height) != h) ||
+ (uint32_t(buffer->format) != format) ||
+ ((uint32_t(buffer->usage) & usage) != usage))
+ {
+ usage |= GraphicBuffer::USAGE_HW_TEXTURE;
+ status_t error;
+ sp<GraphicBuffer> graphicBuffer(
+ mGraphicBufferAlloc->createGraphicBuffer(
+ w, h, format, usage, &error));
+ if (graphicBuffer == 0) {
+ ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
+ "failed");
+ return error;
+ }
+ if (updateFormat) {
+ mPixelFormat = format;
+ }
+ mSlots[buf].mGraphicBuffer = graphicBuffer;
+ mSlots[buf].mRequestBufferCalled = false;
+ mSlots[buf].mFence = EGL_NO_SYNC_KHR;
+ if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
+ eglDestroyImageKHR(mSlots[buf].mEglDisplay,
+ mSlots[buf].mEglImage);
+ mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
+ mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
+ }
+ if (mCurrentTexture == buf) {
+ // The current texture no longer references the buffer in this slot
+ // since we just allocated a new buffer.
+ mCurrentTexture = INVALID_BUFFER_SLOT;
+ }
+ returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
}
- returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
+
+ dpy = mSlots[buf].mEglDisplay;
+ fence = mSlots[buf].mFence;
+ mSlots[buf].mFence = EGL_NO_SYNC_KHR;
}
+
+ if (fence != EGL_NO_SYNC_KHR) {
+ EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
+ // If something goes wrong, log the error, but return the buffer without
+ // synchronizing access to it. It's too late at this point to abort the
+ // dequeue operation.
+ if (result == EGL_FALSE) {
+ LOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError());
+ } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+ LOGE("dequeueBuffer: timeout waiting for fence");
+ }
+ eglDestroySyncKHR(dpy, fence);
+ }
+
ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", buf,
mSlots[buf].mGraphicBuffer->handle, returnFlags);
+
return returnFlags;
}
@@ -712,8 +763,8 @@
// Update the GL texture object.
EGLImageKHR image = mSlots[buf].mEglImage;
+ EGLDisplay dpy = eglGetCurrentDisplay();
if (image == EGL_NO_IMAGE_KHR) {
- EGLDisplay dpy = eglGetCurrentDisplay();
if (mSlots[buf].mGraphicBuffer == 0) {
ST_LOGE("buffer at slot %d is null", buf);
return BAD_VALUE;
@@ -746,16 +797,32 @@
return -EINVAL;
}
- ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture,
- mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0, buf,
- mSlots[buf].mGraphicBuffer->handle);
+ if (mCurrentTexture != INVALID_BUFFER_SLOT) {
+ if (mUseFenceSync) {
+ EGLSyncKHR fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR,
+ NULL);
+ if (fence == EGL_NO_SYNC_KHR) {
+ LOGE("updateTexImage: error creating fence: %#x",
+ eglGetError());
+ return -EINVAL;
+ }
+ glFlush();
+ mSlots[mCurrentTexture].mFence = fence;
+ }
+ }
+
+ ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)",
+ mCurrentTexture,
+ mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
+ buf, mSlots[buf].mGraphicBuffer->handle);
if (mCurrentTexture != INVALID_BUFFER_SLOT) {
// The current buffer becomes FREE if it was still in the queued
// state. If it has already been given to the client
// (synchronous mode), then it stays in DEQUEUED state.
- if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED)
+ if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED) {
mSlots[mCurrentTexture].mBufferState = BufferSlot::FREE;
+ }
}
// Update the SurfaceTexture state.
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 6d1b951..c313904 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -536,6 +536,20 @@
}
}
+void fillRGBA8BufferSolid(uint8_t* buf, int w, int h, int stride, uint8_t r,
+ uint8_t g, uint8_t b, uint8_t a) {
+ const size_t PIXEL_SIZE = 4;
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < h; x++) {
+ off_t offset = (y * stride + x) * PIXEL_SIZE;
+ buf[offset + 0] = r;
+ buf[offset + 1] = g;
+ buf[offset + 2] = b;
+ buf[offset + 3] = a;
+ }
+ }
+}
+
TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) {
const int texWidth = 64;
const int texHeight = 66;
@@ -1616,4 +1630,101 @@
}
}
+class SurfaceTextureFBOTest : public SurfaceTextureGLTest {
+protected:
+
+ virtual void SetUp() {
+ SurfaceTextureGLTest::SetUp();
+
+ glGenFramebuffers(1, &mFbo);
+ ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+
+ glGenTextures(1, &mFboTex);
+ glBindTexture(GL_TEXTURE_2D, mFboTex);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getSurfaceWidth(),
+ getSurfaceHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+
+ glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, mFboTex, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+ }
+
+ virtual void TearDown() {
+ SurfaceTextureGLTest::TearDown();
+
+ glDeleteTextures(1, &mFboTex);
+ glDeleteFramebuffers(1, &mFbo);
+ }
+
+ GLuint mFbo;
+ GLuint mFboTex;
+};
+
+// This test is intended to verify that proper synchronization is done when
+// rendering into an FBO.
+TEST_F(SurfaceTextureFBOTest, BlitFromCpuFilledBufferToFbo) {
+ const int texWidth = 64;
+ const int texHeight = 64;
+
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+ texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
+ ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+ GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+ android_native_buffer_t* anb;
+ ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+ ASSERT_TRUE(anb != NULL);
+
+ sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+ ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
+
+ // Fill the buffer with green
+ uint8_t* img = NULL;
+ buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+ fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 0, 255,
+ 0, 255);
+ buf->unlock();
+ ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
+
+ ASSERT_EQ(NO_ERROR, mST->updateTexImage());
+
+ glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
+ drawTexture();
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ for (int i = 0; i < 4; i++) {
+ SCOPED_TRACE(String8::format("frame %d", i).string());
+
+ ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+ ASSERT_TRUE(anb != NULL);
+
+ buf = new GraphicBuffer(anb, false);
+ ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(),
+ buf->getNativeBuffer()));
+
+ // Fill the buffer with red
+ ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN,
+ (void**)(&img)));
+ fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 255, 0,
+ 0, 255);
+ ASSERT_EQ(NO_ERROR, buf->unlock());
+ ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(),
+ buf->getNativeBuffer()));
+
+ ASSERT_EQ(NO_ERROR, mST->updateTexImage());
+
+ drawTexture();
+
+ EXPECT_TRUE(checkPixel( 24, 39, 255, 0, 0, 255));
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
+
+ EXPECT_TRUE(checkPixel( 24, 39, 0, 255, 0, 255));
+}
+
} // namespace android
diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp
index b311f35..078be94 100644
--- a/media/libmedia/IStreamSource.cpp
+++ b/media/libmedia/IStreamSource.cpp
@@ -30,7 +30,7 @@
const char *const IStreamListener::kKeyResumeAtPTS = "resume-at-PTS";
// static
-const char *const IStreamListener::kKeyFormatChange = "format-change";
+const char *const IStreamListener::kKeyDiscontinuityMask = "discontinuity-mask";
enum {
// IStreamSource
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 2a5c0a6..93ab704 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -54,6 +54,7 @@
mVideoEOS(false),
mScanSourcesPending(false),
mScanSourcesGeneration(0),
+ mTimeDiscontinuityPending(false),
mFlushingAudio(NONE),
mFlushingVideo(NONE),
mResetInProgress(false),
@@ -462,11 +463,24 @@
{
LOGV("kWhatReset");
+ if (mRenderer != NULL) {
+ // There's an edge case where the renderer owns all output
+ // buffers and is paused, therefore the decoder will not read
+ // more input data and will never encounter the matching
+ // discontinuity. To avoid this, we resume the renderer.
+
+ if (mFlushingAudio == AWAITING_DISCONTINUITY
+ || mFlushingVideo == AWAITING_DISCONTINUITY) {
+ mRenderer->resume();
+ }
+ }
+
if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
// We're currently flushing, postpone the reset until that's
// completed.
- LOGV("postponing reset");
+ LOGV("postponing reset mFlushingAudio=%d, mFlushingVideo=%d",
+ mFlushingAudio, mFlushingVideo);
mResetPostponed = true;
break;
@@ -477,6 +491,8 @@
break;
}
+ mTimeDiscontinuityPending = true;
+
if (mAudioDecoder != NULL) {
flushDecoder(true /* audio */, true /* needShutdown */);
}
@@ -540,7 +556,10 @@
LOGV("both audio and video are flushed now.");
- mRenderer->signalTimeDiscontinuity();
+ if (mTimeDiscontinuityPending) {
+ mRenderer->signalTimeDiscontinuity();
+ mTimeDiscontinuityPending = false;
+ }
if (mAudioDecoder != NULL) {
mAudioDecoder->signalResume();
@@ -663,10 +682,15 @@
CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
bool formatChange =
- type == ATSParser::DISCONTINUITY_FORMATCHANGE;
+ (audio &&
+ (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
+ || (!audio &&
+ (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
- LOGV("%s discontinuity (formatChange=%d)",
- audio ? "audio" : "video", formatChange);
+ bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
+
+ LOGI("%s discontinuity (formatChange=%d, time=%d)",
+ audio ? "audio" : "video", formatChange, timeChange);
if (audio) {
mSkipRenderingAudioUntilMediaTimeUs = -1;
@@ -674,26 +698,45 @@
mSkipRenderingVideoUntilMediaTimeUs = -1;
}
- sp<AMessage> extra;
- if (accessUnit->meta()->findMessage("extra", &extra)
- && extra != NULL) {
- int64_t resumeAtMediaTimeUs;
- if (extra->findInt64(
- "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
- LOGI("suppressing rendering of %s until %lld us",
- audio ? "audio" : "video", resumeAtMediaTimeUs);
+ if (timeChange) {
+ sp<AMessage> extra;
+ if (accessUnit->meta()->findMessage("extra", &extra)
+ && extra != NULL) {
+ int64_t resumeAtMediaTimeUs;
+ if (extra->findInt64(
+ "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
+ LOGI("suppressing rendering of %s until %lld us",
+ audio ? "audio" : "video", resumeAtMediaTimeUs);
- if (audio) {
- mSkipRenderingAudioUntilMediaTimeUs =
- resumeAtMediaTimeUs;
- } else {
- mSkipRenderingVideoUntilMediaTimeUs =
- resumeAtMediaTimeUs;
+ if (audio) {
+ mSkipRenderingAudioUntilMediaTimeUs =
+ resumeAtMediaTimeUs;
+ } else {
+ mSkipRenderingVideoUntilMediaTimeUs =
+ resumeAtMediaTimeUs;
+ }
}
}
}
- flushDecoder(audio, formatChange);
+ mTimeDiscontinuityPending =
+ mTimeDiscontinuityPending || timeChange;
+
+ if (formatChange || timeChange) {
+ flushDecoder(audio, formatChange);
+ } else {
+ // This stream is unaffected by the discontinuity
+
+ if (audio) {
+ mFlushingAudio = FLUSHED;
+ } else {
+ mFlushingVideo = FLUSHED;
+ }
+
+ finishFlushIfPossible();
+
+ return -EWOULDBLOCK;
+ }
}
reply->setInt32("err", err);
@@ -794,6 +837,11 @@
}
void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
+ if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
+ LOGI("flushDecoder %s without decoder present",
+ audio ? "audio" : "video");
+ }
+
// Make sure we don't continue to scan sources until we finish flushing.
++mScanSourcesGeneration;
mScanSourcesPending = false;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index f23deea..ffc710e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -112,6 +112,10 @@
SHUT_DOWN,
};
+ // Once the current flush is complete this indicates whether the
+ // notion of time has changed.
+ bool mTimeDiscontinuityPending;
+
FlushStatus mFlushingAudio;
FlushStatus mFlushingVideo;
bool mResetInProgress;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 640e9fa..0cb7f45 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -628,11 +628,16 @@
mAudioSink->pause();
}
+ LOGV("now paused audio queue has %d entries, video has %d entries",
+ mAudioQueue.size(), mVideoQueue.size());
+
mPaused = true;
}
void NuPlayer::Renderer::onResume() {
- CHECK(mPaused);
+ if (!mPaused) {
+ return;
+ }
if (mHasAudio) {
mAudioSink->start();
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index f795654..2e63b3b 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -63,17 +63,22 @@
mFinalResult = ERROR_END_OF_STREAM;
break;
} else if (n == INFO_DISCONTINUITY) {
- ATSParser::DiscontinuityType type = ATSParser::DISCONTINUITY_SEEK;
+ int32_t type = ATSParser::DISCONTINUITY_SEEK;
- int32_t formatChange;
+ int32_t mask;
if (extra != NULL
&& extra->findInt32(
- IStreamListener::kKeyFormatChange, &formatChange)
- && formatChange != 0) {
- type = ATSParser::DISCONTINUITY_FORMATCHANGE;
+ IStreamListener::kKeyDiscontinuityMask, &mask)) {
+ if (mask == 0) {
+ LOGE("Client specified an illegal discontinuity type.");
+ return ERROR_UNSUPPORTED;
+ }
+
+ type = mask;
}
- mTSParser->signalDiscontinuity(type, extra);
+ mTSParser->signalDiscontinuity(
+ (ATSParser::DiscontinuityType)type, extra);
} else if (n < 0) {
CHECK_EQ(n, -EWOULDBLOCK);
break;
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index d947760..dbc9b7e 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -342,6 +342,7 @@
}
void ACodec::signalFlush() {
+ LOGV("[%s] signalFlush", mComponentName.c_str());
(new AMessage(kWhatFlush, id()))->post();
}
@@ -1092,6 +1093,20 @@
return OK;
}
+size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
+ size_t n = 0;
+
+ for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
+ const BufferInfo &info = mBuffers[portIndex].itemAt(i);
+
+ if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
+ ++n;
+ }
+ }
+
+ return n;
+}
+
bool ACodec::allYourBuffersAreBelongToUs(
OMX_U32 portIndex) {
for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
@@ -2041,6 +2056,14 @@
case kWhatFlush:
{
+ LOGV("[%s] ExecutingState flushing now "
+ "(codec owns %d/%d input, %d/%d output).",
+ mCodec->mComponentName.c_str(),
+ mCodec->countBuffersOwnedByComponent(kPortIndexInput),
+ mCodec->mBuffers[kPortIndexInput].size(),
+ mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
+ mCodec->mBuffers[kPortIndexOutput].size());
+
mActive = false;
CHECK_EQ(mCodec->mOMX->sendCommand(
@@ -2180,6 +2203,12 @@
err);
mCodec->signalError();
+
+ // This is technically not correct, since we were unable
+ // to allocate output buffers and therefore the output port
+ // remains disabled. It is necessary however to allow us
+ // to shutdown the codec properly.
+ mCodec->changeState(mCodec->mExecutingState);
}
return true;
@@ -2408,6 +2437,9 @@
bool ACodec::FlushingState::onOMXEvent(
OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
+ LOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
+ mCodec->mComponentName.c_str(), event, data1);
+
switch (event) {
case OMX_EventCmdComplete:
{
diff --git a/media/libstagefright/AVIExtractor.cpp b/media/libstagefright/AVIExtractor.cpp
index 0be2ca4..815f987 100644
--- a/media/libstagefright/AVIExtractor.cpp
+++ b/media/libstagefright/AVIExtractor.cpp
@@ -1094,7 +1094,7 @@
CHECK(meta->findData(kKeyAVCC, &type, &csd, &csdSize));
track->mMeta->setInt32(kKeyWidth, width);
- track->mMeta->setInt32(kKeyHeight, width);
+ track->mMeta->setInt32(kKeyHeight, height);
track->mMeta->setData(kKeyAVCC, type, csd, csdSize);
return OK;
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index 2b27ee2..86b33d1 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -336,7 +336,7 @@
(uint32_t(buffer->height) != h) ||
(uint32_t(buffer->format) != format) ||
((uint32_t(buffer->usage) & usage) != usage)) {
- usage |= GraphicBuffer::USAGE_HW_TEXTURE;
+ usage |= GraphicBuffer::USAGE_HW_VIDEO_ENCODER;
status_t error;
sp<GraphicBuffer> graphicBuffer(
mGraphicBufferAlloc->createGraphicBuffer(
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 72f1282..6cec63a 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -123,6 +123,9 @@
void extractAACFrames(const sp<ABuffer> &buffer);
+ bool isAudio() const;
+ bool isVideo() const;
+
DISALLOW_EVIL_CONSTRUCTORS(Stream);
};
@@ -401,7 +404,7 @@
case STREAMTYPE_H264:
mQueue = new ElementaryStreamQueue(ElementaryStreamQueue::H264);
break;
- case STREAMTYPE_MPEG2_AUDIO_ATDS:
+ case STREAMTYPE_MPEG2_AUDIO_ADTS:
mQueue = new ElementaryStreamQueue(ElementaryStreamQueue::AAC);
break;
case STREAMTYPE_MPEG1_AUDIO:
@@ -486,6 +489,31 @@
return OK;
}
+bool ATSParser::Stream::isVideo() const {
+ switch (mStreamType) {
+ case STREAMTYPE_H264:
+ case STREAMTYPE_MPEG1_VIDEO:
+ case STREAMTYPE_MPEG2_VIDEO:
+ case STREAMTYPE_MPEG4_VIDEO:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool ATSParser::Stream::isAudio() const {
+ switch (mStreamType) {
+ case STREAMTYPE_MPEG1_AUDIO:
+ case STREAMTYPE_MPEG2_AUDIO:
+ case STREAMTYPE_MPEG2_AUDIO_ADTS:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
void ATSParser::Stream::signalDiscontinuity(
DiscontinuityType type, const sp<AMessage> &extra) {
if (mQueue == NULL) {
@@ -495,34 +523,34 @@
mPayloadStarted = false;
mBuffer->setRange(0, 0);
- switch (type) {
- case DISCONTINUITY_SEEK:
- case DISCONTINUITY_FORMATCHANGE:
- {
- bool isASeek = (type == DISCONTINUITY_SEEK);
-
- mQueue->clear(!isASeek);
-
- uint64_t resumeAtPTS;
- if (extra != NULL
- && extra->findInt64(
- IStreamListener::kKeyResumeAtPTS,
- (int64_t *)&resumeAtPTS)) {
- int64_t resumeAtMediaTimeUs =
- mProgram->convertPTSToTimestamp(resumeAtPTS);
-
- extra->setInt64("resume-at-mediatimeUs", resumeAtMediaTimeUs);
- }
-
- if (mSource != NULL) {
- mSource->queueDiscontinuity(type, extra);
- }
- break;
+ bool clearFormat = false;
+ if (isAudio()) {
+ if (type & DISCONTINUITY_AUDIO_FORMAT) {
+ clearFormat = true;
}
+ } else {
+ if (type & DISCONTINUITY_VIDEO_FORMAT) {
+ clearFormat = true;
+ }
+ }
- default:
- TRESPASS();
- break;
+ mQueue->clear(clearFormat);
+
+ if (type & DISCONTINUITY_TIME) {
+ uint64_t resumeAtPTS;
+ if (extra != NULL
+ && extra->findInt64(
+ IStreamListener::kKeyResumeAtPTS,
+ (int64_t *)&resumeAtPTS)) {
+ int64_t resumeAtMediaTimeUs =
+ mProgram->convertPTSToTimestamp(resumeAtPTS);
+
+ extra->setInt64("resume-at-mediatimeUs", resumeAtMediaTimeUs);
+ }
+ }
+
+ if (mSource != NULL) {
+ mSource->queueDiscontinuity(type, extra);
}
}
@@ -764,10 +792,7 @@
switch (type) {
case VIDEO:
{
- if (mStreamType == STREAMTYPE_H264
- || mStreamType == STREAMTYPE_MPEG1_VIDEO
- || mStreamType == STREAMTYPE_MPEG2_VIDEO
- || mStreamType == STREAMTYPE_MPEG4_VIDEO) {
+ if (isVideo()) {
return mSource;
}
break;
@@ -775,9 +800,7 @@
case AUDIO:
{
- if (mStreamType == STREAMTYPE_MPEG1_AUDIO
- || mStreamType == STREAMTYPE_MPEG2_AUDIO
- || mStreamType == STREAMTYPE_MPEG2_AUDIO_ATDS) {
+ if (isAudio()) {
return mSource;
}
break;
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index 878e534..c8038d1 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -33,9 +33,18 @@
struct ATSParser : public RefBase {
enum DiscontinuityType {
- DISCONTINUITY_NONE,
- DISCONTINUITY_SEEK,
- DISCONTINUITY_FORMATCHANGE
+ DISCONTINUITY_NONE = 0,
+ DISCONTINUITY_TIME = 1,
+ DISCONTINUITY_AUDIO_FORMAT = 2,
+ DISCONTINUITY_VIDEO_FORMAT = 4,
+
+ DISCONTINUITY_SEEK = DISCONTINUITY_TIME,
+
+ // For legacy reasons this also implies a time discontinuity.
+ DISCONTINUITY_FORMATCHANGE =
+ DISCONTINUITY_AUDIO_FORMAT
+ | DISCONTINUITY_VIDEO_FORMAT
+ | DISCONTINUITY_TIME,
};
enum Flags {
@@ -71,7 +80,7 @@
STREAMTYPE_MPEG2_VIDEO = 0x02,
STREAMTYPE_MPEG1_AUDIO = 0x03,
STREAMTYPE_MPEG2_AUDIO = 0x04,
- STREAMTYPE_MPEG2_AUDIO_ATDS = 0x0f,
+ STREAMTYPE_MPEG2_AUDIO_ADTS = 0x0f,
STREAMTYPE_MPEG4_VIDEO = 0x10,
STREAMTYPE_H264 = 0x1b,
};
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index ce07e32..f782ce5 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -29,8 +29,17 @@
namespace android {
AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta)
- : mFormat(meta),
+ : mIsAudio(false),
+ mFormat(meta),
mEOSResult(OK) {
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (!strncasecmp("audio/", mime, 6)) {
+ mIsAudio = true;
+ } else {
+ CHECK(!strncasecmp("video/", mime, 6));
+ }
}
void AnotherPacketSource::setFormat(const sp<MetaData> &meta) {
@@ -67,8 +76,7 @@
int32_t discontinuity;
if ((*buffer)->meta()->findInt32("discontinuity", &discontinuity)) {
-
- if (discontinuity == ATSParser::DISCONTINUITY_FORMATCHANGE) {
+ if (wasFormatChange(discontinuity)) {
mFormat.clear();
}
@@ -96,7 +104,7 @@
int32_t discontinuity;
if (buffer->meta()->findInt32("discontinuity", &discontinuity)) {
- if (discontinuity == ATSParser::DISCONTINUITY_FORMATCHANGE) {
+ if (wasFormatChange(discontinuity)) {
mFormat.clear();
}
@@ -117,6 +125,15 @@
return mEOSResult;
}
+bool AnotherPacketSource::wasFormatChange(
+ int32_t discontinuityType) const {
+ if (mIsAudio) {
+ return (discontinuityType & ATSParser::DISCONTINUITY_AUDIO_FORMAT) != 0;
+ }
+
+ return (discontinuityType & ATSParser::DISCONTINUITY_VIDEO_FORMAT) != 0;
+}
+
void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
int32_t damaged;
if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
index 439c7853..c99f7f2 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -61,10 +61,13 @@
Mutex mLock;
Condition mCondition;
+ bool mIsAudio;
sp<MetaData> mFormat;
List<sp<ABuffer> > mBuffers;
status_t mEOSResult;
+ bool wasFormatChange(int32_t discontinuityType) const;
+
DISALLOW_EVIL_CONSTRUCTORS(AnotherPacketSource);
};
diff --git a/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
index f55be6e..a089dbf 100644
--- a/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
+++ b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
@@ -543,7 +543,7 @@
case ATSParser::STREAMTYPE_H264:
mode = ElementaryStreamQueue::H264;
break;
- case ATSParser::STREAMTYPE_MPEG2_AUDIO_ATDS:
+ case ATSParser::STREAMTYPE_MPEG2_AUDIO_ADTS:
mode = ElementaryStreamQueue::AAC;
break;
case ATSParser::STREAMTYPE_MPEG1_AUDIO:
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
index 3fb2da0..92ac9eb 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
@@ -39,6 +39,7 @@
import com.android.mediaframeworktest.functional.videoeditor.VideoEditorPreviewTest;
import junit.framework.TestSuite;
+import android.os.Bundle;
import android.test.InstrumentationTestRunner;
import android.test.InstrumentationTestSuite;
@@ -54,6 +55,7 @@
public class MediaFrameworkTestRunner extends InstrumentationTestRunner {
+ public static int mMinCameraFps = 0;
@Override
public TestSuite getAllTests() {
@@ -87,4 +89,16 @@
public ClassLoader getLoader() {
return MediaFrameworkTestRunner.class.getClassLoader();
}
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ String minCameraFps = (String) icicle.get("min_camera_fps");
+ System.out.print("min_camera_" + minCameraFps);
+
+ if (minCameraFps != null ) {
+ mMinCameraFps = Integer.parseInt(minCameraFps);
+ }
+ }
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediarecorder/MediaRecorderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediarecorder/MediaRecorderTest.java
index b5c8c8c..0684946 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediarecorder/MediaRecorderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediarecorder/MediaRecorderTest.java
@@ -33,6 +33,7 @@
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import com.android.mediaframeworktest.MediaProfileReader;
+import com.android.mediaframeworktest.MediaFrameworkTestRunner;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.Suppress;
@@ -115,9 +116,16 @@
int audioChannels = highQuality? audioCap.mMaxChannels: audioCap.mMinChannels ;
int audioSamplingRate = highQuality? audioCap.mMaxSampleRate: audioCap.mMinSampleRate;
+ //Overide the fps if the min_camera_fps is set
+ if (MediaFrameworkTestRunner.mMinCameraFps != 0 &&
+ MediaFrameworkTestRunner.mMinCameraFps > videoFps){
+ videoFps = MediaFrameworkTestRunner.mMinCameraFps;
+ }
+
if (videoFps < MIN_VIDEO_FPS) {
videoFps = MIN_VIDEO_FPS;
}
+
mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
String filename = ("/sdcard/" + videoEncoder + "_" + audioEncoder + "_" + highQuality + ".3gp");
try {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
index 0b887b9..4f6e7d2 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
@@ -37,11 +37,13 @@
import android.view.SurfaceHolder;
import java.util.List;
+import java.io.BufferedReader;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.Writer;
import java.io.File;
import java.io.FileWriter;
@@ -68,6 +70,8 @@
private static final long MEDIA_STRESS_WAIT_TIME = 5000; //5 seconds
private static final String MEDIA_MEMORY_OUTPUT =
"/sdcard/mediaMemOutput.txt";
+ private static final String MEDIA_PROCMEM_OUTPUT =
+ "/sdcard/mediaProcmemOutput.txt";
private static int mStartMemory = 0;
private static int mEndMemory = 0;
@@ -84,6 +88,9 @@
private static int DECODER_LIMIT = 150;
private static int CAMERA_LIMIT = 80;
+ private Writer mProcMemWriter;
+ private Writer mMemWriter;
+
private static List<VideoEncoderCap> videoEncoders = MediaProfileReader.getVideoEncoders();
Camera mCamera;
@@ -97,12 +104,21 @@
getActivity();
if (MediaFrameworkPerfTestRunner.mGetNativeHeapDump)
MediaTestUtil.getNativeHeapDump(this.getName() + "_before");
+
+ mProcMemWriter = new BufferedWriter(new FileWriter
+ (new File(MEDIA_PROCMEM_OUTPUT), true));
+ mProcMemWriter.write(this.getName() + "\n");
+ mMemWriter = new BufferedWriter(new FileWriter
+ (new File(MEDIA_MEMORY_OUTPUT), true));
+
}
protected void tearDown() throws Exception {
- super.tearDown();
if (MediaFrameworkPerfTestRunner.mGetNativeHeapDump)
MediaTestUtil.getNativeHeapDump(this.getName() + "_after");
+ mProcMemWriter.close();
+ mMemWriter.close();
+ super.tearDown();
}
private void initializeMessageLooper() {
@@ -247,24 +263,39 @@
}
//Write the ps output to the file
- public void getMemoryWriteToLog(Writer output, int writeCount) {
+ public void getMemoryWriteToLog(int writeCount) {
String memusage = null;
try {
if (writeCount == 0) {
mStartMemory = getMediaserverVsize();
- output.write("Start memory : " + mStartMemory + "\n");
+ mMemWriter.write("Start memory : " + mStartMemory + "\n");
}
memusage = captureMediaserverInfo();
- output.write(memusage);
+ mMemWriter.write(memusage);
if (writeCount == NUM_STRESS_LOOP - 1) {
mEndMemory = getMediaserverVsize();
- output.write("End Memory :" + mEndMemory + "\n");
+ mMemWriter.write("End Memory :" + mEndMemory + "\n");
}
} catch (Exception e) {
e.toString();
}
}
+ public void writeProcmemInfo() throws Exception{
+ String cmd = "procmem " + getMediaserverPid();
+ Process p = Runtime.getRuntime().exec(cmd);
+
+ InputStream inStream = p.getInputStream();
+ InputStreamReader inReader = new InputStreamReader(inStream);
+ BufferedReader inBuffer = new BufferedReader(inReader);
+ String s;
+ while ((s = inBuffer.readLine()) != null) {
+ mProcMemWriter.write(s);
+ mProcMemWriter.write("\n");
+ }
+ mProcMemWriter.write("\n\n");
+ }
+
public String captureMediaserverInfo() {
String cm = "ps mediaserver";
String memoryUsage = null;
@@ -306,7 +337,7 @@
return vsizevalue;
}
- public boolean validateMemoryResult(int startPid, int startMemory, Writer output, int limit)
+ public boolean validateMemoryResult(int startPid, int startMemory, int limit)
throws Exception {
// Wait for 10 seconds to make sure the memory settle.
Thread.sleep(10000);
@@ -315,11 +346,11 @@
if (memDiff < 0) {
memDiff = 0;
}
- output.write("The total diff = " + memDiff);
- output.write("\n\n");
+ mMemWriter.write("The total diff = " + memDiff);
+ mMemWriter.write("\n\n");
// mediaserver crash
if (startPid != mEndPid) {
- output.write("mediaserver died. Test failed\n");
+ mMemWriter.write("mediaserver died. Test failed\n");
return false;
}
// memory leak greter than the tolerant
@@ -331,18 +362,16 @@
@LargeTest
public void testH263VideoPlaybackMemoryUsage() throws Exception {
boolean memoryResult = false;
- mStartPid = getMediaserverPid();
- File h263MemoryOut = new File(MEDIA_MEMORY_OUTPUT);
- Writer output = new BufferedWriter(new FileWriter(h263MemoryOut, true));
- output.write("H263 Video Playback Only\n");
+ mStartPid = getMediaserverPid();
+ mMemWriter.write("H263 Video Playback Only\n");
for (int i = 0; i < NUM_STRESS_LOOP; i++) {
mediaStressPlayback(MediaNames.VIDEO_HIGHRES_H263);
- getMemoryWriteToLog(output, i);
+ getMemoryWriteToLog(i);
+ writeProcmemInfo();
}
- output.write("\n");
- memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, DECODER_LIMIT);
- output.close();
+ mMemWriter.write("\n");
+ memoryResult = validateMemoryResult(mStartPid, mStartMemory, DECODER_LIMIT);
assertTrue("H263 playback memory test", memoryResult);
}
@@ -350,18 +379,16 @@
@LargeTest
public void testH264VideoPlaybackMemoryUsage() throws Exception {
boolean memoryResult = false;
- mStartPid = getMediaserverPid();
- File h264MemoryOut = new File(MEDIA_MEMORY_OUTPUT);
- Writer output = new BufferedWriter(new FileWriter(h264MemoryOut, true));
- output.write("H264 Video Playback only\n");
+ mStartPid = getMediaserverPid();
+ mMemWriter.write("H264 Video Playback only\n");
for (int i = 0; i < NUM_STRESS_LOOP; i++) {
mediaStressPlayback(MediaNames.VIDEO_H264_AMR);
- getMemoryWriteToLog(output, i);
+ getMemoryWriteToLog(i);
+ writeProcmemInfo();
}
- output.write("\n");
- memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, DECODER_LIMIT);
- output.close();
+ mMemWriter.write("\n");
+ memoryResult = validateMemoryResult(mStartPid, mStartMemory, DECODER_LIMIT);
assertTrue("H264 playback memory test", memoryResult);
}
@@ -369,21 +396,19 @@
@LargeTest
public void testH263RecordVideoOnlyMemoryUsage() throws Exception {
boolean memoryResult = false;
- mStartPid = getMediaserverPid();
- File videoH263RecordOnlyMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
- Writer output = new BufferedWriter(new FileWriter(videoH263RecordOnlyMemoryOut, true));
- output.write("H263 video record only\n");
+ mStartPid = getMediaserverPid();
+ mMemWriter.write("H263 video record only\n");
int frameRate = MediaProfileReader.getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H263);
assertTrue("H263 video recording frame rate", frameRate != -1);
for (int i = 0; i < NUM_STRESS_LOOP; i++) {
assertTrue(stressVideoRecord(frameRate, 352, 288, MediaRecorder.VideoEncoder.H263,
MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true));
- getMemoryWriteToLog(output, i);
+ getMemoryWriteToLog(i);
+ writeProcmemInfo();
}
- output.write("\n");
- memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, ENCODER_LIMIT);
- output.close();
+ mMemWriter.write("\n");
+ memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
assertTrue("H263 record only memory test", memoryResult);
}
@@ -391,21 +416,19 @@
@LargeTest
public void testMpeg4RecordVideoOnlyMemoryUsage() throws Exception {
boolean memoryResult = false;
- mStartPid = getMediaserverPid();
- File videoMp4RecordOnlyMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
- Writer output = new BufferedWriter(new FileWriter(videoMp4RecordOnlyMemoryOut, true));
- output.write("MPEG4 video record only\n");
+ mStartPid = getMediaserverPid();
+ mMemWriter.write("MPEG4 video record only\n");
int frameRate = MediaProfileReader.getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.MPEG_4_SP);
assertTrue("MPEG4 video recording frame rate", frameRate != -1);
for (int i = 0; i < NUM_STRESS_LOOP; i++) {
assertTrue(stressVideoRecord(frameRate, 352, 288, MediaRecorder.VideoEncoder.MPEG_4_SP,
MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true));
- getMemoryWriteToLog(output, i);
+ getMemoryWriteToLog(i);
+ writeProcmemInfo();
}
- output.write("\n");
- memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, ENCODER_LIMIT);
- output.close();
+ mMemWriter.write("\n");
+ memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
assertTrue("mpeg4 record only memory test", memoryResult);
}
@@ -414,21 +437,19 @@
@LargeTest
public void testRecordVideoAudioMemoryUsage() throws Exception {
boolean memoryResult = false;
- mStartPid = getMediaserverPid();
- File videoRecordAudioMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
- Writer output = new BufferedWriter(new FileWriter(videoRecordAudioMemoryOut, true));
+ mStartPid = getMediaserverPid();
int frameRate = MediaProfileReader.getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H263);
assertTrue("H263 video recording frame rate", frameRate != -1);
- output.write("Audio and h263 video record\n");
+ mMemWriter.write("Audio and h263 video record\n");
for (int i = 0; i < NUM_STRESS_LOOP; i++) {
assertTrue(stressVideoRecord(frameRate, 352, 288, MediaRecorder.VideoEncoder.H263,
MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, false));
- getMemoryWriteToLog(output, i);
+ getMemoryWriteToLog(i);
+ writeProcmemInfo();
}
- output.write("\n");
- memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, ENCODER_LIMIT);
- output.close();
+ mMemWriter.write("\n");
+ memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
assertTrue("H263 audio video record memory test", memoryResult);
}
@@ -436,18 +457,16 @@
@LargeTest
public void testRecordAudioOnlyMemoryUsage() throws Exception {
boolean memoryResult = false;
- mStartPid = getMediaserverPid();
- File audioOnlyMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
- Writer output = new BufferedWriter(new FileWriter(audioOnlyMemoryOut, true));
- output.write("Audio record only\n");
+ mStartPid = getMediaserverPid();
+ mMemWriter.write("Audio record only\n");
for (int i = 0; i < NUM_STRESS_LOOP; i++) {
stressAudioRecord(MediaNames.RECORDER_OUTPUT);
- getMemoryWriteToLog(output, i);
+ getMemoryWriteToLog(i);
+ writeProcmemInfo();
}
- output.write("\n");
- memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, ENCODER_LIMIT);
- output.close();
+ mMemWriter.write("\n");
+ memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
assertTrue("audio record only memory test", memoryResult);
}
@@ -455,18 +474,16 @@
@LargeTest
public void testCameraPreviewMemoryUsage() throws Exception {
boolean memoryResult = false;
- mStartPid = getMediaserverPid();
- File cameraPreviewMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
- Writer output = new BufferedWriter(new FileWriter(cameraPreviewMemoryOut, true));
- output.write("Camera Preview Only\n");
+ mStartPid = getMediaserverPid();
+ mMemWriter.write("Camera Preview Only\n");
for (int i = 0; i < NUM_STRESS_LOOP; i++) {
stressCameraPreview();
- getMemoryWriteToLog(output, i);
+ getMemoryWriteToLog(i);
+ writeProcmemInfo();
}
- output.write("\n");
- memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, CAMERA_LIMIT);
- output.close();
+ mMemWriter.write("\n");
+ memoryResult = validateMemoryResult(mStartPid, mStartMemory, CAMERA_LIMIT);
assertTrue("camera preview memory test", memoryResult);
}
}
diff --git a/native/include/android/keycodes.h b/native/include/android/keycodes.h
index 5d49775..8414ff6 100644
--- a/native/include/android/keycodes.h
+++ b/native/include/android/keycodes.h
@@ -250,6 +250,10 @@
AKEYCODE_LANGUAGE_SWITCH = 204,
AKEYCODE_MANNER_MODE = 205,
AKEYCODE_3D_MODE = 206,
+ AKEYCODE_CONTACTS = 207,
+ AKEYCODE_CALENDAR = 208,
+ AKEYCODE_MUSIC = 209,
+ AKEYCODE_CALCULATOR = 210,
// NOTE: If you add a new keycode here you must also add it to several other files.
// Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index a63d5b0..2b0ed5d 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -49,6 +49,8 @@
// ----------------------------------------------------------------------------
+#define EGL_VERSION_HW_ANDROID 0x3143
+
struct extention_map_t {
const char* name;
__eglMustCastToProperFunctionPointerType address;
@@ -972,6 +974,12 @@
return dp->getExtensionString();
case EGL_CLIENT_APIS:
return dp->getClientApiString();
+ case EGL_VERSION_HW_ANDROID: {
+ if (gEGLImpl[IMPL_HARDWARE].dso) {
+ return dp->disp[IMPL_HARDWARE].queryString.version;
+ }
+ return dp->disp[IMPL_SOFTWARE].queryString.version;
+ }
}
return setError(EGL_BAD_PARAMETER, (const char *)0);
}
diff --git a/opengl/specs/README b/opengl/specs/README
index 2fa2587..16b278f 100644
--- a/opengl/specs/README
+++ b/opengl/specs/README
@@ -9,4 +9,5 @@
0x3140 EGL_ANDROID_image_native_buffer
0x3141 (unused)
0x3142 EGL_ANDROID_recordable
-0x3143 - 0x314F (unused)
+0x3143 EGL_VERSION_HW_ANDROID (internal use)
+0x3144 - 0x314F (unused)
diff --git a/packages/SettingsProvider/res/values-vi/strings.xml b/packages/SettingsProvider/res/values-vi/strings.xml
index 113d7ad..504479d 100644
--- a/packages/SettingsProvider/res/values-vi/strings.xml
+++ b/packages/SettingsProvider/res/values-vi/strings.xml
@@ -19,5 +19,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4567566098528588863">"Bộ nhớ Cài đặt"</string>
+ <string name="app_label" msgid="4567566098528588863">"Lưu trữ cài đặt"</string>
</resources>
diff --git a/packages/SettingsProvider/res/xml/bookmarks.xml b/packages/SettingsProvider/res/xml/bookmarks.xml
index 83229f4..454f456 100644
--- a/packages/SettingsProvider/res/xml/bookmarks.xml
+++ b/packages/SettingsProvider/res/xml/bookmarks.xml
@@ -19,6 +19,7 @@
Bookmarks for vendor apps should be added to a bookmarks resource overlay; not here.
Typical shortcuts (not necessarily defined here):
+ 'a': Calculator
'b': Browser
'c': Contacts
'e': Email
@@ -32,27 +33,27 @@
-->
<bookmarks>
<bookmark
- package="com.android.browser"
- class="com.android.browser.BrowserActivity"
+ category="android.intent.category.APP_CALCULATOR"
+ shortcut="a" />
+ <bookmark
+ category="android.intent.category.APP_BROWSER"
shortcut="b" />
<bookmark
- package="com.android.contacts"
- class="com.android.contacts.activities.ContactsFrontDoor"
+ category="android.intent.category.APP_CONTACTS"
shortcut="c" />
<bookmark
- package="com.google.android.email"
- class="com.android.email.activity.Welcome"
+ category="android.intent.category.APP_EMAIL"
shortcut="e" />
<bookmark
- package="com.google.android.calendar"
- class="com.android.calendar.LaunchActivity"
+ category="android.intent.category.APP_CALENDAR"
shortcut="l" />
<bookmark
- package="com.android.music"
- class="com.android.music.MusicBrowserActivity"
+ category="android.intent.category.APP_MAPS"
+ shortcut="m" />
+ <bookmark
+ category="android.intent.category.APP_MUSIC"
shortcut="p" />
<bookmark
- package="com.android.mms"
- class="com.android.mms.ui.ConversationList"
+ category="android.intent.category.APP_MESSAGING"
shortcut="s" />
</bookmarks>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index aa08e64..080d345 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -63,7 +63,7 @@
// database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
// is properly propagated through your change. Not doing so will result in a loss of user
// settings.
- private static final int DATABASE_VERSION = 70;
+ private static final int DATABASE_VERSION = 71;
private Context mContext;
@@ -946,6 +946,12 @@
upgradeVersion = 70;
}
+ if (upgradeVersion == 70) {
+ // Update all built-in bookmarks. Some of the package names have changed.
+ loadBookmarks(db);
+ upgradeVersion = 71;
+ }
+
// *** Remember to update DATABASE_VERSION above!
if (upgradeVersion != currentVersion) {
@@ -1086,16 +1092,11 @@
* Loads the default set of bookmarked shortcuts from an xml file.
*
* @param db The database to write the values into
- * @param startingIndex The zero-based position at which bookmarks in this file should begin
*/
- private int loadBookmarks(SQLiteDatabase db, int startingIndex) {
- Intent intent = new Intent(Intent.ACTION_MAIN, null);
- intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ private void loadBookmarks(SQLiteDatabase db) {
ContentValues values = new ContentValues();
PackageManager packageManager = mContext.getPackageManager();
- int i = startingIndex;
-
try {
XmlResourceParser parser = mContext.getResources().getXml(R.xml.bookmarks);
XmlUtils.beginDocument(parser, "bookmarks");
@@ -1118,54 +1119,60 @@
String pkg = parser.getAttributeValue(null, "package");
String cls = parser.getAttributeValue(null, "class");
String shortcutStr = parser.getAttributeValue(null, "shortcut");
+ String category = parser.getAttributeValue(null, "category");
int shortcutValue = shortcutStr.charAt(0);
if (TextUtils.isEmpty(shortcutStr)) {
Log.w(TAG, "Unable to get shortcut for: " + pkg + "/" + cls);
+ continue;
}
- ActivityInfo info = null;
- ComponentName cn = new ComponentName(pkg, cls);
- try {
- info = packageManager.getActivityInfo(cn, 0);
- } catch (PackageManager.NameNotFoundException e) {
- String[] packages = packageManager.canonicalToCurrentPackageNames(
- new String[] { pkg });
- cn = new ComponentName(packages[0], cls);
+ final Intent intent;
+ final String title;
+ if (pkg != null && cls != null) {
+ ActivityInfo info = null;
+ ComponentName cn = new ComponentName(pkg, cls);
try {
info = packageManager.getActivityInfo(cn, 0);
- } catch (PackageManager.NameNotFoundException e1) {
- Log.w(TAG, "Unable to add bookmark: " + pkg + "/" + cls, e);
+ } catch (PackageManager.NameNotFoundException e) {
+ String[] packages = packageManager.canonicalToCurrentPackageNames(
+ new String[] { pkg });
+ cn = new ComponentName(packages[0], cls);
+ try {
+ info = packageManager.getActivityInfo(cn, 0);
+ } catch (PackageManager.NameNotFoundException e1) {
+ Log.w(TAG, "Unable to add bookmark: " + pkg + "/" + cls, e);
+ continue;
+ }
}
- }
-
- if (info != null) {
+
+ intent = new Intent(Intent.ACTION_MAIN, null);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setComponent(cn);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- values.put(Settings.Bookmarks.INTENT, intent.toUri(0));
- values.put(Settings.Bookmarks.TITLE,
- info.loadLabel(packageManager).toString());
- values.put(Settings.Bookmarks.SHORTCUT, shortcutValue);
- db.insert("bookmarks", null, values);
- i++;
+ title = info.loadLabel(packageManager).toString();
+ } else if (category != null) {
+ intent = new Intent(Intent.ACTION_MAIN, null);
+ intent.addCategory(category);
+ title = "";
+ } else {
+ Log.w(TAG, "Unable to add bookmark for shortcut " + shortcutStr
+ + ": missing package/class or category attributes");
+ continue;
}
+
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ values.put(Settings.Bookmarks.INTENT, intent.toUri(0));
+ values.put(Settings.Bookmarks.TITLE, title);
+ values.put(Settings.Bookmarks.SHORTCUT, shortcutValue);
+ db.delete("bookmarks", "shortcut = ?",
+ new String[] { Integer.toString(shortcutValue) });
+ db.insert("bookmarks", null, values);
}
} catch (XmlPullParserException e) {
Log.w(TAG, "Got execption parsing bookmarks.", e);
} catch (IOException e) {
Log.w(TAG, "Got execption parsing bookmarks.", e);
}
-
- return i;
- }
-
- /**
- * Loads the default set of bookmark packages.
- *
- * @param db The database to write the values into
- */
- private void loadBookmarks(SQLiteDatabase db) {
- loadBookmarks(db, 0);
}
/**
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index e937587..ec08e6c 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -46,26 +46,6 @@
</intent-filter>
</receiver>
- <!-- should you need to launch the screensaver, this is a good way to do it -->
- <activity android:name=".DreamsDockLauncher"
- android:theme="@android:style/Theme.Dialog"
- android:label="@string/dreams_dock_launcher">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
-
- <!-- launch screensaver on (desk) dock event -->
- <receiver android:name=".DreamsDockLauncher$DockEventReceiver"
- android:exported="true"
- >
- <intent-filter>
- <action android:name="android.intent.action.DOCK_EVENT" />
- </intent-filter>
- </receiver>
-
-
<activity android:name=".usb.UsbStorageActivity"
android:label="@*android:string/usb_storage_activity_title"
android:excludeFromRecents="true">
diff --git a/packages/SystemUI/res/layout/global_screenshot.xml b/packages/SystemUI/res/layout/global_screenshot.xml
index d416af9..8b337ea 100644
--- a/packages/SystemUI/res/layout/global_screenshot.xml
+++ b/packages/SystemUI/res/layout/global_screenshot.xml
@@ -19,23 +19,18 @@
<ImageView android:id="@+id/global_screenshot_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="#FF000000"
+ android:src="@android:color/black"
android:visibility="gone" />
- <FrameLayout
- android:id="@+id/global_screenshot_container"
+ <ImageView android:id="@+id/global_screenshot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/screenshot_panel"
- android:visibility="gone">
- <ImageView android:id="@+id/global_screenshot"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:adjustViewBounds="true" />
- </FrameLayout>
+ android:visibility="gone"
+ android:adjustViewBounds="true" />
<ImageView android:id="@+id/global_screenshot_flash"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="#FFFFFFFF"
+ android:src="@android:color/white"
android:visibility="gone" />
</FrameLayout>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index df46d2609..d313517 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -106,7 +106,7 @@
<string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Signal WiMAX : faible"</string>
<string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Signal WiMAX : moyen"</string>
<string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Signal WiMAX : bon"</string>
- <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Signal WiMAX excellent"</string>
+ <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Signal WiMAX : excellent"</string>
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3G+"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 6e94cc5..17330b1 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -131,7 +131,7 @@
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" удалено из списка."</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Передача данных по каналам 2G и 3G отключена"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Передача данных по каналу 4G отключена"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Мобильный Интернет отключен"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Моб. Интернет отключен"</string>
<string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"Передача данных отключена"</string>
<string name="data_usage_disabled_dialog" msgid="3853117269051806280">"Достигнут лимит трафика."\n\n"При восстановлении подключения оператор может взимать плату за передачу данных."</string>
<string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"Восстановить подключение"</string>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index fc81f8e..2c1473b 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -362,7 +362,4 @@
<!-- Content description of the clear button in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_clear_all">Clear all notifications.</string>
-
- <!-- Description of the desk dock action that invokes the Android Dreams screen saver feature -->
- <string name="dreams_dock_launcher">Activate screen saver</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java b/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java
deleted file mode 100644
index 1db2a7f..0000000
--- a/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.android.systemui;
-
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.util.Slog;
-
-public class DreamsDockLauncher extends Activity {
- private static final String TAG = "DreamsDockLauncher";
-
- // Launch the screen saver if started as an activity.
- @Override
- protected void onCreate (Bundle icicle) {
- super.onCreate(icicle);
- launchDream(this);
- finish();
- }
-
- private static void launchDream(Context context) {
- try {
- String component = Settings.Secure.getString(
- context.getContentResolver(), Settings.Secure.SCREENSAVER_COMPONENT);
- if (component == null) {
- component = context.getResources().getString(
- com.android.internal.R.string.config_defaultDreamComponent);
- }
- if (component != null) {
- // dismiss the notification shade, recents, etc.
- context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
-
- ComponentName cn = ComponentName.unflattenFromString(component);
- Intent zzz = new Intent(Intent.ACTION_MAIN)
- .setComponent(cn)
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | Intent.FLAG_ACTIVITY_NO_USER_ACTION
- | Intent.FLAG_FROM_BACKGROUND
- | Intent.FLAG_ACTIVITY_NO_HISTORY
- );
- Slog.v(TAG, "Starting screen saver on dock event: " + component);
- context.startActivity(zzz);
- } else {
- Slog.e(TAG, "Couldn't start screen saver: none selected");
- }
- } catch (android.content.ActivityNotFoundException exc) {
- // no screensaver? give up
- Slog.e(TAG, "Couldn't start screen saver: none installed");
- }
- }
-
- // Trap low-level dock events and launch the screensaver.
- public static class DockEventReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- final boolean activateOnDock = 0 != Settings.Secure.getInt(
- context.getContentResolver(),
- Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, 1);
-
- if (!activateOnDock) return;
-
- if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
- Bundle extras = intent.getExtras();
- int state = extras
- .getInt(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED);
- if (state == Intent.EXTRA_DOCK_STATE_DESK
- || state == Intent.EXTRA_DOCK_STATE_LE_DESK
- || state == Intent.EXTRA_DOCK_STATE_HE_DESK) {
- launchDream(context);
- }
- }
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index ad37603..2dcd80d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -38,11 +38,9 @@
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Process;
-import android.os.ServiceManager;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
import android.view.Display;
-import android.view.IWindowManager;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.Surface;
@@ -50,9 +48,7 @@
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.Interpolator;
-import android.widget.FrameLayout;
import android.widget.ImageView;
-
import com.android.systemui.R;
import java.io.File;
@@ -77,7 +73,6 @@
*/
class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Void,
SaveImageInBackgroundData> {
- private static final String TAG = "SaveImageInBackgroundTask";
private static final String SCREENSHOTS_DIR_NAME = "Screenshots";
private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
private static final String SCREENSHOT_FILE_PATH_TEMPLATE = "%s/%s/%s";
@@ -85,11 +80,8 @@
private int mNotificationId;
private NotificationManager mNotificationManager;
private Notification.Builder mNotificationBuilder;
- private Intent mLaunchIntent;
- private String mImageDir;
private String mImageFileName;
private String mImageFilePath;
- private String mImageDate;
private long mImageTime;
// WORKAROUND: We want the same notification across screenshots that we update so that we don't
@@ -105,11 +97,11 @@
// Prepare all the output metadata
mImageTime = System.currentTimeMillis();
- mImageDate = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date(mImageTime));
- mImageDir = Environment.getExternalStoragePublicDirectory(
+ String imageDate = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date(mImageTime));
+ String imageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES).getAbsolutePath();
- mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, mImageDate);
- mImageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, mImageDir,
+ mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, imageDate);
+ mImageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, imageDir,
SCREENSHOTS_DIR_NAME, mImageFileName);
// Create the large notification icon
@@ -190,7 +182,7 @@
}
return params[0];
- };
+ }
@Override
protected void onPostExecute(SaveImageInBackgroundData params) {
@@ -202,14 +194,14 @@
Resources r = params.context.getResources();
// Create the intent to show the screenshot in gallery
- mLaunchIntent = new Intent(Intent.ACTION_VIEW);
- mLaunchIntent.setDataAndType(params.imageUri, "image/png");
- mLaunchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ Intent launchIntent = new Intent(Intent.ACTION_VIEW);
+ launchIntent.setDataAndType(params.imageUri, "image/png");
+ launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mNotificationBuilder
.setContentTitle(r.getString(R.string.screenshot_saved_title))
.setContentText(r.getString(R.string.screenshot_saved_text))
- .setContentIntent(PendingIntent.getActivity(params.context, 0, mLaunchIntent, 0))
+ .setContentIntent(PendingIntent.getActivity(params.context, 0, launchIntent, 0))
.setWhen(System.currentTimeMillis())
.setAutoCancel(true);
@@ -218,7 +210,7 @@
mNotificationManager.notify(mNotificationId, n);
}
params.finisher.run();
- };
+ }
}
/**
@@ -228,7 +220,6 @@
* type of gallery?
*/
class GlobalScreenshot {
- private static final String TAG = "GlobalScreenshot";
private static final int SCREENSHOT_NOTIFICATION_ID = 789;
private static final int SCREENSHOT_FLASH_TO_PEAK_DURATION = 130;
private static final int SCREENSHOT_DROP_IN_DURATION = 430;
@@ -244,8 +235,6 @@
private static final float SCREENSHOT_DROP_OUT_MIN_SCALE_OFFSET = 0f;
private Context mContext;
- private LayoutInflater mLayoutInflater;
- private IWindowManager mIWindowManager;
private WindowManager mWindowManager;
private WindowManager.LayoutParams mWindowLayoutParams;
private NotificationManager mNotificationManager;
@@ -256,7 +245,6 @@
private Bitmap mScreenBitmap;
private View mScreenshotLayout;
private ImageView mBackgroundView;
- private FrameLayout mScreenshotContainerView;
private ImageView mScreenshotView;
private ImageView mScreenshotFlash;
@@ -273,14 +261,13 @@
public GlobalScreenshot(Context context) {
Resources r = context.getResources();
mContext = context;
- mLayoutInflater = (LayoutInflater)
+ LayoutInflater layoutInflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Inflate the screenshot layout
mDisplayMatrix = new Matrix();
- mScreenshotLayout = mLayoutInflater.inflate(R.layout.global_screenshot, null);
+ mScreenshotLayout = layoutInflater.inflate(R.layout.global_screenshot, null);
mBackgroundView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_background);
- mScreenshotContainerView = (FrameLayout) mScreenshotLayout.findViewById(R.id.global_screenshot_container);
mScreenshotView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot);
mScreenshotFlash = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_flash);
mScreenshotLayout.setFocusable(true);
@@ -293,8 +280,6 @@
});
// Setup the window that we are going to use
- mIWindowManager = IWindowManager.Stub.asInterface(
- ServiceManager.getService(Context.WINDOW_SERVICE));
mWindowLayoutParams = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 0, 0,
WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
@@ -428,8 +413,8 @@
mScreenshotLayout.post(new Runnable() {
@Override
public void run() {
- mScreenshotContainerView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- mScreenshotContainerView.buildLayer();
+ mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ mScreenshotView.buildLayer();
mScreenshotAnimation.start();
}
});
@@ -463,20 +448,16 @@
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
- mBackgroundView.setFastAlpha(0f);
+ mBackgroundView.setAlpha(0f);
mBackgroundView.setVisibility(View.VISIBLE);
- mBackgroundView.fastInvalidate();
- mScreenshotContainerView.setFastAlpha(0f);
- mScreenshotContainerView.setFastTranslationX(0f);
- mScreenshotContainerView.setFastTranslationY(0f);
- mScreenshotContainerView.setFastScaleX(SCREENSHOT_SCALE + mBgPaddingScale);
- mScreenshotContainerView.setFastScaleY(SCREENSHOT_SCALE + mBgPaddingScale);
- mScreenshotContainerView.setVisibility(View.VISIBLE);
- mScreenshotContainerView.fastInvalidate();
- mScreenshotFlash.setFastAlpha(0f);
+ mScreenshotView.setAlpha(0f);
+ mScreenshotView.setTranslationX(0f);
+ mScreenshotView.setTranslationY(0f);
+ mScreenshotView.setScaleX(SCREENSHOT_SCALE + mBgPaddingScale);
+ mScreenshotView.setScaleY(SCREENSHOT_SCALE + mBgPaddingScale);
+ mScreenshotView.setVisibility(View.VISIBLE);
+ mScreenshotFlash.setAlpha(0f);
mScreenshotFlash.setVisibility(View.VISIBLE);
- mScreenshotFlash.fastInvalidate();
- mScreenshotLayout.invalidate();
}
@Override
public void onAnimationEnd(android.animation.Animator animation) {
@@ -486,19 +467,15 @@
anim.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
- float t = ((Float) animation.getAnimatedValue()).floatValue();
+ float t = (Float) animation.getAnimatedValue();
float scaleT = (SCREENSHOT_SCALE + mBgPaddingScale)
- - (float) scaleInterpolator.getInterpolation(t)
+ - scaleInterpolator.getInterpolation(t)
* (SCREENSHOT_SCALE - SCREENSHOT_DROP_IN_MIN_SCALE);
- mBackgroundView.setFastAlpha(scaleInterpolator.getInterpolation(t) * BACKGROUND_ALPHA);
- mBackgroundView.fastInvalidate();
- mScreenshotContainerView.setFastAlpha(t);
- mScreenshotContainerView.setFastScaleX(scaleT);
- mScreenshotContainerView.setFastScaleY(scaleT);
- mScreenshotContainerView.fastInvalidate();
- mScreenshotFlash.setFastAlpha(flashAlphaInterpolator.getInterpolation(t));
- mScreenshotFlash.fastInvalidate();
- mScreenshotLayout.invalidate();
+ mBackgroundView.setAlpha(scaleInterpolator.getInterpolation(t) * BACKGROUND_ALPHA);
+ mScreenshotView.setAlpha(t);
+ mScreenshotView.setScaleX(scaleT);
+ mScreenshotView.setScaleY(scaleT);
+ mScreenshotFlash.setAlpha(flashAlphaInterpolator.getInterpolation(t));
}
});
return anim;
@@ -511,8 +488,8 @@
@Override
public void onAnimationEnd(Animator animation) {
mBackgroundView.setVisibility(View.GONE);
- mScreenshotContainerView.setVisibility(View.GONE);
- mScreenshotContainerView.setLayerType(View.LAYER_TYPE_NONE, null);
+ mScreenshotView.setVisibility(View.GONE);
+ mScreenshotView.setLayerType(View.LAYER_TYPE_NONE, null);
}
});
@@ -522,17 +499,13 @@
anim.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
- float t = ((Float) animation.getAnimatedValue()).floatValue();
+ float t = (Float) animation.getAnimatedValue();
float scaleT = (SCREENSHOT_DROP_IN_MIN_SCALE + mBgPaddingScale)
- - (float) t * (SCREENSHOT_DROP_IN_MIN_SCALE
- - SCREENSHOT_FAST_DROP_OUT_MIN_SCALE);
- mBackgroundView.setFastAlpha((1f - t) * BACKGROUND_ALPHA);
- mBackgroundView.fastInvalidate();
- mScreenshotContainerView.setFastAlpha(1f - t);
- mScreenshotContainerView.setFastScaleX(scaleT);
- mScreenshotContainerView.setFastScaleY(scaleT);
- mScreenshotContainerView.fastInvalidate();
- mScreenshotLayout.invalidate();
+ - t * (SCREENSHOT_DROP_IN_MIN_SCALE - SCREENSHOT_FAST_DROP_OUT_MIN_SCALE);
+ mBackgroundView.setAlpha((1f - t) * BACKGROUND_ALPHA);
+ mScreenshotView.setAlpha(1f - t);
+ mScreenshotView.setScaleX(scaleT);
+ mScreenshotView.setScaleY(scaleT);
}
});
} else {
@@ -563,19 +536,16 @@
anim.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
- float t = ((Float) animation.getAnimatedValue()).floatValue();
+ float t = (Float) animation.getAnimatedValue();
float scaleT = (SCREENSHOT_DROP_IN_MIN_SCALE + mBgPaddingScale)
- - (float) scaleInterpolator.getInterpolation(t)
+ - scaleInterpolator.getInterpolation(t)
* (SCREENSHOT_DROP_IN_MIN_SCALE - SCREENSHOT_DROP_OUT_MIN_SCALE);
- mBackgroundView.setFastAlpha((1f - t) * BACKGROUND_ALPHA);
- mBackgroundView.fastInvalidate();
- mScreenshotContainerView.setFastAlpha(1f - scaleInterpolator.getInterpolation(t));
- mScreenshotContainerView.setFastScaleX(scaleT);
- mScreenshotContainerView.setFastScaleY(scaleT);
- mScreenshotContainerView.setFastTranslationX(t * finalPos.x);
- mScreenshotContainerView.setFastTranslationY(t * finalPos.y);
- mScreenshotContainerView.fastInvalidate();
- mScreenshotLayout.invalidate();
+ mBackgroundView.setAlpha((1f - t) * BACKGROUND_ALPHA);
+ mScreenshotView.setAlpha(1f - scaleInterpolator.getInterpolation(t));
+ mScreenshotView.setScaleX(scaleT);
+ mScreenshotView.setScaleY(scaleT);
+ mScreenshotView.setTranslationX(t * finalPos.x);
+ mScreenshotView.setTranslationY(t * finalPos.y);
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java
index 7fbf734..2d951c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java
@@ -49,6 +49,10 @@
public void refresh() {
int mode = mAM.getFrontActivityScreenCompatMode();
+ if (mode == ActivityManager.COMPAT_MODE_UNKNOWN) {
+ // If in an unknown state, don't change.
+ return;
+ }
final boolean vis = (mode != ActivityManager.COMPAT_MODE_NEVER
&& mode != ActivityManager.COMPAT_MODE_ALWAYS);
if (DEBUG) Slog.d(TAG, "compat mode is " + mode + "; icon will " + (vis ? "show" : "hide"));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 55a5b0a..135a04c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -898,7 +898,7 @@
combinedSignalIconId = mDataSignalIconId; // set by updateDataIcon()
mContentDescriptionCombinedSignal = mContentDescriptionDataType;
}
-
+
if (mWifiConnected) {
if (mWifiSsid == null) {
label = context.getString(R.string.status_bar_settings_signal_meter_wifi_nossid);
@@ -932,19 +932,23 @@
mContentDescriptionCombinedSignal = mContext.getString(
R.string.accessibility_bluetooth_tether);
}
-
+
if (mAirplaneMode &&
(mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly()))) {
// Only display the flight-mode icon if not in "emergency calls only" mode.
- label = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
- mContentDescriptionCombinedSignal = mContentDescriptionPhoneSignal
- = mContext.getString(R.string.accessibility_airplane_mode);
-
+
// look again; your radios are now airplanes
+ mContentDescriptionPhoneSignal = mContext.getString(
+ R.string.accessibility_airplane_mode);
mPhoneSignalIconId = mDataSignalIconId = R.drawable.stat_sys_signal_flightmode;
mDataTypeIconId = 0;
- combinedSignalIconId = mDataSignalIconId;
+ // combined values from connected wifi take precedence over airplane mode
+ if (!mWifiConnected) {
+ label = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
+ mContentDescriptionCombinedSignal = mContentDescriptionPhoneSignal;
+ combinedSignalIconId = mDataSignalIconId;
+ }
}
else if (!mDataConnected && !mWifiConnected && !mBluetoothTethered && !mWimaxConnected) {
// pretty much totally disconnected
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 01406bc..757ce0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -534,6 +534,7 @@
mCompatModeButton = (CompatModeButton) sb.findViewById(R.id.compatModeButton);
mCompatModeButton.setOnClickListener(mOnClickListener);
+ mCompatModeButton.setVisibility(View.GONE);
// for redirecting errant bar taps to the IME
mFakeSpaceBar = sb.findViewById(R.id.fake_space_bar);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index fd9e095..f6bf213 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -40,7 +40,6 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.BatteryManager;
-import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -69,8 +68,10 @@
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseArray;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
+import android.view.IApplicationToken;
import android.view.IWindowManager;
import android.view.InputChannel;
import android.view.InputDevice;
@@ -163,9 +164,6 @@
static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true;
static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
- // Should screen savers use their own timeout, or the SCREEN_OFF_TIMEOUT?
- static final boolean SEPARATE_TIMEOUT_FOR_SCREEN_SAVER = false;
-
static final int LONG_PRESS_POWER_NOTHING = 0;
static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
static final int LONG_PRESS_POWER_SHUT_OFF = 2;
@@ -230,7 +228,30 @@
// Useful scan codes.
private static final int SW_LID = 0x00;
private static final int BTN_MOUSE = 0x110;
-
+
+ /* Table of Application Launch keys. Maps from key codes to intent categories.
+ *
+ * These are special keys that are used to launch particular kinds of applications,
+ * such as a web browser. HID defines nearly a hundred of them in the Consumer (0x0C)
+ * usage page. We don't support quite that many yet...
+ */
+ static SparseArray<String> sApplicationLaunchKeyCategories;
+ static {
+ sApplicationLaunchKeyCategories = new SparseArray<String>();
+ sApplicationLaunchKeyCategories.append(
+ KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER);
+ sApplicationLaunchKeyCategories.append(
+ KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL);
+ sApplicationLaunchKeyCategories.append(
+ KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS);
+ sApplicationLaunchKeyCategories.append(
+ KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR);
+ sApplicationLaunchKeyCategories.append(
+ KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC);
+ sApplicationLaunchKeyCategories.append(
+ KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
+ }
+
/**
* Lock protecting internal state. Must not call out into window
* manager with lock held. (This lock will be acquired in places
@@ -319,6 +340,7 @@
// The last window we were told about in focusChanged.
WindowState mFocusedWindow;
+ IApplicationToken mFocusedApp;
private final InputHandler mPointerLocationInputHandler = new BaseInputHandler() {
@Override
@@ -398,12 +420,6 @@
int mLockScreenTimeout;
boolean mLockScreenTimerActive;
- // visual screen saver support
- int mScreenSaverTimeout = 0;
- boolean mScreenSaverEnabledByUser = false;
- boolean mScreenSaverMayRun = true; // false if a wakelock is held
- boolean mPluggedIn;
-
// Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.)
int mEndcallBehavior;
@@ -466,12 +482,6 @@
Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
resolver.registerContentObserver(Settings.System.getUriFor(
"fancy_rotation_anim"), false, this);
- resolver.registerContentObserver(Settings.Secure.getUriFor(
- Settings.Secure.SCREENSAVER_ENABLED), false, this);
- if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) {
- resolver.registerContentObserver(Settings.Secure.getUriFor(
- "screensaver_timeout"), false, this);
- } // otherwise SCREEN_OFF_TIMEOUT will do nicely
updateSettings();
}
@@ -779,14 +789,6 @@
Intent.EXTRA_DOCK_STATE_UNDOCKED);
}
- // watch the plug to know whether to trigger the screen saver
- filter = new IntentFilter();
- filter.addAction(Intent.ACTION_BATTERY_CHANGED);
- intent = context.registerReceiver(mPowerReceiver, filter);
- if (intent != null) {
- mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
- }
-
mVibrator = new Vibrator();
mLongPressVibePattern = getLongIntArray(mContext.getResources(),
com.android.internal.R.array.config_longPressVibePattern);
@@ -935,23 +937,6 @@
mHasSoftInput = hasSoftInput;
updateRotation = true;
}
-
- mScreenSaverEnabledByUser = 0 != Settings.Secure.getInt(resolver,
- Settings.Secure.SCREENSAVER_ENABLED, 1);
-
- if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) {
- mScreenSaverTimeout = Settings.Secure.getInt(resolver,
- "screensaver_timeout", 0);
- } else {
- mScreenSaverTimeout = Settings.System.getInt(resolver,
- Settings.System.SCREEN_OFF_TIMEOUT, 0);
- if (mScreenSaverTimeout > 0) {
- // We actually want to activate the screensaver just before the
- // power manager's screen timeout
- mScreenSaverTimeout -= 5000;
- }
- }
- updateScreenSaverTimeoutLocked();
}
if (updateRotation) {
updateRotation(true);
@@ -1649,6 +1634,23 @@
}
}
+ // Handle application launch keys.
+ if (down && repeatCount == 0) {
+ String category = sApplicationLaunchKeyCategories.get(keyCode);
+ if (category != null) {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(category);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ mContext.startActivity(intent);
+ } catch (ActivityNotFoundException ex) {
+ Slog.w(TAG, "Dropping application launch key because "
+ + "the activity to which it is registered was not found: "
+ + "keyCode=" + keyCode + ", category=" + category, ex);
+ }
+ }
+ }
+
return 0;
}
@@ -2986,15 +2988,6 @@
}
};
- BroadcastReceiver mPowerReceiver = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
- mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
- if (localLOGV) Log.v(TAG, "BATTERY_CHANGED: " + intent + " plugged=" + mPluggedIn);
- }
- }
- };
-
/** {@inheritDoc} */
public void screenTurnedOff(int why) {
EventLog.writeEvent(70000, 0);
@@ -3006,7 +2999,6 @@
synchronized (mLock) {
updateOrientationListenerLp();
updateLockScreenTimeout();
- updateScreenSaverTimeoutLocked();
}
}
@@ -3053,7 +3045,6 @@
mScreenOnEarly = true;
updateOrientationListenerLp();
updateLockScreenTimeout();
- updateScreenSaverTimeoutLocked();
}
}
@@ -3448,75 +3439,6 @@
mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
}
}
-
- synchronized (mLock) {
- // Only posts messages; holds no additional locks.
- updateScreenSaverTimeoutLocked();
- }
- }
-
- Runnable mScreenSaverActivator = new Runnable() {
- public void run() {
- if (!(mScreenSaverMayRun && mScreenOnEarly)) {
- Log.w(TAG, "mScreenSaverActivator ran, but the screensaver should not be showing. Who's driving this thing?");
- return;
- }
- if (!mPluggedIn) {
- if (localLOGV) Log.v(TAG, "mScreenSaverActivator: not running screen saver when not plugged in");
- return;
- }
-
- if (localLOGV) Log.v(TAG, "mScreenSaverActivator entering dreamland");
-
- try {
- String component = Settings.Secure.getString(
- mContext.getContentResolver(), Settings.Secure.SCREENSAVER_COMPONENT);
- if (component == null) {
- component = mContext.getResources().getString(R.string.config_defaultDreamComponent);
- }
- if (component != null) {
- // dismiss the notification shade, recents, etc.
- mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
-
- ComponentName cn = ComponentName.unflattenFromString(component);
- Intent intent = new Intent(Intent.ACTION_MAIN)
- .setComponent(cn)
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | Intent.FLAG_ACTIVITY_NO_USER_ACTION
- | Intent.FLAG_FROM_BACKGROUND
- | Intent.FLAG_ACTIVITY_NO_HISTORY
- );
- mContext.startActivity(intent);
- } else {
- Log.e(TAG, "Couldn't start screen saver: none selected");
- }
- } catch (android.content.ActivityNotFoundException exc) {
- // no screensaver? give up
- Log.e(TAG, "Couldn't start screen saver: none installed");
- }
- }
- };
-
- // Must call while holding mLock
- private void updateScreenSaverTimeoutLocked() {
- if (mScreenSaverActivator == null) return;
-
- mHandler.removeCallbacks(mScreenSaverActivator);
- if (mScreenSaverEnabledByUser && mScreenSaverMayRun && mScreenOnEarly && mScreenSaverTimeout > 0) {
- if (localLOGV)
- Log.v(TAG, "scheduling screensaver for " + mScreenSaverTimeout + "ms from now");
- mHandler.postDelayed(mScreenSaverActivator, mScreenSaverTimeout);
- } else {
- if (localLOGV) {
- if (!mScreenSaverEnabledByUser || mScreenSaverTimeout == 0)
- Log.v(TAG, "screen saver disabled by user");
- else if (!mScreenOnEarly)
- Log.v(TAG, "screen saver disabled while screen off");
- else
- Log.v(TAG, "screen saver disabled by wakelock");
- }
- }
}
Runnable mScreenLockTimeout = new Runnable() {
@@ -3722,11 +3644,6 @@
}
public void screenOnStartedLw() {
- // The window manager has just grabbed a wake lock. This is our cue to disable the screen
- // saver.
- synchronized (mLock) {
- mScreenSaverMayRun = false;
- }
}
public void screenOnStoppedLw() {
@@ -3735,13 +3652,6 @@
long curTime = SystemClock.uptimeMillis();
mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
}
-
- synchronized (mLock) {
- // even if the keyguard is up, now that all the wakelocks have been released, we
- // should re-enable the screen saver
- mScreenSaverMayRun = true;
- updateScreenSaverTimeoutLocked();
- }
}
}
@@ -3762,11 +3672,13 @@
int diff = visibility ^ mLastSystemUiFlags;
final boolean needsMenu = (mFocusedWindow.getAttrs().flags
& WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0;
- if (diff == 0 && mLastFocusNeedsMenu == needsMenu) {
+ if (diff == 0 && mLastFocusNeedsMenu == needsMenu
+ && mFocusedApp == mFocusedWindow.getAppToken()) {
return 0;
}
mLastSystemUiFlags = visibility;
mLastFocusNeedsMenu = needsMenu;
+ mFocusedApp = mFocusedWindow.getAppToken();
mHandler.post(new Runnable() {
public void run() {
if (mStatusBarService == null) {
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index 5408436..4dad209 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -50,12 +50,12 @@
# NotificationManagerService.java
# ---------------------------
# when a NotificationManager.notify is called
-2750 notification_enqueue (pkg|3),(id|1|5),(notification|3)
+2750 notification_enqueue (pkg|3),(id|1|5),(tag|3),(notification|3)
# when someone tries to cancel a notification, the notification manager sometimes
# calls this with flags too
-2751 notification_cancel (pkg|3),(id|1|5),(required_flags|1)
+2751 notification_cancel (pkg|3),(id|1|5),(tag|3),(required_flags|1),(forbidden_flags|1)
# when someone tries to cancel all of the notifications for a particular package
-2752 notification_cancel_all (pkg|3),(required_flags|1)
+2752 notification_cancel_all (pkg|3),(required_flags|1),(forbidden_flags|1)
# ---------------------------
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 7d1d976..5039294 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -707,7 +707,8 @@
// behalf of the download manager without affecting other apps.
if (!pkg.equals("com.android.providers.downloads")
|| Log.isLoggable("DownloadManager", Log.VERBOSE)) {
- EventLog.writeEvent(EventLogTags.NOTIFICATION_ENQUEUE, pkg, id, notification.toString());
+ EventLog.writeEvent(EventLogTags.NOTIFICATION_ENQUEUE, pkg, id, tag,
+ notification.toString());
}
if (pkg == null || notification == null) {
@@ -944,7 +945,8 @@
*/
private void cancelNotification(String pkg, String tag, int id, int mustHaveFlags,
int mustNotHaveFlags, boolean sendDelete) {
- EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL, pkg, id, mustHaveFlags);
+ EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL, pkg, id, tag,
+ mustHaveFlags, mustNotHaveFlags);
synchronized (mNotificationList) {
int index = indexOfNotificationLocked(pkg, tag, id);
@@ -972,7 +974,8 @@
*/
boolean cancelAllNotificationsInt(String pkg, int mustHaveFlags,
int mustNotHaveFlags, boolean doit) {
- EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL_ALL, pkg, mustHaveFlags);
+ EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL_ALL, pkg, mustHaveFlags,
+ mustNotHaveFlags);
synchronized (mNotificationList) {
final int N = mNotificationList.size();
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 6b23b33..2a0d2a0 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -1689,6 +1689,11 @@
// before showing it to the user. We want the light off
// until it is ready to be shown to the user, not it using
// whatever the last value it had.
+ if (DEBUG_SCREEN_ON) {
+ Slog.i(TAG, "Forcing brightness 0: mPowerState=0x"
+ + Integer.toHexString(mPowerState)
+ + " mSkippedScreenOn=" + mSkippedScreenOn);
+ }
mScreenBrightness.forceValueLocked(Power.BRIGHTNESS_OFF);
}
}
@@ -2038,12 +2043,14 @@
} finally {
Binder.restoreCallingIdentity(identity);
}
- mScreenBrightness.setTargetLocked(brightness, steps,
- INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);
- if (DEBUG_SCREEN_ON) {
- RuntimeException e = new RuntimeException("here");
- e.fillInStackTrace();
- Slog.i(TAG, "Setting screen brightness: " + brightness, e);
+ if (!mSkippedScreenOn) {
+ mScreenBrightness.setTargetLocked(brightness, steps,
+ INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);
+ if (DEBUG_SCREEN_ON) {
+ RuntimeException e = new RuntimeException("here");
+ e.fillInStackTrace();
+ Slog.i(TAG, "Setting screen brightness: " + brightness, e);
+ }
}
}
@@ -2086,6 +2093,11 @@
? LightsService.BRIGHTNESS_MODE_SENSOR
: LightsService.BRIGHTNESS_MODE_USER);
if ((mask & SCREEN_BRIGHT_BIT) != 0) {
+ if (DEBUG_SCREEN_ON) {
+ RuntimeException e = new RuntimeException("here");
+ e.fillInStackTrace();
+ Slog.i(TAG, "Set LCD brightness: " + value, e);
+ }
mLcdLight.setBrightness(value, brightnessMode);
}
if ((mask & BUTTON_BRIGHT_BIT) != 0) {
@@ -2137,7 +2149,7 @@
delta = (targetValue -
(nominalCurrentValue >= 0 ? nominalCurrentValue : curValue))
/ stepsToTarget;
- if (mSpew) {
+ if (mSpew || DEBUG_SCREEN_ON) {
String noticeMe = nominalCurrentValue == curValue ? "" : " ******************";
Slog.i(TAG, "setTargetLocked mask=" + mask + " curValue=" + curValue
+ " target=" + target + " targetValue=" + targetValue + " delta=" + delta
@@ -2527,8 +2539,10 @@
}
if (mAutoBrightessEnabled && mScreenBrightnessOverride < 0) {
- mScreenBrightness.setTargetLocked(lcdValue, AUTOBRIGHTNESS_ANIM_STEPS,
- INITIAL_SCREEN_BRIGHTNESS, (int)mScreenBrightness.curValue);
+ if (!mSkippedScreenOn) {
+ mScreenBrightness.setTargetLocked(lcdValue, AUTOBRIGHTNESS_ANIM_STEPS,
+ INITIAL_SCREEN_BRIGHTNESS, (int)mScreenBrightness.curValue);
+ }
}
if (mButtonBrightnessOverride < 0) {
mButtonLight.setBrightness(buttonValue);
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index d04b440..8384ebc 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -392,9 +392,16 @@
Slog.d(TAG, "FinishSpellCheckerService");
}
synchronized(mSpellCheckerMap) {
+ final ArrayList<SpellCheckerBindGroup> removeList =
+ new ArrayList<SpellCheckerBindGroup>();
for (SpellCheckerBindGroup group : mSpellCheckerBindGroups.values()) {
if (group == null) continue;
- group.removeListener(listener);
+ // Use removeList to avoid modifying mSpellCheckerBindGroups in this loop.
+ removeList.add(group);
+ }
+ final int removeSize = removeList.size();
+ for (int i = 0; i < removeSize; ++i) {
+ removeList.get(i).removeListener(listener);
}
}
}
@@ -669,6 +676,7 @@
}
}
+ // cleanLocked may remove elements from mSpellCheckerBindGroups
private void cleanLocked() {
if (DBG) {
Slog.d(TAG, "cleanLocked");
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index e6392d7..c7fbc00 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -65,7 +65,7 @@
// Enable launching of applications when entering the dock.
private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true;
- private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = false;
+ private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = true;
private static final int MSG_UPDATE_TWILIGHT = 0;
private static final int MSG_ENABLE_LOCATION_UPDATES = 1;
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 7fa404e..4925a4e 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -476,6 +476,13 @@
ParcelFileDescriptor updateWallpaperBitmapLocked(String name) {
if (name == null) name = "";
try {
+ if (!WALLPAPER_DIR.exists()) {
+ WALLPAPER_DIR.mkdir();
+ FileUtils.setPermissions(
+ WALLPAPER_DIR.getPath(),
+ FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
+ -1, -1);
+ }
ParcelFileDescriptor fd = ParcelFileDescriptor.open(WALLPAPER_FILE,
MODE_CREATE|MODE_READ_WRITE);
mName = name;
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index fd528cc..b70ed96 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -115,8 +115,8 @@
private final Set<ComponentName> mEnabledServices = new HashSet<ComponentName>();
- private final SparseArray<IAccessibilityInteractionConnection> mWindowIdToInteractionConnectionMap =
- new SparseArray<IAccessibilityInteractionConnection>();
+ private final SparseArray<AccessibilityConnectionWrapper> mWindowIdToInteractionConnectionWrapperMap =
+ new SparseArray<AccessibilityConnectionWrapper>();
private final SparseArray<IBinder> mWindowIdToWindowTokenMap = new SparseArray<IBinder>();
@@ -439,16 +439,11 @@
final IWindow addedWindowToken = windowToken;
final IAccessibilityInteractionConnection addedConnection = connection;
final int windowId = sNextWindowId++;
- addedConnection.asBinder().linkToDeath(new DeathRecipient() {
- public void binderDied() {
- synchronized (mLock) {
- addedConnection.asBinder().unlinkToDeath(this, 0);
- removeAccessibilityInteractionConnection(addedWindowToken);
- }
- }
- }, 0);
+ AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(windowId,
+ connection);
+ wrapper.linkToDeath();
mWindowIdToWindowTokenMap.put(windowId, addedWindowToken.asBinder());
- mWindowIdToInteractionConnectionMap.put(windowId, connection);
+ mWindowIdToInteractionConnectionWrapperMap.put(windowId, wrapper);
if (DEBUG) {
Slog.i(LOG_TAG, "Adding interaction connection to windowId: " + windowId);
}
@@ -462,18 +457,17 @@
for (int i = 0; i < count; i++) {
if (mWindowIdToWindowTokenMap.valueAt(i) == windowToken.asBinder()) {
final int windowId = mWindowIdToWindowTokenMap.keyAt(i);
- mWindowIdToWindowTokenMap.remove(windowId);
- mWindowIdToInteractionConnectionMap.remove(windowId);
- if (DEBUG) {
- Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId);
- }
+ AccessibilityConnectionWrapper wrapper =
+ mWindowIdToInteractionConnectionWrapperMap.get(windowId);
+ wrapper.unlinkToDeath();
+ removeAccessibilityInteractionConnectionLocked(windowId);
return;
}
}
}
}
- public IAccessibilityServiceConnection registerEventListener(IEventListener listener) {
+ public void registerEventListener(IEventListener listener) {
mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT,
FUNCTION_REGISTER_EVENT_LISTENER);
ComponentName componentName = new ComponentName("foo.bar",
@@ -501,7 +495,19 @@
accessibilityServiceInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
Service service = new Service(componentName, accessibilityServiceInfo, true);
service.onServiceConnected(componentName, listener.asBinder());
- return service;
+ }
+
+ /**
+ * Removes an AccessibilityInteractionConnection.
+ *
+ * @param windowId The id of the window to which the connection is targeted.
+ */
+ private void removeAccessibilityInteractionConnectionLocked(int windowId) {
+ mWindowIdToWindowTokenMap.remove(windowId);
+ mWindowIdToInteractionConnectionWrapperMap.remove(windowId);
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId);
+ }
}
/**
@@ -594,6 +600,13 @@
*/
private void notifyEventListenerLocked(Service service, int eventType) {
IEventListener listener = service.mServiceInterface;
+
+ // If the service died/was disabled while the message for dispatching
+ // the accessibility event was propagating the listener may be null.
+ if (listener == null) {
+ return;
+ }
+
AccessibilityEvent event = service.mPendingEvents.get(eventType);
// Check for null here because there is a concurrent scenario in which this
@@ -618,7 +631,7 @@
service.mPendingEvents.remove(eventType);
try {
if (mSecurityPolicy.canRetrieveWindowContent(service)) {
- event.setConnection(service);
+ event.setConnectionId(service.mId);
} else {
event.setSource(null);
}
@@ -666,6 +679,7 @@
mComponentNameToServiceMap.remove(service.mComponentName);
mHandler.removeMessages(service.mId);
service.unlinkToOwnDeath();
+ service.dispose();
updateInputFilterLocked();
return removed;
}
@@ -895,6 +909,33 @@
sendStateToClientsLocked();
}
+ private class AccessibilityConnectionWrapper implements DeathRecipient {
+ private final int mWindowId;
+ private final IAccessibilityInteractionConnection mConnection;
+
+ public AccessibilityConnectionWrapper(int windowId,
+ IAccessibilityInteractionConnection connection) {
+ mWindowId = windowId;
+ mConnection = connection;
+ }
+
+ public void linkToDeath() throws RemoteException {
+ mConnection.asBinder().linkToDeath(this, 0);
+ }
+
+ public void unlinkToDeath() {
+ mConnection.asBinder().unlinkToDeath(this, 0);
+ }
+
+ @Override
+ public void binderDied() {
+ unlinkToDeath();
+ synchronized (mLock) {
+ removeAccessibilityInteractionConnectionLocked(mWindowId);
+ }
+ }
+ }
+
/**
* This class represents an accessibility service. It stores all per service
* data required for the service management, provides API for starting/stopping the
@@ -997,7 +1038,6 @@
if (!mIsAutomation) {
mContext.unbindService(this);
}
- mService = null;
return true;
}
return false;
@@ -1021,7 +1061,7 @@
mService = service;
mServiceInterface = IEventListener.Stub.asInterface(service);
try {
- mServiceInterface.setConnection(this);
+ mServiceInterface.setConnection(this, mId);
synchronized (mLock) {
tryAddServiceLocked(this);
}
@@ -1123,14 +1163,16 @@
if (!permissionGranted) {
return 0;
} else {
- connection = mWindowIdToInteractionConnectionMap.get(accessibilityWindowId);
- if (connection == null) {
+ AccessibilityConnectionWrapper wrapper =
+ mWindowIdToInteractionConnectionWrapperMap.get(accessibilityWindowId);
+ if (wrapper == null) {
if (DEBUG) {
Slog.e(LOG_TAG, "No interaction connection to window: "
+ accessibilityWindowId);
}
return 0;
}
+ connection = wrapper.mConnection;
}
}
final int interrogatingPid = Binder.getCallingPid();
@@ -1159,14 +1201,16 @@
if (!permissionGranted) {
return false;
} else {
- connection = mWindowIdToInteractionConnectionMap.get(accessibilityWindowId);
- if (connection == null) {
+ AccessibilityConnectionWrapper wrapper =
+ mWindowIdToInteractionConnectionWrapperMap.get(accessibilityWindowId);
+ if (wrapper == null) {
if (DEBUG) {
Slog.e(LOG_TAG, "No interaction connection to window: "
+ accessibilityWindowId);
}
return false;
}
+ connection = wrapper.mConnection;
}
}
final int interrogatingPid = Binder.getCallingPid();
@@ -1197,9 +1241,21 @@
mService.unlinkToDeath(this, 0);
}
+ public void dispose() {
+ try {
+ // Clear the proxy in the other process so this
+ // IAccessibilityServiceConnection can be garbage collected.
+ mServiceInterface.setConnection(null, mId);
+ } catch (RemoteException re) {
+ /* ignore */
+ }
+ mService = null;
+ mServiceInterface = null;
+ }
+
public void binderDied() {
synchronized (mLock) {
- mService.unlinkToDeath(this, 0);
+ unlinkToOwnDeath();
tryRemoveServiceLocked(this);
// We no longer have an automation service, so restore
// the state based on values in the settings database.
@@ -1214,7 +1270,9 @@
if (DEBUG) {
Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
}
- return mWindowIdToInteractionConnectionMap.get(windowId);
+ AccessibilityConnectionWrapper wrapper =
+ mWindowIdToInteractionConnectionWrapperMap.get(windowId);
+ return (wrapper != null) ? wrapper.mConnection : null;
}
private float getCompatibilityScale(int windowId) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 8023477..b36ba3a 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -129,7 +129,6 @@
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -1222,6 +1221,23 @@
@Override public void run() {
StringBuilder dropBuilder = new StringBuilder(1024);
StringBuilder logBuilder = new StringBuilder(1024);
+ StringWriter oomSw = new StringWriter();
+ PrintWriter oomPw = new PrintWriter(oomSw);
+ StringWriter catSw = new StringWriter();
+ PrintWriter catPw = new PrintWriter(catSw);
+ String[] emptyArgs = new String[] { };
+ StringBuilder tag = new StringBuilder(128);
+ StringBuilder stack = new StringBuilder(128);
+ tag.append("Low on memory -- ");
+ dumpApplicationMemoryUsage(null, oomPw, " ", emptyArgs, true, catPw,
+ tag, stack);
+ dropBuilder.append(stack);
+ dropBuilder.append('\n');
+ dropBuilder.append('\n');
+ String oomString = oomSw.toString();
+ dropBuilder.append(oomString);
+ dropBuilder.append('\n');
+ logBuilder.append(oomString);
try {
java.lang.Process proc = Runtime.getRuntime().exec(new String[] {
"procrank", });
@@ -1244,27 +1260,15 @@
converter.close();
} catch (IOException e) {
}
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- StringWriter catSw = new StringWriter();
- PrintWriter catPw = new PrintWriter(catSw);
- String[] emptyArgs = new String[] { };
- StringBuilder tag = new StringBuilder(128);
synchronized (ActivityManagerService.this) {
+ catPw.println();
dumpProcessesLocked(null, catPw, emptyArgs, 0, false, null);
catPw.println();
dumpServicesLocked(null, catPw, emptyArgs, 0, false, false, null);
catPw.println();
dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null);
- catPw.println();
}
- tag.append("Low on memory -- ");
- dumpApplicationMemoryUsage(null, pw, " ", emptyArgs, true, catPw, tag);
- String memUsage = sw.toString();
- dropBuilder.append('\n');
- dropBuilder.append(memUsage);
dropBuilder.append(catSw.toString());
- logBuilder.append(memUsage);
addErrorToDropBox("lowmem", null, "system_server", null,
null, tag.toString(), dropBuilder.toString(), null, null);
Slog.i(TAG, logBuilder.toString());
@@ -1420,7 +1424,7 @@
}
mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args,
- false, null, null);
+ false, null, null, null);
}
}
@@ -2716,6 +2720,10 @@
}
if (!r.finishing) {
Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
+ EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
+ System.identityHashCode(r),
+ r.task.taskId, r.shortComponentName,
+ "proc died without state saved");
}
r.makeFinishing();
mMainStack.mHistory.remove(i);
@@ -9416,7 +9424,7 @@
} else if (r.setAdj >= ProcessList.SERVICE_ADJ) {
oomAdj = buildOomTag("svc ", null, r.setAdj, ProcessList.SERVICE_ADJ);
} else if (r.setAdj >= ProcessList.BACKUP_APP_ADJ) {
- oomAdj = buildOomTag("bckup", null, r.setAdj, ProcessList.BACKUP_APP_ADJ);
+ oomAdj = buildOomTag("bkup ", null, r.setAdj, ProcessList.BACKUP_APP_ADJ);
} else if (r.setAdj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
oomAdj = buildOomTag("hvy ", null, r.setAdj, ProcessList.HEAVY_WEIGHT_APP_ADJ);
} else if (r.setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
@@ -9645,7 +9653,8 @@
1*1024*1024, 2*1024*1024, 5*1024*1024, 10*1024*1024, 20*1024*1024
};
- static final void appendMemBucket(StringBuilder out, long memKB, String label) {
+ static final void appendMemBucket(StringBuilder out, long memKB, String label,
+ boolean stackLike) {
int start = label.lastIndexOf('.');
if (start >= 0) start++;
else start = 0;
@@ -9654,13 +9663,13 @@
if (DUMP_MEM_BUCKETS[i] >= memKB) {
long bucket = DUMP_MEM_BUCKETS[i]/1024;
out.append(bucket);
- out.append("MB ");
+ out.append(stackLike ? "MB." : "MB ");
out.append(label, start, end);
return;
}
}
out.append(memKB/1024);
- out.append("MB ");
+ out.append(stackLike ? "MB." : "MB ");
out.append(label, start, end);
}
@@ -9679,7 +9688,7 @@
final void dumpApplicationMemoryUsage(FileDescriptor fd,
PrintWriter pw, String prefix, String[] args, boolean brief,
- PrintWriter categoryPw, StringBuilder outTag) {
+ PrintWriter categoryPw, StringBuilder outTag, StringBuilder outStack) {
boolean dumpAll = false;
boolean oomOnly = false;
@@ -9816,8 +9825,14 @@
}
}
- if (outTag != null) {
- appendMemBucket(outTag, totalPss, "total");
+ if (outTag != null || outStack != null) {
+ if (outTag != null) {
+ appendMemBucket(outTag, totalPss, "total", false);
+ }
+ if (outStack != null) {
+ appendMemBucket(outStack, totalPss, "total", true);
+ }
+ boolean firstLine = true;
for (int i=0; i<oomMems.size(); i++) {
MemItem miCat = oomMems.get(i);
if (miCat.subitems == null || miCat.subitems.size() < 1) {
@@ -9826,13 +9841,47 @@
if (miCat.id < ProcessList.SERVICE_ADJ
|| miCat.id == ProcessList.HOME_APP_ADJ
|| miCat.id == ProcessList.PREVIOUS_APP_ADJ) {
- outTag.append(" / ");
+ if (outTag != null && miCat.id <= ProcessList.FOREGROUND_APP_ADJ) {
+ outTag.append(" / ");
+ }
+ if (outStack != null) {
+ if (miCat.id >= ProcessList.FOREGROUND_APP_ADJ) {
+ if (firstLine) {
+ outStack.append(":");
+ firstLine = false;
+ }
+ outStack.append("\n\t at ");
+ } else {
+ outStack.append("$");
+ }
+ }
for (int j=0; j<miCat.subitems.size(); j++) {
MemItem mi = miCat.subitems.get(j);
if (j > 0) {
- outTag.append(" ");
+ if (outTag != null) {
+ outTag.append(" ");
+ }
+ if (outStack != null) {
+ outStack.append("$");
+ }
}
- appendMemBucket(outTag, mi.pss, mi.shortLabel);
+ if (outTag != null && miCat.id <= ProcessList.FOREGROUND_APP_ADJ) {
+ appendMemBucket(outTag, mi.pss, mi.shortLabel, false);
+ }
+ if (outStack != null) {
+ appendMemBucket(outStack, mi.pss, mi.shortLabel, true);
+ }
+ }
+ if (outStack != null && miCat.id >= ProcessList.FOREGROUND_APP_ADJ) {
+ outStack.append("(");
+ for (int k=0; k<DUMP_MEM_OOM_ADJ.length; k++) {
+ if (DUMP_MEM_OOM_ADJ[k] == miCat.id) {
+ outStack.append(DUMP_MEM_OOM_LABEL[k]);
+ outStack.append(":");
+ outStack.append(DUMP_MEM_OOM_ADJ[k]);
+ }
+ }
+ outStack.append(")");
}
}
}
@@ -13551,6 +13600,7 @@
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
app.adjType = "stopping";
}
+ app.hidden = false;
app.foregroundActivities = true;
}
}
@@ -14199,7 +14249,7 @@
if (app.curAdj != app.setAdj) {
if (Process.setOomAdj(app.pid, app.curAdj)) {
- if (true || DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
TAG, "Set " + app.pid + " " + app.processName +
" adj " + app.curAdj + ": " + app.adjType);
app.setAdj = app.curAdj;
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 769e6cf..f5c2de9 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -429,6 +429,18 @@
boolean mSystemBooted = false;
boolean mForceDisplayEnabled = false;
boolean mShowingBootMessages = false;
+
+ // This protects the following display size properties, so that
+ // getDisplaySize() doesn't need to acquire the global lock. This is
+ // needed because the window manager sometimes needs to use ActivityThread
+ // while it has its global state locked (for example to load animation
+ // resources), but the ActivityThread also needs get the current display
+ // size sometimes when it has its package lock held.
+ //
+ // These will only be modified with both mWindowMap and mDisplaySizeLock
+ // held (in that order) so the window manager doesn't need to acquire this
+ // lock when needing these values in its normal operation.
+ final Object mDisplaySizeLock = new Object();
int mInitialDisplayWidth = 0;
int mInitialDisplayHeight = 0;
int mBaseDisplayWidth = 0;
@@ -437,6 +449,7 @@
int mCurDisplayHeight = 0;
int mAppDisplayWidth = 0;
int mAppDisplayHeight = 0;
+
int mRotation = 0;
int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
boolean mAltOrientation = false;
@@ -6006,25 +6019,27 @@
final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
- if (mAltOrientation) {
- mCurDisplayWidth = realdw;
- mCurDisplayHeight = realdh;
- if (realdw > realdh) {
- // Turn landscape into portrait.
- int maxw = (int)(realdh/1.3f);
- if (maxw < realdw) {
- mCurDisplayWidth = maxw;
+ synchronized(mDisplaySizeLock) {
+ if (mAltOrientation) {
+ mCurDisplayWidth = realdw;
+ mCurDisplayHeight = realdh;
+ if (realdw > realdh) {
+ // Turn landscape into portrait.
+ int maxw = (int)(realdh/1.3f);
+ if (maxw < realdw) {
+ mCurDisplayWidth = maxw;
+ }
+ } else {
+ // Turn portrait into landscape.
+ int maxh = (int)(realdw/1.3f);
+ if (maxh < realdh) {
+ mCurDisplayHeight = maxh;
+ }
}
} else {
- // Turn portrait into landscape.
- int maxh = (int)(realdw/1.3f);
- if (maxh < realdh) {
- mCurDisplayHeight = maxh;
- }
+ mCurDisplayWidth = realdw;
+ mCurDisplayHeight = realdh;
}
- } else {
- mCurDisplayWidth = realdw;
- mCurDisplayHeight = realdh;
}
final int dw = mCurDisplayWidth;
@@ -6043,8 +6058,12 @@
// Update application display metrics.
final DisplayMetrics dm = mDisplayMetrics;
- mAppDisplayWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
- mAppDisplayHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
+ final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
+ final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
+ synchronized(mDisplaySizeLock) {
+ mAppDisplayWidth = appWidth;
+ mAppDisplayHeight = appHeight;
+ }
if (false) {
Slog.i(TAG, "Set app display size: " + mAppDisplayWidth
+ " x " + mAppDisplayHeight);
@@ -6414,18 +6433,20 @@
}
WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
mDisplay = wm.getDefaultDisplay();
- mInitialDisplayWidth = mDisplay.getRawWidth();
- mInitialDisplayHeight = mDisplay.getRawHeight();
- int rot = mDisplay.getRotation();
- if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
- // If the screen is currently rotated, we need to swap the
- // initial width and height to get the true natural values.
- int tmp = mInitialDisplayWidth;
- mInitialDisplayWidth = mInitialDisplayHeight;
- mInitialDisplayHeight = tmp;
+ synchronized(mDisplaySizeLock) {
+ mInitialDisplayWidth = mDisplay.getRawWidth();
+ mInitialDisplayHeight = mDisplay.getRawHeight();
+ int rot = mDisplay.getRotation();
+ if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
+ // If the screen is currently rotated, we need to swap the
+ // initial width and height to get the true natural values.
+ int tmp = mInitialDisplayWidth;
+ mInitialDisplayWidth = mInitialDisplayHeight;
+ mInitialDisplayHeight = tmp;
+ }
+ mBaseDisplayWidth = mCurDisplayWidth = mAppDisplayWidth = mInitialDisplayWidth;
+ mBaseDisplayHeight = mCurDisplayHeight = mAppDisplayHeight = mInitialDisplayHeight;
}
- mBaseDisplayWidth = mCurDisplayWidth = mAppDisplayWidth = mInitialDisplayWidth;
- mBaseDisplayHeight = mCurDisplayHeight = mAppDisplayHeight = mInitialDisplayHeight;
mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY,
mDisplay.getRawWidth(), mDisplay.getRawHeight(),
mDisplay.getRawExternalWidth(), mDisplay.getRawExternalHeight());
@@ -6963,28 +6984,28 @@
}
public void getDisplaySize(Point size) {
- synchronized(mWindowMap) {
+ synchronized(mDisplaySizeLock) {
size.x = mAppDisplayWidth;
size.y = mAppDisplayHeight;
}
}
public void getRealDisplaySize(Point size) {
- synchronized(mWindowMap) {
+ synchronized(mDisplaySizeLock) {
size.x = mCurDisplayWidth;
size.y = mCurDisplayHeight;
}
}
public void getInitialDisplaySize(Point size) {
- synchronized(mWindowMap) {
+ synchronized(mDisplaySizeLock) {
size.x = mInitialDisplayWidth;
size.y = mInitialDisplayHeight;
}
}
public int getMaximumSizeDimension() {
- synchronized(mWindowMap) {
+ synchronized(mDisplaySizeLock) {
// Do this based on the raw screen size, until we are smarter.
return mBaseDisplayWidth > mBaseDisplayHeight
? mBaseDisplayWidth : mBaseDisplayHeight;
@@ -7077,8 +7098,10 @@
private void setForcedDisplaySizeLocked(int width, int height) {
Slog.i(TAG, "Using new display size: " + width + "x" + height);
- mBaseDisplayWidth = width;
- mBaseDisplayHeight = height;
+ synchronized(mDisplaySizeLock) {
+ mBaseDisplayWidth = width;
+ mBaseDisplayHeight = height;
+ }
mPolicy.setInitialDisplaySize(mBaseDisplayWidth, mBaseDisplayHeight);
mLayoutNeeded = true;
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 61a8358..f63c0c1 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -28,6 +28,7 @@
endif
ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE
+ LOCAL_CFLAGS += -DREFRESH_RATE=56
endif
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1b00e93..f38e948 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -65,6 +65,8 @@
#define AID_GRAPHICS 1003
#endif
+#define EGL_VERSION_HW_ANDROID 0x3143
+
#define DISPLAY_COUNT 1
namespace android {
@@ -1527,7 +1529,7 @@
* Dump the layers in the purgatory
*/
- const size_t purgatorySize = mLayerPurgatory.size();
+ const size_t purgatorySize = mLayerPurgatory.size();
snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize);
result.append(buffer);
for (size_t i=0 ; i<purgatorySize ; i++) {
@@ -1548,6 +1550,12 @@
extensions.getRenderer(),
extensions.getVersion());
result.append(buffer);
+
+ snprintf(buffer, SIZE, "EGL : %s\n",
+ eglQueryString(graphicPlane(0).getEGLDisplay(),
+ EGL_VERSION_HW_ANDROID));
+ result.append(buffer);
+
snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension());
result.append(buffer);
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
index 4390ca1..5020e00 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -28,7 +28,7 @@
SurfaceTextureLayer::SurfaceTextureLayer(GLuint tex, const sp<Layer>& layer)
- : SurfaceTexture(tex), mLayer(layer) {
+ : SurfaceTexture(tex, true, GL_TEXTURE_EXTERNAL_OES, false), mLayer(layer) {
}
SurfaceTextureLayer::~SurfaceTextureLayer() {
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index 636646e..4619899 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -699,8 +699,10 @@
break;
case EVENT_DISCONNECT:
- if (DBG) log("DcDefaultState: msg.what=EVENT_DISCONNECT");
- notifyDisconnectCompleted((DisconnectParams) msg.obj);
+ if (DBG) {
+ log("DcDefaultState deferring msg.what=EVENT_DISCONNECT" + mRefCount);
+ }
+ deferMessage(msg);
break;
case EVENT_RIL_CONNECTED:
@@ -807,6 +809,12 @@
retVal = HANDLED;
break;
+ case EVENT_DISCONNECT:
+ if (DBG) log("DcInactiveState: msg.what=EVENT_DISCONNECT");
+ notifyDisconnectCompleted((DisconnectParams)msg.obj);
+ retVal = HANDLED;
+ break;
+
default:
if (VDBG) {
log("DcInactiveState nothandled msg.what=0x" +
@@ -831,13 +839,6 @@
ConnectionParams cp;
switch (msg.what) {
- case EVENT_DISCONNECT:
- if (DBG) log("DcActivatingState deferring msg.what=EVENT_DISCONNECT"
- + mRefCount);
- deferMessage(msg);
- retVal = HANDLED;
- break;
-
case EVENT_CONNECT:
if (DBG) log("DcActivatingState deferring msg.what=EVENT_CONNECT refCount = "
+ mRefCount);
diff --git a/tests/FrameworkPerf/res/layout/main.xml b/tests/FrameworkPerf/res/layout/main.xml
index 7812648..e00ad92 100644
--- a/tests/FrameworkPerf/res/layout/main.xml
+++ b/tests/FrameworkPerf/res/layout/main.xml
@@ -66,7 +66,24 @@
>
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="Limit by: "
+ />
+ <Spinner android:id="@+id/limitspinner"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:drawSelectorOnTop="true"
+ />
+ </LinearLayout>
+
+ <LinearLayout android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_marginTop="10dp"
+ >
+ <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Test time (ms): "
+ android:id="@+id/limitlabel"
/>
<EditText android:id="@+id/testtime"
android:layout_width="match_parent"
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
index 8ee5978..30a968f 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
@@ -50,6 +50,8 @@
Spinner mFgSpinner;
Spinner mBgSpinner;
+ Spinner mLimitSpinner;
+ TextView mLimitLabel;
TextView mTestTime;
Button mStartButton;
Button mStopButton;
@@ -58,10 +60,12 @@
PowerManager.WakeLock mPartialWakeLock;
long mMaxRunTime = 5000;
+ boolean mLimitIsIterations;
boolean mStarted;
final String[] mAvailOpLabels;
final String[] mAvailOpDescriptions;
+ final String[] mLimitLabels = { "Time", "Iterations" };
int mFgTestIndex = -1;
int mBgTestIndex = -1;
@@ -169,8 +173,15 @@
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mBgSpinner.setAdapter(adapter);
mBgSpinner.setOnItemSelectedListener(this);
+ mLimitSpinner = (Spinner) findViewById(R.id.limitspinner);
+ adapter = new ArrayAdapter<String>(this,
+ android.R.layout.simple_spinner_item, mLimitLabels);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ mLimitSpinner.setAdapter(adapter);
+ mLimitSpinner.setOnItemSelectedListener(this);
mTestTime = (TextView)findViewById(R.id.testtime);
+ mLimitLabel = (TextView)findViewById(R.id.limitlabel);
mStartButton = (Button)findViewById(R.id.start);
mStartButton.setOnClickListener(new View.OnClickListener() {
@@ -196,16 +207,23 @@
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- if (parent == mFgSpinner || parent == mBgSpinner) {
+ if (parent == mFgSpinner || parent == mBgSpinner || parent == mLimitSpinner) {
TestService.Op op = TestService.mAvailOps[position];
if (parent == mFgSpinner) {
mFgTestIndex = position;
mFgTest = op;
((TextView)findViewById(R.id.fgtext)).setText(mAvailOpDescriptions[position]);
- } else {
+ } else if (parent == mBgSpinner) {
mBgTestIndex = position;
mBgTest = op;
((TextView)findViewById(R.id.bgtext)).setText(mAvailOpDescriptions[position]);
+ } else if (parent == mLimitSpinner) {
+ mLimitIsIterations = (position != 0);
+ if (mLimitIsIterations) {
+ mLimitLabel.setText("Iterations: ");
+ } else {
+ mLimitLabel.setText("Test time (ms): ");
+ }
}
}
}
@@ -234,7 +252,11 @@
return;
}
TestArgs args = new TestArgs();
- args.maxTime = mMaxRunTime;
+ if (mLimitIsIterations) {
+ args.maxOps = mMaxRunTime;
+ } else {
+ args.maxTime = mMaxRunTime;
+ }
if (mFgTestIndex == 0 && mBgTestIndex == 0) {
args.combOp = mCurOpIndex;
} else if (mFgTestIndex != 0 && mBgTestIndex != 0) {
@@ -376,6 +398,7 @@
mTestTime.setEnabled(false);
mFgSpinner.setEnabled(false);
mBgSpinner.setEnabled(false);
+ mLimitSpinner.setEnabled(false);
updateWakeLock();
startService(new Intent(this, SchedulerService.class));
mCurOpIndex = 0;
@@ -397,6 +420,7 @@
mTestTime.setEnabled(true);
mFgSpinner.setEnabled(true);
mBgSpinner.setEnabled(true);
+ mLimitSpinner.setEnabled(true);
updateWakeLock();
stopService(new Intent(this, SchedulerService.class));
synchronized (mResults) {
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/TestArgs.java b/tests/FrameworkPerf/src/com/android/frameworkperf/TestArgs.java
index f2f7c56..2fe38aa 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/TestArgs.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/TestArgs.java
@@ -21,6 +21,7 @@
public class TestArgs implements Parcelable {
long maxTime;
+ long maxOps = -1;
int combOp = -1;
int fgOp = -1;
int bgOp = -1;
@@ -30,6 +31,7 @@
public TestArgs(Parcel source) {
maxTime = source.readLong();
+ maxOps = source.readLong();
combOp = source.readInt();
fgOp = source.readInt();
bgOp = source.readInt();
@@ -43,6 +45,7 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(maxTime);
+ dest.writeLong(maxOps);
dest.writeInt(combOp);
dest.writeInt(fgOp);
dest.writeInt(bgOp);
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java b/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java
index 8cf1ac2..a8c43e9 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java
@@ -224,6 +224,7 @@
public class TestRunner {
Handler mHandler;
long mMaxRunTime;
+ long mMaxOps;
Op mForegroundOp;
Op mBackgroundOp;
Runnable mDoneCallback;
@@ -277,6 +278,7 @@
public void run(Handler handler, TestArgs args, Runnable doneCallback) {
mHandler = handler;
mMaxRunTime = args.maxTime;
+ mMaxOps = args.maxOps;
if (args.combOp >= 0) {
mForegroundOp = mOpPairs[args.combOp];
mBackgroundOp = mOpPairs[args.combOp+1];
@@ -352,9 +354,18 @@
if (!mBackgroundRunning && !mForegroundRunning) {
return false;
}
- long now = SystemClock.uptimeMillis();
- if (now > (mStartTime+mMaxRunTime)) {
- return false;
+ if (mMaxOps > 0) {
+ // iteration-limited case
+ if (mForegroundOps >= mMaxOps) {
+ return false;
+ }
+ mForegroundOps++;
+ } else {
+ // time-limited case
+ long now = SystemClock.uptimeMillis();
+ if (now > (mStartTime+mMaxRunTime)) {
+ return false;
+ }
}
return true;
}
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
index b1cef15c..10802b4 100644
--- a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
@@ -110,9 +110,9 @@
* been redrawn.
*/
@Override
- protected void pageSwapCallback() {
+ protected void pageSwapCallback(boolean startAnim) {
mContentInvalMillis = System.currentTimeMillis() - mContentInvalMillis;
- super.pageSwapCallback();
+ super.pageSwapCallback(startAnim);
Log.d("ProfiledWebView", "REDRAW TOOK " + mContentInvalMillis
+ "millis");
mIsTesting = true;