summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java33
-rw-r--r--core/java/android/accessibilityservice/IEventListener.aidl2
-rw-r--r--core/java/android/app/ActivityThread.java8
-rw-r--r--core/java/android/app/ApplicationPackageManager.java37
-rw-r--r--core/java/android/app/DatePickerDialog.java7
-rw-r--r--core/java/android/app/TimePickerDialog.java8
-rw-r--r--core/java/android/bluetooth/BluetoothA2dp.java4
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java26
-rw-r--r--core/java/android/bluetooth/BluetoothDeviceProfileState.java28
-rw-r--r--core/java/android/bluetooth/BluetoothHeadset.java1
-rw-r--r--core/java/android/bluetooth/BluetoothHealth.java4
-rw-r--r--core/java/android/bluetooth/BluetoothInputDevice.java4
-rw-r--r--core/java/android/bluetooth/BluetoothPan.java6
-rw-r--r--core/java/android/bluetooth/BluetoothPbap.java3
-rw-r--r--core/java/android/content/Intent.java68
-rw-r--r--core/java/android/inputmethodservice/ExtractEditText.java23
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java26
-rw-r--r--core/java/android/os/IBinder.java13
-rw-r--r--core/java/android/provider/MediaStore.java5
-rw-r--r--core/java/android/provider/Settings.java22
-rwxr-xr-xcore/java/android/server/BluetoothService.java44
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java4
-rw-r--r--core/java/android/speech/tts/AudioPlaybackHandler.java3
-rwxr-xr-xcore/java/android/speech/tts/TextToSpeech.java20
-rw-r--r--core/java/android/speech/tts/TextToSpeechService.java6
-rw-r--r--core/java/android/text/TextLine.java24
-rw-r--r--core/java/android/text/method/Touch.java40
-rw-r--r--core/java/android/util/SparseArray.java1
-rw-r--r--core/java/android/view/GLES20Canvas.java17
-rw-r--r--core/java/android/view/HardwareRenderer.java12
-rw-r--r--core/java/android/view/IWindowSession.aidl13
-rwxr-xr-xcore/java/android/view/KeyEvent.java22
-rw-r--r--core/java/android/view/SurfaceView.java152
-rw-r--r--core/java/android/view/ViewRootImpl.java39
-rw-r--r--core/java/android/view/VolumePanel.java22
-rw-r--r--core/java/android/view/WindowManagerImpl.java27
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java36
-rw-r--r--core/java/android/view/accessibility/AccessibilityInteractionClient.java240
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java55
-rw-r--r--core/java/android/view/accessibility/AccessibilityRecord.java50
-rw-r--r--core/java/android/view/accessibility/IAccessibilityManager.aidl2
-rw-r--r--core/java/android/webkit/CookieManager.java11
-rw-r--r--core/java/android/webkit/WebView.java66
-rw-r--r--core/java/android/webkit/WebViewCore.java15
-rw-r--r--core/java/android/webkit/ZoomManager.java8
-rw-r--r--core/java/android/widget/NumberPicker.java53
-rw-r--r--core/java/android/widget/TextView.java172
47 files changed, 973 insertions, 509 deletions
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.Message;
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 @@ public abstract class AccessibilityService extends Service {
private AccessibilityServiceInfo mInfo;
- IAccessibilityServiceConnection mConnection;
+ private int mConnectionId;
/**
* Callback for {@link android.view.accessibility.AccessibilityEvent}s.
@@ -264,9 +265,11 @@ public abstract class AccessibilityService extends Service {
* 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 @@ public abstract class AccessibilityService extends Service {
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 @@ public abstract class AccessibilityService extends Service {
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 @@ import android.view.accessibility.AccessibilityEvent;
*/
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 @@ public final class ActivityThread {
// 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 @@ final class ApplicationPackageManager extends PackageManager {
return info.activityInfo.loadIcon(this);
}
- throw new NameNotFoundException(intent.toURI());
+ throw new NameNotFoundException(intent.toUri(0));
}
@Override public Drawable getDefaultActivityIcon() {
@@ -728,15 +728,22 @@ final class ApplicationPackageManager extends PackageManager {
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 @@ final class ApplicationPackageManager extends PackageManager {
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 @@ final class ApplicationPackageManager extends PackageManager {
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 @@ public class DatePickerDialog extends AlertDialog implements OnClickListener,
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 @@ public class TimePickerDialog extends AlertDialog
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 96f3290..7300107 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -129,6 +129,10 @@ public final class BluetoothA2dp implements BluetoothProfile {
}
}
+ /*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 @@ public final class BluetoothAdapter {
* @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 @@ public final class BluetoothDeviceProfileState extends StateMachine {
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 @@ public final class BluetoothDeviceProfileState extends StateMachine {
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 @@ public final class BluetoothDeviceProfileState extends StateMachine {
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 @@ public final class BluetoothHeadset implements BluetoothProfile {
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 @@ public final class BluetoothHealth implements BluetoothProfile {
}
}
+ /*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 @@ public final class BluetoothInputDevice implements BluetoothProfile {
}
}
+ /*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 @@ public final class BluetoothPan implements BluetoothProfile {
}
}
+ /*package*/ void close() {
+ mServiceListener = null;
+ }
+
/**
* Initiate connection to a profile of the remote bluetooth device.
*
@@ -299,4 +303,4 @@ public final class BluetoothPan implements BluetoothProfile {
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 @@ public class BluetoothPbap {
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 @@ public class BluetoothPbap {
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 @@ public class Intent implements Parcelable, Cloneable {
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
+ // 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 @@ public class ExtractEditText extends EditText {
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 @@ public class InputMethodService extends AbstractInputMethodService {
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 @@ public class InputMethodService extends AbstractInputMethodService {
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/os/IBinder.java b/core/java/android/os/IBinder.java
index 81defd6..0586d9e 100644
--- a/core/java/android/os/IBinder.java
+++ b/core/java/android/os/IBinder.java
@@ -128,6 +128,19 @@ public interface IBinder {
int TWEET_TRANSACTION = ('_'<<24)|('T'<<16)|('W'<<8)|'T';
/**
+ * IBinder protocol transaction code: tell an app asynchronously that the
+ * caller likes it. The app is responsible for incrementing and maintaining
+ * its own like counter, and may display this value to the user to indicate the
+ * quality of the app. This is an optional command that applications do not
+ * need to handle, so the default implementation is to do nothing.
+ *
+ * <p>There is no response returned and nothing about the
+ * system will be functionally affected by it, but it will improve the
+ * app's self-esteem.
+ */
+ int LIKE_TRANSACTION = ('_'<<24)|('L'<<16)|('I'<<8)|'K';
+
+ /**
* Flag to {@link #transact}: this is a one-way call, meaning that the
* caller returns immediately, without waiting for a result from the
* callee. Applies only if the caller and callee are in different
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.FileNotFoundException;
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 @@ public final class MediaStore {
/**
* 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 final class Settings {
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..94fbbc8 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -145,7 +145,12 @@ public class BluetoothService extends IBluetooth.Stub {
private final ArrayList<String> mUuidIntentTracker;
private final HashMap<RemoteService, IBluetoothCallback> mUuidCallbackTracker;
- private final HashMap<Integer, Pair<Integer, IBinder>> mServiceRecordToPid;
+ private static class ServiceRecordClient {
+ int pid;
+ IBinder binder;
+ IBinder.DeathRecipient death;
+ }
+ private final HashMap<Integer, ServiceRecordClient> mServiceRecordToPid;
private final HashMap<String, BluetoothDeviceProfileState> mDeviceProfileState;
private final BluetoothProfileState mA2dpProfileState;
@@ -221,7 +226,7 @@ public class BluetoothService extends IBluetooth.Stub {
mDeviceOobData = new HashMap<String, Pair<byte[], byte[]>>();
mUuidIntentTracker = new ArrayList<String>();
mUuidCallbackTracker = new HashMap<RemoteService, IBluetoothCallback>();
- mServiceRecordToPid = new HashMap<Integer, Pair<Integer, IBinder>>();
+ mServiceRecordToPid = new HashMap<Integer, ServiceRecordClient>();
mDeviceProfileState = new HashMap<String, BluetoothDeviceProfileState>();
mA2dpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.A2DP);
mHfpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HFP);
@@ -1528,11 +1533,17 @@ public class BluetoothService extends IBluetooth.Stub {
return -1;
}
- int pid = Binder.getCallingPid();
- mServiceRecordToPid.put(new Integer(handle), new Pair<Integer, IBinder>(pid, b));
+ ServiceRecordClient client = new ServiceRecordClient();
+ client.pid = Binder.getCallingPid();
+ client.binder = b;
+ client.death = new Reaper(handle, client.pid, RFCOMM_RECORD_REAPER);
+ mServiceRecordToPid.put(new Integer(handle), client);
try {
- b.linkToDeath(new Reaper(handle, pid, RFCOMM_RECORD_REAPER), 0);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
+ b.linkToDeath(client.death, 0);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ client.death = null;
+ }
return handle;
}
@@ -1547,10 +1558,15 @@ public class BluetoothService extends IBluetooth.Stub {
}
private synchronized void checkAndRemoveRecord(int handle, int pid) {
- Pair<Integer, IBinder> pidPair = mServiceRecordToPid.get(handle);
- if (pidPair != null && pid == pidPair.first) {
+ ServiceRecordClient client = mServiceRecordToPid.get(handle);
+ if (client != null && pid == client.pid) {
if (DBG) Log.d(TAG, "Removing service record " +
Integer.toHexString(handle) + " for pid " + pid);
+
+ if (client.death != null) {
+ client.binder.unlinkToDeath(client.death, 0);
+ }
+
mServiceRecordToPid.remove(handle);
removeServiceRecordNative(handle);
}
@@ -1880,7 +1896,7 @@ public class BluetoothService extends IBluetooth.Stub {
private void dumpApplicationServiceRecords(PrintWriter pw) {
pw.println("\n--Application Service Records--");
for (Integer handle : mServiceRecordToPid.keySet()) {
- Integer pid = mServiceRecordToPid.get(handle).first;
+ Integer pid = mServiceRecordToPid.get(handle).pid;
pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle));
}
}
@@ -2374,16 +2390,18 @@ public class BluetoothService extends IBluetooth.Stub {
}
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/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index a9a628a..18167b6 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -608,7 +608,7 @@ public abstract class WallpaperService extends Service {
final int relayoutResult = mSession.relayout(
mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
- View.VISIBLE, false, mWinFrame, mContentInsets,
+ View.VISIBLE, 0, mWinFrame, mContentInsets,
mVisibleInsets, mConfiguration, mSurfaceHolder.mSurface);
if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface
@@ -654,7 +654,7 @@ public abstract class WallpaperService extends Service {
}
redrawNeeded |= creating
- || (relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0;
+ || (relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0;
if (forceReport || creating || surfaceCreating
|| formatChanged || sizeChanged) {
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 @@ class AudioPlaybackHandler {
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/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 38699ea..a220615 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -490,6 +490,7 @@ public class TextToSpeech {
private final Map<String, Uri> mUtterances;
private final Bundle mParams = new Bundle();
private final TtsEngines mEnginesHelper;
+ private final String mPackageName;
private volatile String mCurrentEngine = null;
/**
@@ -518,19 +519,36 @@ public class TextToSpeech {
* @param engine Package name of the TTS engine to use.
*/
public TextToSpeech(Context context, OnInitListener listener, String engine) {
+ this(context, listener, engine, null);
+ }
+
+ /**
+ * Used by the framework to instantiate TextToSpeech objects with a supplied
+ * package name, instead of using {@link android.content.Context#getPackageName()}
+ *
+ * @hide
+ */
+ public TextToSpeech(Context context, OnInitListener listener, String engine,
+ String packageName) {
mContext = context;
mInitListener = listener;
mRequestedEngine = engine;
mEarcons = new HashMap<String, Uri>();
mUtterances = new HashMap<String, Uri>();
+ mUtteranceProgressListener = null;
mEnginesHelper = new TtsEngines(mContext);
+ if (packageName != null) {
+ mPackageName = packageName;
+ } else {
+ mPackageName = mContext.getPackageName();
+ }
initTts();
}
private String getPackageName() {
- return mContext.getPackageName();
+ return mPackageName;
}
private <R> R runActionNoReconnect(Action<R> action, R errorResult, String method) {
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index f82a659..aee678a 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -450,7 +450,7 @@ public abstract class TextToSpeechService extends Service {
@Override
public void dispatchOnDone() {
final String utteranceId = getUtteranceId();
- if (!TextUtils.isEmpty(utteranceId)) {
+ if (utteranceId != null) {
mCallbacks.dispatchOnDone(getCallingApp(), utteranceId);
}
}
@@ -458,7 +458,7 @@ public abstract class TextToSpeechService extends Service {
@Override
public void dispatchOnStart() {
final String utteranceId = getUtteranceId();
- if (!TextUtils.isEmpty(utteranceId)) {
+ if (utteranceId != null) {
mCallbacks.dispatchOnStart(getCallingApp(), utteranceId);
}
}
@@ -466,7 +466,7 @@ public abstract class TextToSpeechService extends Service {
@Override
public void dispatchOnError() {
final String utteranceId = getUtteranceId();
- if (!TextUtils.isEmpty(utteranceId)) {
+ if (utteranceId != null) {
mCallbacks.dispatchOnError(getCallingApp(), utteranceId);
}
}
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 68fea19..b73d900 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -119,6 +119,7 @@ class TextLine {
* @param hasTabs true if the line might contain tabs or emoji
* @param tabStops the tabStops. Can be null.
*/
+ @SuppressWarnings("null")
void set(TextPaint paint, CharSequence text, int start, int limit, int dir,
Directions directions, boolean hasTabs, TabStops tabStops) {
mPaint = paint;
@@ -134,11 +135,12 @@ class TextLine {
mSpanned = null;
boolean hasReplacement = false;
+ SpanSet<ReplacementSpan> replacementSpans = null;
if (text instanceof Spanned) {
mSpanned = (Spanned) text;
- ReplacementSpan[] spans = mSpanned.getSpans(start, limit, ReplacementSpan.class);
- spans = TextUtils.removeEmptySpans(spans, mSpanned, ReplacementSpan.class);
- hasReplacement = spans.length > 0;
+ replacementSpans = new SpanSet<ReplacementSpan>(mSpanned, start, limit,
+ ReplacementSpan.class);
+ hasReplacement = replacementSpans.numberOfSpans > 0;
}
mCharsValid = hasReplacement || hasTabs || directions != Layout.DIRS_ALL_LEFT_TO_RIGHT;
@@ -156,10 +158,9 @@ class TextLine {
// zero-width characters.
char[] chars = mChars;
for (int i = start, inext; i < limit; i = inext) {
- inext = mSpanned.nextSpanTransition(i, limit, ReplacementSpan.class);
- ReplacementSpan[] spans = mSpanned.getSpans(i, inext, ReplacementSpan.class);
- spans = TextUtils.removeEmptySpans(spans, mSpanned, ReplacementSpan.class);
- if (spans.length > 0) {
+ // replacementSpans cannot be null if hasReplacement is true
+ inext = replacementSpans.getNextTransition(i, limit);
+ if (replacementSpans.hasSpansIntersecting(i, inext)) {
// transition into a span
chars[i - start] = '\ufffc';
for (int j = i - start + 1, e = inext - start; j < e; ++j) {
@@ -908,6 +909,15 @@ class TextLine {
numberOfSpans = count;
}
+ public boolean hasSpansIntersecting(int start, int end) {
+ for (int i = 0; i < numberOfSpans; i++) {
+ // equal test is valid since both intervals are not empty by construction
+ if (spanStarts[i] >= end || spanEnds[i] <= start) continue;
+ return true;
+ }
+ return false;
+ }
+
int getNextTransition(int start, int limit) {
for (int i = 0; i < numberOfSpans; i++) {
final int spanStart = spanStarts[i];
diff --git a/core/java/android/text/method/Touch.java b/core/java/android/text/method/Touch.java
index 106a801..3dfd44d 100644
--- a/core/java/android/text/method/Touch.java
+++ b/core/java/android/text/method/Touch.java
@@ -35,22 +35,30 @@ public class Touch {
* Y position.
*/
public static void scrollTo(TextView widget, Layout layout, int x, int y) {
- final int verticalPadding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom();
- final int top = layout.getLineForVertical(y);
- final int bottom = layout.getLineForVertical(y + widget.getHeight() - verticalPadding);
+ final int horizontalPadding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight();
+ final int availableWidth = widget.getWidth() - horizontalPadding;
- int left = Integer.MAX_VALUE;
- int right = 0;
+ final int top = layout.getLineForVertical(y);
Alignment a = layout.getParagraphAlignment(top);
boolean ltr = layout.getParagraphDirection(top) > 0;
- for (int i = top; i <= bottom; i++) {
- left = (int) Math.min(left, layout.getLineLeft(i));
- right = (int) Math.max(right, layout.getLineRight(i));
+ int left, right;
+ if (widget.getHorizontallyScrolling()) {
+ final int verticalPadding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom();
+ final int bottom = layout.getLineForVertical(y + widget.getHeight() - verticalPadding);
+
+ left = Integer.MAX_VALUE;
+ right = 0;
+
+ for (int i = top; i <= bottom; i++) {
+ left = (int) Math.min(left, layout.getLineLeft(i));
+ right = (int) Math.max(right, layout.getLineRight(i));
+ }
+ } else {
+ left = 0;
+ right = availableWidth;
}
- final int hoizontalPadding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight();
- final int availableWidth = widget.getWidth() - hoizontalPadding;
final int actualWidth = right - left;
if (actualWidth < availableWidth) {
@@ -166,16 +174,24 @@ public class Touch {
return false;
}
+ /**
+ * @param widget The text view.
+ * @param buffer The text buffer.
+ */
public static int getInitialScrollX(TextView widget, Spannable buffer) {
DragState[] ds = buffer.getSpans(0, buffer.length(), DragState.class);
return ds.length > 0 ? ds[0].mScrollX : -1;
}
-
+
+ /**
+ * @param widget The text view.
+ * @param buffer The text buffer.
+ */
public static int getInitialScrollY(TextView widget, Spannable buffer) {
DragState[] ds = buffer.getSpans(0, buffer.length(), DragState.class);
return ds.length > 0 ? ds[0].mScrollY : -1;
}
-
+
private static class DragState implements NoCopySpan {
public float mX;
public float mY;
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 @@ public class SparseArray<E> implements Cloneable {
if (i != o) {
keys[o] = keys[i];
values[o] = val;
+ values[i] = null;
}
o++;
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index d948ec2..4ca299f 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -737,8 +737,21 @@ class GLES20Canvas extends HardwareCanvas {
// Shaders are ignored when drawing bitmaps
int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
final int nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, src.left, src.top, src.right,
- src.bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint);
+
+ float left, top, right, bottom;
+ if (src == null) {
+ left = top = 0;
+ right = bitmap.getWidth();
+ bottom = bitmap.getHeight();
+ } else {
+ left = src.left;
+ right = src.right;
+ top = src.top;
+ bottom = src.bottom;
+ }
+
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint);
if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index f77cf7e..ccb6489 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -219,6 +219,13 @@ public abstract class HardwareRenderer {
abstract int getHeight();
/**
+ * Gets the current canvas associated with this HardwareRenderer.
+ *
+ * @return the current HardwareCanvas
+ */
+ abstract HardwareCanvas getCanvas();
+
+ /**
* Sets the directory to use as a persistent storage for hardware rendering
* resources.
*
@@ -783,6 +790,11 @@ public abstract class HardwareRenderer {
return mHeight;
}
+ @Override
+ HardwareCanvas getCanvas() {
+ return mCanvas;
+ }
+
boolean canDraw() {
return mGl != null && mCanvas != null;
}
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 282d7be..53d6e1f 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -54,9 +54,8 @@ interface IWindowSession {
* @param requestedWidth The width the window wants to be.
* @param requestedHeight The height the window wants to be.
* @param viewVisibility Window root view's visibility.
- * @param insetsPending Set to true if the client will be later giving
- * internal insets; as a result, the window will not impact other window
- * layouts until the insets are given.
+ * @param flags Request flags: {@link WindowManagerImpl#RELAYOUT_INSETS_PENDING},
+ * {@link WindowManagerImpl#RELAYOUT_DEFER_SURFACE_DESTROY}.
* @param outFrame Rect in which is placed the new position/size on
* screen.
* @param outContentInsets Rect in which is placed the offsets from
@@ -80,11 +79,17 @@ interface IWindowSession {
*/
int relayout(IWindow window, int seq, in WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility,
- boolean insetsPending, out Rect outFrame, out Rect outContentInsets,
+ int flags, out Rect outFrame, out Rect outContentInsets,
out Rect outVisibleInsets, out Configuration outConfig,
out Surface outSurface);
/**
+ * If a call to relayout() asked to have the surface destroy deferred,
+ * it must call this once it is okay to destroy that surface.
+ */
+ void performDeferredDestroy(IWindow window);
+
+ /**
* Called by a client to report that it ran out of graphics memory.
*/
boolean outOfMemory(IWindow window);
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 @@ public class KeyEvent extends InputEvent implements Parcelable {
/** Key code constant: 3D Mode key.
* Toggles the display between 2D and 3D mode. */
public static final int KEYCODE_3D_MODE = 206;
-
- private static final int LAST_KEYCODE = KEYCODE_BUTTON_16;
+ /** 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_CALCULATOR;
// NOTE: If you add a new keycode here you must also add it to:
// isSystem()
@@ -589,6 +601,8 @@ public class KeyEvent extends InputEvent implements Parcelable {
// 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 @@ public class KeyEvent extends InputEvent implements Parcelable {
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/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 9a57ea0..0e68490 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -16,7 +16,6 @@
package android.view;
-import android.util.DisplayMetrics;
import com.android.internal.view.BaseIWindow;
import android.content.Context;
@@ -82,7 +81,6 @@ import java.util.concurrent.locks.ReentrantLock;
public class SurfaceView extends View {
static private final String TAG = "SurfaceView";
static private final boolean DEBUG = false;
- static private final boolean localLOGV = DEBUG ? true : false;
final ArrayList<SurfaceHolder.Callback> mCallbacks
= new ArrayList<SurfaceHolder.Callback>();
@@ -90,7 +88,8 @@ public class SurfaceView extends View {
final int[] mLocation = new int[2];
final ReentrantLock mSurfaceLock = new ReentrantLock();
- final Surface mSurface = new Surface();
+ Surface mSurface = new Surface(); // Current surface in use
+ Surface mNewSurface = new Surface(); // New surface we are switching to
boolean mDrawingStopped = true;
final WindowManager.LayoutParams mLayout
@@ -145,8 +144,7 @@ public class SurfaceView extends View {
int mRequestedFormat = PixelFormat.RGB_565;
boolean mHaveFrame = false;
- boolean mDestroyReportNeeded = false;
- boolean mNewSurfaceNeeded = false;
+ boolean mSurfaceCreated = false;
long mLastLockTime = 0;
boolean mVisible = false;
@@ -236,46 +234,6 @@ public class SurfaceView extends View {
updateWindow(false, false);
}
- /**
- * This method is not intended for general use. It was created
- * temporarily to improve performance of 3D layers in Launcher
- * and should be removed and fixed properly.
- *
- * Do not call this method. Ever.
- *
- * @hide
- */
- protected void showSurface() {
- if (mSession != null) {
- updateWindow(true, false);
- }
- }
-
- /**
- * This method is not intended for general use. It was created
- * temporarily to improve performance of 3D layers in Launcher
- * and should be removed and fixed properly.
- *
- * Do not call this method. Ever.
- *
- * @hide
- */
- protected void hideSurface() {
- if (mSession != null && mWindow != null) {
- mSurfaceLock.lock();
- try {
- DisplayMetrics metrics = getResources().getDisplayMetrics();
- mLayout.x = metrics.widthPixels * 3;
- mSession.relayout(mWindow, mWindow.mSeq, mLayout, mWidth, mHeight, VISIBLE, false,
- mWinFrame, mContentInsets, mVisibleInsets, mConfiguration, mSurface);
- } catch (RemoteException e) {
- // Ignore
- } finally {
- mSurfaceLock.unlock();
- }
- }
- }
-
@Override
protected void onDetachedFromWindow() {
if (mGlobalListenersAdded) {
@@ -444,14 +402,13 @@ public class SurfaceView extends View {
final boolean creating = mWindow == null;
final boolean formatChanged = mFormat != mRequestedFormat;
final boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
- final boolean visibleChanged = mVisible != mRequestedVisible
- || mNewSurfaceNeeded;
+ final boolean visibleChanged = mVisible != mRequestedVisible;
if (force || creating || formatChanged || sizeChanged || visibleChanged
|| mLeft != mLocation[0] || mTop != mLocation[1]
|| mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) {
- if (localLOGV) Log.i(TAG, "Changes: creating=" + creating
+ if (DEBUG) Log.i(TAG, "Changes: creating=" + creating
+ " format=" + formatChanged + " size=" + sizeChanged
+ " visible=" + visibleChanged
+ " left=" + (mLeft != mLocation[0])
@@ -496,15 +453,11 @@ public class SurfaceView extends View {
mVisible ? VISIBLE : GONE, mContentInsets);
}
- if (visibleChanged && (!visible || mNewSurfaceNeeded)) {
- reportSurfaceDestroyed();
- }
-
- mNewSurfaceNeeded = false;
-
boolean realSizeChanged;
boolean reportDrawNeeded;
-
+
+ int relayoutResult;
+
mSurfaceLock.lock();
try {
mUpdateWindowNeeded = false;
@@ -512,17 +465,21 @@ public class SurfaceView extends View {
mReportDrawNeeded = false;
mDrawingStopped = !visible;
- final int relayoutResult = mSession.relayout(
+ if (DEBUG) Log.i(TAG, "Cur surface: " + mSurface);
+
+ relayoutResult = mSession.relayout(
mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
- visible ? VISIBLE : GONE, false, mWinFrame, mContentInsets,
- mVisibleInsets, mConfiguration, mSurface);
- if ((relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) {
+ visible ? VISIBLE : GONE,
+ WindowManagerImpl.RELAYOUT_DEFER_SURFACE_DESTROY,
+ mWinFrame, mContentInsets,
+ mVisibleInsets, mConfiguration, mNewSurface);
+ if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
mReportDrawNeeded = true;
}
-
- if (localLOGV) Log.i(TAG, "New surface: " + mSurface
+
+ if (DEBUG) Log.i(TAG, "New surface: " + mNewSurface
+ ", vis=" + visible + ", frame=" + mWinFrame);
-
+
mSurfaceFrame.left = 0;
mSurfaceFrame.top = 0;
if (mTranslator == null) {
@@ -547,28 +504,54 @@ public class SurfaceView extends View {
try {
redrawNeeded |= creating | reportDrawNeeded;
- if (visible) {
- mDestroyReportNeeded = true;
+ SurfaceHolder.Callback callbacks[] = null;
- SurfaceHolder.Callback callbacks[];
- synchronized (mCallbacks) {
- callbacks = new SurfaceHolder.Callback[mCallbacks.size()];
- mCallbacks.toArray(callbacks);
+ final boolean surfaceChanged =
+ (relayoutResult&WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED) != 0;
+ if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {
+ mSurfaceCreated = false;
+ if (mSurface.isValid()) {
+ if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceDestroyed");
+ callbacks = getSurfaceCallbacks();
+ for (SurfaceHolder.Callback c : callbacks) {
+ c.surfaceDestroyed(mSurfaceHolder);
+ }
}
+ }
+
+ Surface tmpSurface = mSurface;
+ mSurface = mNewSurface;
+ mNewSurface = tmpSurface;
+ mNewSurface.release();
- if (visibleChanged) {
+ if (visible) {
+ if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) {
+ mSurfaceCreated = true;
mIsCreating = true;
+ if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceCreated");
+ if (callbacks == null) {
+ callbacks = getSurfaceCallbacks();
+ }
for (SurfaceHolder.Callback c : callbacks) {
c.surfaceCreated(mSurfaceHolder);
}
}
if (creating || formatChanged || sizeChanged
|| visibleChanged || realSizeChanged) {
+ if (DEBUG) Log.i(TAG, "surfaceChanged -- format=" + mFormat
+ + " w=" + myWidth + " h=" + myHeight);
+ if (callbacks == null) {
+ callbacks = getSurfaceCallbacks();
+ }
for (SurfaceHolder.Callback c : callbacks) {
c.surfaceChanged(mSurfaceHolder, mFormat, myWidth, myHeight);
}
}
if (redrawNeeded) {
+ if (DEBUG) Log.i(TAG, "surfaceRedrawNeeded");
+ if (callbacks == null) {
+ callbacks = getSurfaceCallbacks();
+ }
for (SurfaceHolder.Callback c : callbacks) {
if (c instanceof SurfaceHolder.Callback2) {
((SurfaceHolder.Callback2)c).surfaceRedrawNeeded(
@@ -576,41 +559,34 @@ public class SurfaceView extends View {
}
}
}
- } else {
- mSurface.release();
}
} finally {
mIsCreating = false;
if (redrawNeeded) {
+ if (DEBUG) Log.i(TAG, "finishedDrawing");
mSession.finishDrawing(mWindow);
}
+ mSession.performDeferredDestroy(mWindow);
}
} catch (RemoteException ex) {
}
- if (localLOGV) Log.v(
+ if (DEBUG) Log.v(
TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
" w=" + mLayout.width + " h=" + mLayout.height +
", frame=" + mSurfaceFrame);
}
}
- private void reportSurfaceDestroyed() {
- if (mDestroyReportNeeded) {
- mDestroyReportNeeded = false;
- SurfaceHolder.Callback callbacks[];
- synchronized (mCallbacks) {
- callbacks = new SurfaceHolder.Callback[mCallbacks.size()];
- mCallbacks.toArray(callbacks);
- }
- for (SurfaceHolder.Callback c : callbacks) {
- c.surfaceDestroyed(mSurfaceHolder);
- }
+ private SurfaceHolder.Callback[] getSurfaceCallbacks() {
+ SurfaceHolder.Callback callbacks[];
+ synchronized (mCallbacks) {
+ callbacks = new SurfaceHolder.Callback[mCallbacks.size()];
+ mCallbacks.toArray(callbacks);
}
- super.onDetachedFromWindow();
+ return callbacks;
}
void handleGetNewSurface() {
- mNewSurfaceNeeded = true;
updateWindow(false, false);
}
@@ -636,7 +612,7 @@ public class SurfaceView extends View {
Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
SurfaceView surfaceView = mSurfaceView.get();
if (surfaceView != null) {
- if (localLOGV) Log.v(
+ if (DEBUG) Log.v(
"SurfaceView", surfaceView + " got resized: w=" +
w + " h=" + h + ", cur w=" + mCurWidth + " h=" + mCurHeight);
surfaceView.mSurfaceLock.lock();
@@ -754,7 +730,7 @@ public class SurfaceView extends View {
private final Canvas internalLockCanvas(Rect dirty) {
mSurfaceLock.lock();
- if (localLOGV) Log.i(TAG, "Locking canvas... stopped="
+ if (DEBUG) Log.i(TAG, "Locking canvas... stopped="
+ mDrawingStopped + ", win=" + mWindow);
Canvas c = null;
@@ -774,7 +750,7 @@ public class SurfaceView extends View {
}
}
- if (localLOGV) Log.i(TAG, "Returned canvas: " + c);
+ if (DEBUG) Log.i(TAG, "Returned canvas: " + c);
if (c != null) {
mLastLockTime = SystemClock.uptimeMillis();
return c;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 5f70a39..7f5b5be 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1216,7 +1216,8 @@ public final class ViewRootImpl extends Handler implements ViewParent,
disposeResizeBuffer();
boolean completed = false;
- HardwareCanvas canvas = null;
+ HardwareCanvas hwRendererCanvas = mAttachInfo.mHardwareRenderer.getCanvas();
+ HardwareCanvas layerCanvas = null;
try {
if (mResizeBuffer == null) {
mResizeBuffer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
@@ -1225,12 +1226,12 @@ public final class ViewRootImpl extends Handler implements ViewParent,
mResizeBuffer.getHeight() != mHeight) {
mResizeBuffer.resize(mWidth, mHeight);
}
- canvas = mResizeBuffer.start(mAttachInfo.mHardwareCanvas);
- canvas.setViewport(mWidth, mHeight);
- canvas.onPreDraw(null);
- final int restoreCount = canvas.save();
+ layerCanvas = mResizeBuffer.start(hwRendererCanvas);
+ layerCanvas.setViewport(mWidth, mHeight);
+ layerCanvas.onPreDraw(null);
+ final int restoreCount = layerCanvas.save();
- canvas.drawColor(0xff000000, PorterDuff.Mode.SRC);
+ layerCanvas.drawColor(0xff000000, PorterDuff.Mode.SRC);
int yoff;
final boolean scrolling = mScroller != null
@@ -1242,27 +1243,27 @@ public final class ViewRootImpl extends Handler implements ViewParent,
yoff = mScrollY;
}
- canvas.translate(0, -yoff);
+ layerCanvas.translate(0, -yoff);
if (mTranslator != null) {
- mTranslator.translateCanvas(canvas);
+ mTranslator.translateCanvas(layerCanvas);
}
- mView.draw(canvas);
+ mView.draw(layerCanvas);
mResizeBufferStartTime = SystemClock.uptimeMillis();
mResizeBufferDuration = mView.getResources().getInteger(
com.android.internal.R.integer.config_mediumAnimTime);
completed = true;
- canvas.restoreToCount(restoreCount);
+ layerCanvas.restoreToCount(restoreCount);
} catch (OutOfMemoryError e) {
Log.w(TAG, "Not enough memory for content change anim buffer", e);
} finally {
- if (canvas != null) {
- canvas.onPostDraw();
+ if (layerCanvas != null) {
+ layerCanvas.onPostDraw();
}
if (mResizeBuffer != null) {
- mResizeBuffer.end(mAttachInfo.mHardwareCanvas);
+ mResizeBuffer.end(hwRendererCanvas);
if (!completed) {
mResizeBuffer.destroy();
mResizeBuffer = null;
@@ -1425,7 +1426,7 @@ public final class ViewRootImpl extends Handler implements ViewParent,
if (!mStopped) {
boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
- (relayoutResult&WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE) != 0);
+ (relayoutResult&WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
|| mHeight != host.getMeasuredHeight() || contentInsetsChanged) {
childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
@@ -1636,7 +1637,7 @@ public final class ViewRootImpl extends Handler implements ViewParent,
mLastDrawDurationNanos = System.nanoTime() - drawStartTime;
}
- if ((relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0
+ if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0
|| mReportNextDraw) {
if (LOCAL_LOGV) {
Log.v(TAG, "FINISHED DRAWING: " + mWindowAttributes.getTitle());
@@ -1669,7 +1670,7 @@ public final class ViewRootImpl extends Handler implements ViewParent,
}
// We were supposed to report when we are done drawing. Since we canceled the
// draw, remember it here.
- if ((relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) {
+ if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
mReportNextDraw = true;
}
if (fullRedrawNeeded) {
@@ -3585,8 +3586,8 @@ public final class ViewRootImpl extends Handler implements ViewParent,
mWindow, mSeq, params,
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f),
- viewVisibility, insetsPending, mWinFrame,
- mPendingContentInsets, mPendingVisibleInsets,
+ viewVisibility, insetsPending ? WindowManagerImpl.RELAYOUT_INSETS_PENDING : 0,
+ mWinFrame, mPendingContentInsets, mPendingVisibleInsets,
mPendingConfiguration, mSurface);
//Log.d(TAG, "<<<<<< BACK FROM relayout");
if (restore) {
@@ -3716,7 +3717,7 @@ public final class ViewRootImpl extends Handler implements ViewParent,
// animation info.
try {
if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
- & WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) {
+ & WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
sWindowSession.finishDrawing(mWindow);
}
} catch (RemoteException e) {
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index b657204..48fe0df 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -278,10 +278,6 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
}
private void createSliders() {
- final int silentableStreams = System.getInt(mContext.getContentResolver(),
- System.MODE_RINGER_STREAMS_AFFECTED,
- ((1 << AudioSystem.STREAM_NOTIFICATION) | (1 << AudioSystem.STREAM_RING)));
-
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mStreamControls = new HashMap<Integer, StreamControl>(STREAMS.length);
@@ -297,9 +293,6 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
sc.group = (ViewGroup) inflater.inflate(R.layout.volume_adjust_item, null);
sc.group.setTag(sc);
sc.icon = (ImageView) sc.group.findViewById(R.id.stream_icon);
- if ((silentableStreams & (1 << sc.streamType)) != 0) {
- sc.icon.setOnClickListener(this);
- }
sc.icon.setTag(sc);
sc.icon.setContentDescription(res.getString(streamRes.descRes));
sc.iconRes = streamRes.iconRes;
@@ -356,7 +349,6 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
&& mAudioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)) {
sc.icon.setImageResource(R.drawable.ic_audio_ring_notif_vibrate);
}
- sc.seekbarView.setEnabled(!muted);
}
private boolean isExpanded() {
@@ -436,8 +428,6 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
mAudioService.getLastAudibleStreamVolume(streamType)
: mAudioService.getStreamVolume(streamType);
-// int message = UNKNOWN_VOLUME_TEXT;
-// int additionalMessage = 0;
mRingIsSilent = false;
if (LOGD) {
@@ -697,18 +687,6 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
public void onClick(View v) {
if (v == mMoreButton) {
expand();
- } else if (v.getTag() instanceof StreamControl) {
- StreamControl sc = (StreamControl) v.getTag();
- boolean vibeInSilent = Settings.System.getInt(mContext.getContentResolver(),
- System.VIBRATE_IN_SILENT, 1) == 1;
- int newMode = mAudioManager.isSilentMode()
- ? AudioManager.RINGER_MODE_NORMAL
- : (vibeInSilent
- ? AudioManager.RINGER_MODE_VIBRATE
- : AudioManager.RINGER_MODE_SILENT);
- mAudioManager.setRingerMode(newMode);
- // Expand the dialog if it hasn't been expanded yet.
- if (mShowCombinedVolumes && !isExpanded()) expand();
}
resetTimeout();
}
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index dfd1d55..d711337 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -63,15 +63,34 @@ public class WindowManagerImpl implements WindowManager {
* The user is navigating with keys (not the touch screen), so
* navigational focus should be shown.
*/
- public static final int RELAYOUT_IN_TOUCH_MODE = 0x1;
+ public static final int RELAYOUT_RES_IN_TOUCH_MODE = 0x1;
/**
* This is the first time the window is being drawn,
* so the client must call drawingFinished() when done
*/
- public static final int RELAYOUT_FIRST_TIME = 0x2;
-
+ public static final int RELAYOUT_RES_FIRST_TIME = 0x2;
+ /**
+ * The window manager has changed the surface from the last call.
+ */
+ public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4;
+
+ /**
+ * Flag for relayout: the client will be later giving
+ * internal insets; as a result, the window will not impact other window
+ * layouts until the insets are given.
+ */
+ public static final int RELAYOUT_INSETS_PENDING = 0x1;
+
+ /**
+ * Flag for relayout: the client may be currently using the current surface,
+ * so if it is to be destroyed as a part of the relayout the destroy must
+ * be deferred until later. The client will call performDeferredDestroy()
+ * when it is okay.
+ */
+ public static final int RELAYOUT_DEFER_SURFACE_DESTROY = 0x2;
+
public static final int ADD_FLAG_APP_VISIBLE = 0x2;
- public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_IN_TOUCH_MODE;
+ public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_RES_IN_TOUCH_MODE;
public static final int ADD_OKAY = 0;
public static final int ADD_BAD_APP_TOKEN = -1;
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 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
}
/**
- * 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 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
* @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 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
* {@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..96653e5 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -21,6 +21,8 @@ import android.graphics.Rect;
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 @@ import java.util.concurrent.atomic.AtomicInteger;
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,10 @@ public final class AccessibilityInteractionClient
private final Rect mTempBounds = new Rect();
+ // The connection cache is shared between all interrogating threads.
+ private static final SparseArray<IAccessibilityServiceConnection> sConnectionCache =
+ new SparseArray<IAccessibilityServiceConnection>();
+
/**
* @return The singleton of this class.
*/
@@ -111,28 +123,37 @@ public final class AccessibilityInteractionClient
/**
* 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 +162,36 @@ public final class AccessibilityInteractionClient
* 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 +201,36 @@ public final class AccessibilityInteractionClient
* 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 +241,39 @@ public final class AccessibilityInteractionClient
* 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 +281,33 @@ public final class AccessibilityInteractionClient
/**
* 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 +467,14 @@ public final class AccessibilityInteractionClient
* 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 +483,16 @@ public final class AccessibilityInteractionClient
* 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 +510,39 @@ public final class AccessibilityInteractionClient
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 (sConnectionCache) {
+ return sConnectionCache.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 (sConnectionCache) {
+ sConnectionCache.put(connectionId, connection);
+ }
+ }
+
+ /**
+ * Removes a cached accessibility service connection.
+ *
+ * @param connectionId The connection id.
+ */
+ public void removeConnection(int connectionId) {
+ synchronized (sConnectionCache) {
+ sConnectionCache.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 @@ public class AccessibilityNodeInfo implements Parcelable {
private static final boolean DEBUG = false;
+ private static final int UNDEFINED = -1;
+
// Actions.
/**
@@ -107,9 +108,9 @@ public class AccessibilityNodeInfo implements Parcelable {
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 @@ public class AccessibilityNodeInfo implements Parcelable {
private SparseIntArray mChildAccessibilityIds = new SparseIntArray();
private int mActions;
- private IAccessibilityServiceConnection mConnection;
+ private int mConnectionId = UNDEFINED;
/**
* Hide constructor from clients.
@@ -181,7 +182,7 @@ public class AccessibilityNodeInfo implements Parcelable {
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfoByAccessibilityId(mConnection,
+ return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
mAccessibilityWindowId, childAccessibilityViewId);
}
@@ -253,7 +254,7 @@ public class AccessibilityNodeInfo implements Parcelable {
return false;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.performAccessibilityAction(mConnection, mAccessibilityWindowId,
+ return client.performAccessibilityAction(mConnectionId, mAccessibilityWindowId,
mAccessibilityViewId, action);
}
@@ -277,7 +278,7 @@ public class AccessibilityNodeInfo implements Parcelable {
return Collections.emptyList();
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfosByViewText(mConnection, text,
+ return client.findAccessibilityNodeInfosByViewText(mConnectionId, text,
mAccessibilityWindowId, mAccessibilityViewId);
}
@@ -297,7 +298,7 @@ public class AccessibilityNodeInfo implements Parcelable {
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfoByAccessibilityId(mConnection,
+ return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
mAccessibilityWindowId, mParentAccessibilityViewId);
}
@@ -755,15 +756,16 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
- * 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 @@ public class AccessibilityNodeInfo implements Parcelable {
* </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 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
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 @@ public class AccessibilityNodeInfo implements Parcelable {
* @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 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
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 @@ public class AccessibilityNodeInfo implements Parcelable {
}
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 @@ public class AccessibilityRecord {
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 @@ public class AccessibilityRecord {
Parcelable mParcelableData;
final List<CharSequence> mText = new ArrayList<CharSequence>();
- IAccessibilityServiceConnection mConnection;
+
+ int mConnectionId = UNDEFINED;
/*
* Hide constructor.
@@ -108,8 +108,8 @@ public class AccessibilityRecord {
mSourceWindowId = source.getAccessibilityWindowId();
mSourceViewId = source.getAccessibilityViewId();
} else {
- mSourceWindowId = View.NO_ID;
- mSourceViewId = View.NO_ID;
+ mSourceWindowId = UNDEFINED;
+ mSourceViewId = UNDEFINED;
}
}
@@ -119,33 +119,21 @@ public class AccessibilityRecord {
* <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 @@ public class AccessibilityRecord {
}
/**
+ * 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 @@ public class AccessibilityRecord {
mText.addAll(record.mText);
mSourceWindowId = record.mSourceWindowId;
mSourceViewId = record.mSourceViewId;
- mConnection = record.mConnection;
+ mConnectionId = record.mConnectionId;
}
/**
@@ -732,8 +733,9 @@ public class AccessibilityRecord {
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 @@ interface IAccessibilityManager {
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 @@ public final class CookieManager {
* 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 @@ public final class CookieManager {
* 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 @@ public final class CookieManager {
* {@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 877c9ea..24eebd7 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -507,7 +507,7 @@ public class WebView extends AbsoluteLayout
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
@@ -1306,8 +1306,15 @@ public class WebView extends AbsoluteLayout
if (AccessibilityManager.getInstance(mContext).isEnabled()
&& getSettings().getJavaScriptEnabled()) {
// exposing the TTS for now ...
- mTextToSpeech = new TextToSpeech(getContext(), null);
- addJavascriptInterface(mTextToSpeech, ALIAS_ACCESSIBILITY_JS_INTERFACE);
+ final Context ctx = getContext();
+ if (ctx != null) {
+ final String packageName = ctx.getPackageName();
+ if (packageName != null) {
+ mTextToSpeech = new TextToSpeech(getContext(), null, null,
+ packageName + ".**webview**");
+ addJavascriptInterface(mTextToSpeech, ALIAS_ACCESSIBILITY_JS_INTERFACE);
+ }
+ }
}
}
@@ -1628,6 +1635,14 @@ public class WebView extends AbsoluteLayout
clearTextEntry();
clearActionModes();
dismissFullScreenMode();
+ cancelSelectDialog();
+ }
+
+ private void cancelSelectDialog() {
+ if (mListBoxDialog != null) {
+ mListBoxDialog.cancel();
+ mListBoxDialog = null;
+ }
}
/**
@@ -3279,6 +3294,8 @@ public class WebView extends AbsoluteLayout
if (mNativeClass != 0) {
nativeSetPauseDrawing(mNativeClass, true);
}
+
+ cancelSelectDialog();
}
}
@@ -3648,7 +3665,7 @@ public class WebView extends AbsoluteLayout
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);
@@ -4453,6 +4470,7 @@ public class WebView extends AbsoluteLayout
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.
@@ -4488,6 +4506,14 @@ public class WebView extends AbsoluteLayout
}
}
+ 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)
@@ -4587,14 +4613,15 @@ public class WebView extends AbsoluteLayout
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
@@ -4905,6 +4932,7 @@ public class WebView extends AbsoluteLayout
// 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();
@@ -5496,10 +5524,10 @@ public class WebView extends AbsoluteLayout
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));
@@ -5985,9 +6013,9 @@ public class WebView extends AbsoluteLayout
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;
}
}
@@ -6218,7 +6246,7 @@ public class WebView extends AbsoluteLayout
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);
@@ -6409,7 +6437,7 @@ public class WebView extends AbsoluteLayout
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);
@@ -6718,7 +6746,7 @@ public class WebView extends AbsoluteLayout
// 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);
@@ -7240,7 +7268,7 @@ public class WebView extends AbsoluteLayout
+ " vx=" + vx + " vy=" + vy
+ " maxX=" + maxX + " maxY=" + maxY
+ " scrollX=" + scrollX + " scrollY=" + scrollY
- + " layer=" + mScrollingLayer);
+ + " layer=" + mCurrentScrollingLayerId);
}
// Allow sloppy flings without overscrolling at the edges.
@@ -8349,7 +8377,7 @@ public class WebView extends AbsoluteLayout
mSentAutoScrollMessage = false;
break;
}
- if (mScrollingLayer == 0) {
+ if (mCurrentScrollingLayerId == 0) {
pinScrollBy(mAutoScrollX, mAutoScrollY, true, 0);
} else {
scrollLayerTo(mScrollingLayerRect.left + mAutoScrollX,
@@ -8779,10 +8807,13 @@ public class WebView extends AbsoluteLayout
/** @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) {
@@ -9560,6 +9591,7 @@ public class WebView extends AbsoluteLayout
* 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 @@ public final class WebViewCore {
/**
* 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 @@ public final class WebViewCore {
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 @@ public final class WebViewCore {
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 @@ public final class WebViewCore {
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 84d00c9..8c57265 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -493,11 +493,19 @@ class ZoomManager {
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) {
// We've reached the end of the zoom animation.
mInHWAcceleratedZoom = false;
+
+ // Ensure that the zoom level is pushed to WebCore. This has not
+ // yet occurred because we prevent it from happening while
+ // mInHWAcceleratedZoom is true.
+ mWebView.sendViewSizeZoom(false);
}
} else {
canvas.translate(tx, ty);
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 @@ public class NumberPicker extends LinearLayout {
};
/**
+ * 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 @@ public class NumberPicker extends LinearLayout {
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 @@ public class NumberPicker extends LinearLayout {
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 @@ public class NumberPicker extends LinearLayout {
}
updateInputTextView();
initializeSelectorWheelIndices();
+ tryComputeMaxWidth();
}
@Override
@@ -1368,6 +1378,9 @@ public class NumberPicker extends LinearLayout {
* @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 @@ public class NumberPicker extends LinearLayout {
}
/**
+ * 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..bd03fb9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -2581,6 +2581,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
/**
+ * Returns whether the text is allowed to be wider than the View is.
+ * If false, the text will be wrapped to the width of the View.
+ *
+ * @attr ref android.R.styleable#TextView_scrollHorizontally
+ * @hide
+ */
+ public boolean getHorizontallyScrolling() {
+ return mHorizontallyScrolling;
+ }
+
+ /**
* Makes the TextView at least this many lines tall.
*
* Setting this value overrides any other (minimum) height setting. A single line TextView will
@@ -3816,7 +3827,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (imm != null && imm.isActive(this)) {
imm.hideSoftInputFromWindow(getWindowToken(), 0);
}
- clearFocus();
return;
}
}
@@ -3838,7 +3848,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
| KeyEvent.FLAG_EDITOR_ACTION)));
}
}
-
+
/**
* Set the private content type of the text, which is the
* {@link EditorInfo#privateImeOptions EditorInfo.privateImeOptions}
@@ -5594,8 +5604,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
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 +7621,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
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 +7667,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
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 +7969,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@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 +9098,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
case ID_CUT:
setPrimaryClip(ClipData.newPlainText(null, getTransformedText(min, max)));
- ((Editable) mText).delete(min, max);
+ deleteText_internal(min, max);
stopSelectionActionMode();
return true;
@@ -9127,7 +9129,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
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 +9139,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
!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 +9153,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
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, " ");
}
}
}
@@ -9376,40 +9378,57 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mPositionY = mTempCoords[1];
}
- public boolean isVisible(int positionX, int positionY) {
- final TextView textView = TextView.this;
+ public void onScrollChanged() {
+ mScrollHasChanged = true;
+ }
+ }
- if (mTempRect == null) mTempRect = new Rect();
- final Rect clip = mTempRect;
- clip.left = getCompoundPaddingLeft();
- clip.top = getExtendedPaddingTop();
- clip.right = textView.getWidth() - getCompoundPaddingRight();
- clip.bottom = textView.getHeight() - getExtendedPaddingBottom();
-
- final ViewParent parent = textView.getParent();
- if (parent == null || !parent.getChildVisibleRect(textView, clip, null)) {
- return false;
- }
+ private boolean isPositionVisible(int positionX, int positionY) {
+ synchronized (sTmpPosition) {
+ final float[] position = sTmpPosition;
+ position[0] = positionX;
+ position[1] = positionY;
+ View view = this;
- int posX = mPositionX + positionX;
- int posY = mPositionY + positionY;
+ while (view != null) {
+ if (view != this) {
+ // Local scroll is already taken into account in positionX/Y
+ position[0] -= view.getScrollX();
+ position[1] -= view.getScrollY();
+ }
- // Offset by 1 to take into account 0.5 and int rounding around getPrimaryHorizontal.
- return posX >= clip.left - 1 && posX <= clip.right + 1 &&
- posY >= clip.top && posY <= clip.bottom;
- }
+ if (position[0] < 0 || position[1] < 0 ||
+ position[0] > view.getWidth() || position[1] > view.getHeight()) {
+ return false;
+ }
- public boolean isOffsetVisible(int offset) {
- final int line = mLayout.getLineForOffset(offset);
- final int lineBottom = mLayout.getLineBottom(line);
- final int primaryHorizontal = (int) mLayout.getPrimaryHorizontal(offset);
- return isVisible(primaryHorizontal + viewportToContentHorizontalOffset(),
- lineBottom + viewportToContentVerticalOffset());
- }
+ if (!view.getMatrix().isIdentity()) {
+ view.getMatrix().mapPoints(position);
+ }
- public void onScrollChanged() {
- mScrollHasChanged = true;
+ position[0] += view.getLeft();
+ position[1] += view.getTop();
+
+ final ViewParent parent = view.getParent();
+ if (parent instanceof View) {
+ view = (View) parent;
+ } else {
+ // We've reached the ViewRoot, stop iterating
+ view = null;
+ }
+ }
}
+
+ // We've been able to walk up the view hierarchy and the position was never clipped
+ return true;
+ }
+
+ private boolean isOffsetVisible(int offset) {
+ final int line = mLayout.getLineForOffset(offset);
+ final int lineBottom = mLayout.getLineBottom(line);
+ final int primaryHorizontal = (int) mLayout.getPrimaryHorizontal(offset);
+ return isPositionVisible(primaryHorizontal + viewportToContentHorizontalOffset(),
+ lineBottom + viewportToContentVerticalOffset());
}
@Override
@@ -9510,7 +9529,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
public void updatePosition(int parentPositionX, int parentPositionY,
boolean parentPositionChanged, boolean parentScrolled) {
// Either parentPositionChanged or parentScrolled is true, check if still visible
- if (isShowing() && getPositionListener().isOffsetVisible(getTextOffset())) {
+ if (isShowing() && isOffsetVisible(getTextOffset())) {
if (parentScrolled) computeLocalPosition();
updatePosition(parentPositionX, parentPositionY);
} else {
@@ -9867,9 +9886,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@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 +9900,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
Character.isSpaceChar(editable.charAt(spanUnionStart - 1)))) {
spanUnionEnd = spanUnionEnd + 1;
}
- editable.replace(spanUnionStart, spanUnionEnd, "");
+ deleteText_internal(spanUnionStart, spanUnionEnd);
}
hide();
return;
@@ -9904,6 +9921,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
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 +9949,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
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 +9975,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// 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]);
}
@@ -10534,7 +10553,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return false;
}
- return getPositionListener().isVisible(mPositionX + mHotspotX, mPositionY);
+ return TextView.this.isPositionVisible(mPositionX + mHotspotX, mPositionY);
}
public abstract int getCurrentCursorOffset();
@@ -10823,7 +10842,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// 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 +10884,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// 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 +11256,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
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 +11269,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
// 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 +11278,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
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 +11439,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
+ /**
+ * 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;
@@ -11500,6 +11535,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private Path mHighlightPath;
private boolean mHighlightPathBogus = true;
private static final RectF sTempRect = new RectF();
+ private static final float[] sTmpPosition = new float[2];
// XXX should be much larger
private static final int VERY_WIDE = 1024*1024;