Merge "Fix bug 3374792 - Default holo dark activity background is badly dithered at full size" into honeycomb
diff --git a/api/current.xml b/api/current.xml
index 8655ad3..9520f19 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -234861,6 +234861,17 @@
visibility="public"
>
</method>
+<method name="getDisplayZoomControls"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getDomStorageEnabled"
return="boolean"
abstract="false"
@@ -235355,6 +235366,19 @@
<parameter name="zoom" type="android.webkit.WebSettings.ZoomDensity">
</parameter>
</method>
+<method name="setDisplayZoomControls"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
<method name="setDomStorageEnabled"
return="void"
abstract="false"
diff --git a/core/java/android/accounts/ChooseAccountActivity.java b/core/java/android/accounts/ChooseAccountActivity.java
index 0bbb6fc..293df78 100644
--- a/core/java/android/accounts/ChooseAccountActivity.java
+++ b/core/java/android/accounts/ChooseAccountActivity.java
@@ -15,23 +15,39 @@
*/
package android.accounts;
-import android.app.ListActivity;
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcelable;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-import android.view.View;
import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+import com.android.internal.R;
+
+import java.util.HashMap;
/**
* @hide
*/
-public class ChooseAccountActivity extends ListActivity {
+public class ChooseAccountActivity extends Activity {
+
private static final String TAG = "AccountManager";
+
private Parcelable[] mAccounts = null;
private AccountManagerResponse mAccountManagerResponse = null;
private Bundle mResult;
+ private HashMap<String, AuthenticatorDescription> mTypeToAuthDescription
+ = new HashMap<String, AuthenticatorDescription>();
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -47,16 +63,51 @@
return;
}
- String[] mAccountNames = new String[mAccounts.length];
+ getAuthDescriptions();
+
+ AccountInfo[] mAccountInfos = new AccountInfo[mAccounts.length];
for (int i = 0; i < mAccounts.length; i++) {
- mAccountNames[i] = ((Account) mAccounts[i]).name;
+ mAccountInfos[i] = new AccountInfo(((Account) mAccounts[i]).name,
+ getDrawableForType(((Account) mAccounts[i]).type));
}
- // Use an existing ListAdapter that will map an array
- // of strings to TextViews
- setListAdapter(new ArrayAdapter<String>(this,
- android.R.layout.simple_list_item_1, mAccountNames));
- getListView().setTextFilterEnabled(true);
+ setContentView(R.layout.choose_account);
+
+ // Setup the list
+ ListView list = (ListView) findViewById(android.R.id.list);
+ // Use an existing ListAdapter that will map an array of strings to TextViews
+ list.setAdapter(new AccountArrayAdapter(this,
+ android.R.layout.simple_list_item_1, mAccountInfos));
+ list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ list.setTextFilterEnabled(true);
+ list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
+ onListItemClick((ListView)parent, v, position, id);
+ }
+ });
+ }
+
+ private void getAuthDescriptions() {
+ for(AuthenticatorDescription desc : AccountManager.get(this).getAuthenticatorTypes()) {
+ mTypeToAuthDescription.put(desc.type, desc);
+ }
+ }
+
+ private Drawable getDrawableForType(String accountType) {
+ Drawable icon = null;
+ if(mTypeToAuthDescription.containsKey(accountType)) {
+ try {
+ AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
+ Context authContext = createPackageContext(desc.packageName, 0);
+ icon = authContext.getResources().getDrawable(desc.iconId);
+ } catch (PackageManager.NameNotFoundException e) {
+ // Nothing we can do much here, just log
+ if (Log.isLoggable(TAG, Log.WARN)) {
+ Log.w(TAG, "No icon for account type " + accountType);
+ }
+ }
+ }
+ return icon;
}
protected void onListItemClick(ListView l, View v, int position, long id) {
@@ -79,4 +130,51 @@
}
super.finish();
}
+
+ private static class AccountInfo {
+ final String name;
+ final Drawable drawable;
+
+ AccountInfo(String name, Drawable drawable) {
+ this.name = name;
+ this.drawable = drawable;
+ }
+ }
+
+ private static class ViewHolder {
+ ImageView icon;
+ TextView text;
+ }
+
+ private static class AccountArrayAdapter extends ArrayAdapter<AccountInfo> {
+ private LayoutInflater mLayoutInflater;
+ private AccountInfo[] mInfos;
+
+ public AccountArrayAdapter(Context context, int textViewResourceId, AccountInfo[] infos) {
+ super(context, textViewResourceId, infos);
+ mInfos = infos;
+ mLayoutInflater = (LayoutInflater) context.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ViewHolder holder;
+
+ if (convertView == null) {
+ convertView = mLayoutInflater.inflate(R.layout.choose_account_row, null);
+ holder = new ViewHolder();
+ holder.text = (TextView) convertView.findViewById(R.id.account_row_text);
+ holder.icon = (ImageView) convertView.findViewById(R.id.account_row_icon);
+ convertView.setTag(holder);
+ } else {
+ holder = (ViewHolder) convertView.getTag();
+ }
+
+ holder.text.setText(mInfos[position].name);
+ holder.icon.setImageDrawable(mInfos[position].drawable);
+
+ return convertView;
+ }
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index d5b0042..2959fc0 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -670,6 +670,26 @@
return false;
}
+ /**
+ * Send a AT command message to the headset.
+ * @param device Remote Bluetooth Device
+ * @param cmd The String to send.
+ * @hide
+ */
+ public void sendAtCommand(BluetoothDevice device, String command) {
+ if (DBG) log("sendAtCommand()");
+ if (mService != null && isEnabled() && isValidDevice(device)) {
+ try {
+ mService.sendAtCommand(device, command);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
diff --git a/core/java/android/bluetooth/IBluetoothHeadset.aidl b/core/java/android/bluetooth/IBluetoothHeadset.aidl
index e952193..3c6cf77 100644
--- a/core/java/android/bluetooth/IBluetoothHeadset.aidl
+++ b/core/java/android/bluetooth/IBluetoothHeadset.aidl
@@ -50,4 +50,6 @@
boolean startVirtualVoiceCall(in BluetoothDevice device);
boolean stopVirtualVoiceCall(in BluetoothDevice device);
+
+ void sendAtCommand(in BluetoothDevice device, String urc);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 6f23215..4f21265 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1801,7 +1801,6 @@
SCREEN_BRIGHTNESS,
SCREEN_BRIGHTNESS_MODE,
VIBRATE_ON,
- NOTIFICATIONS_USE_RING_VOLUME,
MODE_RINGER,
MODE_RINGER_STREAMS_AFFECTED,
MUTE_STREAMS_AFFECTED,
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 811a633..b41687e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5117,7 +5117,16 @@
removeCallbacks(mPendingCheckForLongPress);
}
}
-
+
+ /**
+ * Remove the pending click action
+ */
+ private void removePerformClickCallback() {
+ if (mPerformClick != null) {
+ removeCallbacks(mPerformClick);
+ }
+ }
+
/**
* Remove the prepress detection timer.
*/
@@ -7579,6 +7588,7 @@
removeUnsetPressCallback();
removeLongPressCallback();
+ removePerformClickCallback();
destroyDrawingCache();
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 518ba69..0bf0eab 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -571,7 +571,6 @@
* A combination of built in zoom controls enabled
* and on screen zoom controls disabled allows for pinch to zoom
* to work without the on screen controls
- * @hide
*/
public void setDisplayZoomControls(boolean enabled) {
mDisplayZoomControls = enabled;
@@ -580,7 +579,6 @@
/**
* Returns true if the on screen zoom buttons are being used.
- * @hide
*/
public boolean getDisplayZoomControls() {
return mDisplayZoomControls;
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 59a239a..6e1a6fc 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -1087,7 +1087,7 @@
*/
/* package */ void setTextAndKeepSelection(String text) {
mPreChange = text.toString();
- Editable edit = (Editable) getText();
+ Editable edit = getText();
int selStart = Selection.getSelectionStart(edit);
int selEnd = Selection.getSelectionEnd(edit);
mInSetTextAndKeepSelection = true;
@@ -1097,6 +1097,12 @@
if (selEnd > newLength) selEnd = newLength;
Selection.setSelection(edit, selStart, selEnd);
mInSetTextAndKeepSelection = false;
+ InputMethodManager imm = InputMethodManager.peekInstance();
+ if (imm != null && imm.isActive(this)) {
+ // Since the text has changed, do not allow the IME to replace the
+ // existing text as though it were a completion.
+ imm.restartInput(this);
+ }
updateCachedTextfield();
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index fad0a4f..aac57ed 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4791,8 +4791,6 @@
return super.onKeyUp(keyCode, event);
}
- hideControllers();
-
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER:
mDPadCenterIsDown = false;
@@ -7126,6 +7124,13 @@
}
super.onFocusChanged(focused, direction, previouslyFocusedRect);
+
+ // After super.onFocusChanged so that this TextView is registered and can ask for the IME
+ // Showing the IME while focus is moved using the D-Pad is a bad idea, however this does
+ // not happen in that case (using the arrows on a bluetooth keyboard).
+ if (focused) {
+ onTouchFinished(null);
+ }
}
private int getLastTapPosition() {
@@ -7268,6 +7273,9 @@
return superResult;
}
+ final boolean touchIsFinished = action == MotionEvent.ACTION_UP && !mIgnoreActionUpEvent &&
+ isFocused();
+
if ((mMovement != null || onCheckIsTextEditor()) && isEnabled()
&& mText instanceof Spannable && mLayout != null) {
boolean handled = false;
@@ -7283,8 +7291,7 @@
handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
}
- if (mLinksClickable && mAutoLinkMask != 0 && mTextIsSelectable &&
- action == MotionEvent.ACTION_UP && !mIgnoreActionUpEvent && isFocused()) {
+ if (mLinksClickable && mAutoLinkMask != 0 && mTextIsSelectable && touchIsFinished) {
// The LinkMovementMethod which should handle taps on links has not been installed
// to support text selection. We reproduce its behavior here to open links.
ClickableSpan[] links = ((Spannable) mText).getSpans(getSelectionStart(),
@@ -7306,26 +7313,15 @@
mSelectionModifierCursorController.updatePosition();
}
}
- if (action == MotionEvent.ACTION_UP && !mIgnoreActionUpEvent && isFocused()) {
- InputMethodManager imm = (InputMethodManager)
- getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ if (touchIsFinished) {
CommitSelectionReceiver csr = null;
if (getSelectionStart() != oldSelStart || getSelectionEnd() != oldSelEnd ||
didTouchFocusSelect()) {
csr = new CommitSelectionReceiver(oldSelStart, oldSelEnd);
}
- if (!mTextIsSelectable) {
- // Show the IME, except when selecting in read-only text.
- handled |= imm.showSoftInput(this, 0, csr) && (csr != null);
- }
-
- stopSelectionActionMode();
- boolean selectAllGotFocus = mSelectAllOnFocus && mTouchFocusSelected;
- if (hasInsertionController() && !selectAllGotFocus) {
- getInsertionController().show();
- }
+ handled = onTouchFinished(csr);
}
}
@@ -7337,6 +7333,35 @@
return superResult;
}
+ /** Shows the IME if applicable, ends selection mode and displays the selection controller.
+ *
+ * This method is called at the end of a touch event, when the finger is lifted up.
+ * It is also called when the TextField gains focus indirectly through a dispatched event from
+ * one of its parents. We want to have the same behavior in that case.
+ *
+ * @param csr A (possibly null) callback called if the IME has been displayed
+ * @return true if the event was properly sent to the csr
+ */
+ private boolean onTouchFinished(CommitSelectionReceiver csr) {
+ boolean handled = false;
+
+ // Show the IME, except when selecting in read-only text.
+ if (!mTextIsSelectable) {
+ final InputMethodManager imm = (InputMethodManager)
+ getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+
+ handled = imm.showSoftInput(this, 0, csr) && (csr != null);
+ }
+
+ stopSelectionActionMode();
+ boolean selectAllGotFocus = mSelectAllOnFocus && mTouchFocusSelected;
+ if (hasInsertionController() && !selectAllGotFocus) {
+ getInsertionController().show();
+ }
+
+ return handled;
+ }
+
private void prepareCursorControllers() {
boolean windowSupportsHandles = false;
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 6a7db1f0..bb23173 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -301,6 +301,8 @@
final Runnable mHide = new Runnable() {
public void run() {
handleHide();
+ // Don't do this in handleHide() because it is also invoked by handleShow()
+ mNextView = null;
}
};
@@ -407,7 +409,6 @@
}
mView = null;
- mNextView = null;
}
}
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 08ce256..25d3aca 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1341,7 +1341,9 @@
<activity android:name="android.accounts.ChooseAccountActivity"
android:excludeFromRecents="true"
- android:exported="true">
+ android:exported="true"
+ android:theme="@android:style/Theme.Holo.Dialog"
+ android:label="@string/choose_account_label">
</activity>
<activity android:name="android.accounts.GrantCredentialsPermissionActivity"
diff --git a/core/res/res/layout/choose_account.xml b/core/res/res/layout/choose_account.xml
new file mode 100644
index 0000000..c37a949
--- /dev/null
+++ b/core/res/res/layout/choose_account.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/layout/list_content.xml
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingLeft="16dip"
+ android:paddingRight="16dip">
+
+ <ListView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/list"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:drawSelectorOnTop="false"
+ android:scrollbarAlwaysDrawVerticalTrack="true" />
+
+</LinearLayout>
diff --git a/core/res/res/layout/choose_account_row.xml b/core/res/res/layout/choose_account_row.xml
new file mode 100644
index 0000000..33764a3
--- /dev/null
+++ b/core/res/res/layout/choose_account_row.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:paddingLeft="16dip"
+ android:paddingRight="16dip"
+ android:orientation="horizontal" >
+
+ <ImageView android:id="@+id/account_row_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:paddingRight="8dip" />
+
+ <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/account_row_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:gravity="center_vertical"
+ android:minHeight="?android:attr/listPreferredItemHeight" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 46e45db..496e254 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2684,4 +2684,7 @@
<string name="vpn_notification_title_disconnected"><xliff:g id="profilename" example="Home PPTP">%s</xliff:g> VPN disconnected</string>
<!-- Message of the VPN service notification: Hint to reconnect VPN [CHAR LIMIT=NONE] -->
<string name="vpn_notification_hint_disconnected">Touch to reconnect to a VPN.</string>
+
+ <!-- Choose Account Activity label -->
+ <string name="choose_account_label">Select an account</string>
</resources>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
index 3d5588c..fb8b5ce 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -78,7 +78,7 @@
public int mWifiState;
public NetworkInfo mWifiNetworkInfo;
public String mBssid;
- public String mPowerSsid = "GoogleGuest"; //Default power SSID
+ public String mPowerSsid = "opennet"; //Default power SSID
private Context mContext;
public boolean scanResultAvailable = false;
diff --git a/docs/html/guide/topics/graphics/animation.jd b/docs/html/guide/topics/graphics/animation.jd
index c977d51..83a4e1d 100644
--- a/docs/html/guide/topics/graphics/animation.jd
+++ b/docs/html/guide/topics/graphics/animation.jd
@@ -13,7 +13,7 @@
<li><a href="#object-animator">Animating with ObjectAnimator</a></li>
- <li><a href="#type-evaluator">Using the TypeEvaluator</a></li>
+ <li><a href="#type-evaluator">Using a TypeEvaluator</a></li>
<li><a href="#interpolators">Using interpolators</a></li>
@@ -60,7 +60,7 @@
<p>The Android system provides a flexible animation system that allows you to animate
almost anything, either programmatically or declaratively with XML. There are two
- animation systems that you can choose from: <a href="property-animation">property
+ animation systems that you can choose from: <a href="#property-animation">property
animation</a> and <a href="#view-animation">view animation</a>. You can use whichever
system that matches your needs, but use only one system for each object that you
are animating.</p>
@@ -91,7 +91,7 @@
<p>Most of the property animation system's features can be found in
{@link android.animation android.animation}. Because the
- <a href="#view-animation>view animation</a> system already
+ <a href="#view-animation">view animation</a> system already
defines many interpolators in {@link android.view.animation android.view.animation},
you will use those to define your animation's interpolation in the property animation
system as well.
@@ -163,7 +163,7 @@
<p>The Android system provides a set of common interpolators in
{@link android.view.animation android.view.animation}. If none of these suits your needs, you
can implement the {@link android.animation.TimeInterpolator} interface and create
- your own. See <a href="#interpolators">Interpolators</a> for more information on
+ your own. See <a href="#interpolators">Using interpolators</a> for more information on
how to write a custom interpolator.</p>
</dd>
</dl>
@@ -286,14 +286,13 @@
android.animation.AnimatorListenerAdapter} for just the {@link
android.animation.Animator.AnimatorListener#onAnimationEnd onAnimationEnd()}
callback:</p>
+
<pre>ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
fadeAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
balls.remove(((ObjectAnimator)animation).getTarget());
-}
-
-</pre>
+}</pre>
<h3 id="object-animator">Animating with ObjectAnimator</h3>
@@ -308,11 +307,9 @@
<p>Instantiating an {@link android.animation.ObjectAnimator} is similar to a {@link
android.animation.ValueAnimator}, but you also specify the object and that object's
property (as a String) that you want to animate:</p>
- <pre>
-ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
+ <pre>ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
anim.setDuration(1000);
-anim.start();
-</pre>
+anim.start();</pre>
<p>To have the {@link android.animation.ObjectAnimator} update properties correctly,
you must do the following:</p>
@@ -355,7 +352,7 @@
</li>
</ul>
- <h3 id="type-evaluator">Using the TypeEvaluator</h3>
+ <h3 id="type-evaluator">Using a TypeEvaluator</h3>
<p>If you want to animate a type that is unknown to the Android system,
you can create your own evaluator by implementing the {@link
@@ -369,15 +366,13 @@
This allows the animator that you are using to return an
appropriate value for your animated property at the current point of the animation. The
{@link android.animation.FloatEvaluator} class demonstrates how to do this:</p>
- <pre>
-public class FloatEvaluator implements TypeEvaluator {
+ <pre>public class FloatEvaluator implements TypeEvaluator {
public Object evaluate(float fraction, Object startValue, Object endValue) {
float startFloat = ((Number) startValue).floatValue();
return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
}
-}
-</pre>
+}</pre>
<p class="note"><strong>Note:</strong> When {@link android.animation.ValueAnimator} (or
{@link android.animation.ObjectAnimator}) runs, it calculates a current elapsed
@@ -387,7 +382,7 @@
parameter, so you do not have to take into account the interpolator
when calculating animated values.</p>
- <h3 id="interpolators">Using Interpolators</h3>
+ <h3 id="interpolators">Using interpolators</h3>
<p>An interpolator define how specific values in an animation are
calculated as a function of time. For example, you can specify animations to happen
@@ -414,12 +409,12 @@
<p><strong>AccelerateDecelerateInterpolator</strong></p>
<pre>public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
- }</pre>
+}</pre>
<p><strong>LinearInterpolator</strong></p>
<pre>public float getInterpolation(float input) {
return input;
- }</pre>
+}</pre>
<p>The following table represents the approximate values that are calculated by these
interpolators for an animation that lasts 1000ms:</p>
@@ -488,7 +483,7 @@
{@link android.view.animation.LinearInterpolator} between 200ms and 600ms and slower
between 600ms and 1000ms.</p>
- <h3 id="keyframes">Specifying Keyframes</h3>
+ <h3 id="keyframes">Specifying keyframes</h3>
<p>A {@link android.animation.Keyframe} object consists of a time/value pair that lets
you define a specific state at a specific time of an animation. Each keyframe can also
@@ -505,19 +500,18 @@
object, you can obtain an animator by passing in the {@link
android.animation.PropertyValuesHolder} object and the object to animate. The following
code snippet demonstrates how to do this:</p>
- <pre>
- Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
- Keyframe kf1 = Keyframe.ofFloat(.9999f, 360f);
- Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
- PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
- ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation)
- rotationAnim.setDuration(5000ms);
-
-</pre>For a more complete example on how to use keyframes, see the <a href=
+ <pre>Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
+Keyframe kf1 = Keyframe.ofFloat(.9999f, 360f);
+Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
+PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
+ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation)
+rotationAnim.setDuration(5000ms);
+</pre>
+<p>For a more complete example on how to use keyframes, see the <a href=
"{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/MultiPropertyAnimation.html">
- MultiPropertyAnimation</a> sample in APIDemos.
+ MultiPropertyAnimation</a> sample in APIDemos.</p>
- <h3 id="choreography">Choreographing multiple animations with Animator Sets</h3>
+ <h3 id="choreography">Choreographing multiple animations with AnimatorSet</h3>
<p>In many cases, you want to play an animation that depends on when another animation
starts or finishes. The Android system lets you bundle animations together into an
@@ -559,7 +553,7 @@
<h3 id="declaring-xml">Declaring animations in XML</h3>
- <p>As with <a href="view-animation">view animation</a>, you can declare property animations with
+ <p>As with <a href="#view-animation">view animation</a>, you can declare property animations with
XML instead of doing it programmatically. The following Android classes also have XML
declaration support with the following XML tags:</p>
@@ -639,14 +633,13 @@
android:propertyName="y"
android:duration="500"
android:valueTo="300"
- android:valueType="int" >
- </set>
- <objectAnimator
- android:propertyName="alpha"
- android:duration="500"
- android:valueTo="0f"/>
- </set>
-</pre>
+ android:valueType="int"/>
+ </set>
+ <objectAnimator
+ android:propertyName="alpha"
+ android:duration="500"
+ android:valueTo="0f"/>
+</set></pre>
<p>In order to run this animation, you must inflate the XML resources in your code to
an {@link android.animation.AnimatorSet} object, and then set the target objects for all of
@@ -698,40 +691,38 @@
<p>The following XML from one of the ApiDemos is used to stretch, then simultaneously
spin and rotate a View object.</p>
- <pre>
-<set android:shareInterpolator="false">
- <scale
- android:interpolator="@android:anim/accelerate_decelerate_interpolator"
- android:fromXScale="1.0"
- android:toXScale="1.4"
- android:fromYScale="1.0"
- android:toYScale="0.6"
- android:pivotX="50%"
- android:pivotY="50%"
- android:fillAfter="false"
- android:duration="700" />
- <set android:interpolator="@android:anim/decelerate_interpolator">
- <scale
- android:fromXScale="1.4"
- android:toXScale="0.0"
- android:fromYScale="0.6"
- android:toYScale="0.0"
- android:pivotX="50%"
- android:pivotY="50%"
- android:startOffset="700"
- android:duration="400"
- android:fillBefore="false" />
- <rotate
- android:fromDegrees="0"
- android:toDegrees="-45"
- android:toYScale="0.0"
- android:pivotX="50%"
- android:pivotY="50%"
- android:startOffset="700"
- android:duration="400" />
- </set>
-</set>
-</pre>
+ <pre><set android:shareInterpolator="false">
+ <scale
+ android:interpolator="@android:anim/accelerate_decelerate_interpolator"
+ android:fromXScale="1.0"
+ android:toXScale="1.4"
+ android:fromYScale="1.0"
+ android:toYScale="0.6"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:fillAfter="false"
+ android:duration="700" />
+ <set android:interpolator="@android:anim/decelerate_interpolator">
+ <scale
+ android:fromXScale="1.4"
+ android:toXScale="0.0"
+ android:fromYScale="0.6"
+ android:toYScale="0.0"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:startOffset="700"
+ android:duration="400"
+ android:fillBefore="false" />
+ <rotate
+ android:fromDegrees="0"
+ android:toDegrees="-45"
+ android:toYScale="0.0"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:startOffset="700"
+ android:duration="400" />
+ </set>
+</set></pre>
<p>Screen coordinates (not used in this example) are (0,0) at the upper left hand
corner, and increase as you go down and to the right.</p>
@@ -805,8 +796,7 @@
image to a View and then called to play. Here's an example Activity, in which the
animation is added to an {@link android.widget.ImageView} and then animated when the
screen is touched:</p>
- <pre>
-AnimationDrawable rocketAnimation;
+ <pre>AnimationDrawable rocketAnimation;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -823,8 +813,7 @@
return true;
}
return super.onTouchEvent(event);
-}
-</pre>
+}</pre>
<p>It's important to note that the <code>start()</code> method called on the
AnimationDrawable cannot be called during the <code>onCreate()</code> method of your
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 74cdf80..3dcfe88 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -212,7 +212,7 @@
for (int ct=0; ct < d.length; ct++) {
i[ct] = d[ct].getID();
}
- copy1DRangeFrom(0, mType.getCount(), i);
+ copy1DRangeFromUnchecked(0, mType.getCount(), i);
}
private void validateBitmapFormat(Bitmap b) {
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index f8daa4f..3251c28 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -305,6 +305,8 @@
void restorePatchedDataPointer(BufferInfo *info);
+ status_t applyRotation();
+
OMXCodec(const OMXCodec &);
OMXCodec &operator=(const OMXCodec &);
};
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index ec88bb2..3d7dbf9 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -22,9 +22,6 @@
#include <utils/Log.h>
#include <utils/threads.h>
#include <core/SkBitmap.h>
-#include <core/SkCanvas.h>
-#include <core/SkDevice.h>
-#include <core/SkScalar.h>
#include <media/mediametadataretriever.h>
#include <private/media/VideoFrame.h>
@@ -136,6 +133,61 @@
process_media_retriever_call(env, retriever->setDataSource(fd, offset, length), "java/lang/RuntimeException", "setDataSource failed");
}
+template<typename T>
+static void rotate0(T* dst, const T* src, size_t width, size_t height)
+{
+ memcpy(dst, src, width * height * sizeof(T));
+}
+
+template<typename T>
+static void rotate90(T* dst, const T* src, size_t width, size_t height)
+{
+ for (size_t i = 0; i < height; ++i) {
+ for (size_t j = 0; j < width; ++j) {
+ dst[j * height + height - 1 - i] = src[i * width + j];
+ }
+ }
+}
+
+template<typename T>
+static void rotate180(T* dst, const T* src, size_t width, size_t height)
+{
+ for (size_t i = 0; i < height; ++i) {
+ for (size_t j = 0; j < width; ++j) {
+ dst[(height - 1 - i) * width + width - 1 - j] = src[i * width + j];
+ }
+ }
+}
+
+template<typename T>
+static void rotate270(T* dst, const T* src, size_t width, size_t height)
+{
+ for (size_t i = 0; i < height; ++i) {
+ for (size_t j = 0; j < width; ++j) {
+ dst[(width - 1 - j) * height + i] = src[i * width + j];
+ }
+ }
+}
+
+template<typename T>
+static void rotate(T *dst, const T *src, size_t width, size_t height, int angle)
+{
+ switch (angle) {
+ case 0:
+ rotate0(dst, src, width, height);
+ break;
+ case 90:
+ rotate90(dst, src, width, height);
+ break;
+ case 180:
+ rotate180(dst, src, width, height);
+ break;
+ case 270:
+ rotate270(dst, src, width, height);
+ break;
+ }
+}
+
static jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env, jobject thiz, jlong timeUs, jint option)
{
LOGV("getFrameAtTime: %lld us option: %d", timeUs, option);
@@ -166,30 +218,33 @@
fields.createConfigMethod,
SkBitmap::kRGB_565_Config);
+ size_t width, height;
+ if (videoFrame->mRotationAngle == 90 || videoFrame->mRotationAngle == 270) {
+ width = videoFrame->mDisplayHeight;
+ height = videoFrame->mDisplayWidth;
+ } else {
+ width = videoFrame->mDisplayWidth;
+ height = videoFrame->mDisplayHeight;
+ }
+
jobject jBitmap = env->CallStaticObjectMethod(
fields.bitmapClazz,
fields.createBitmapMethod,
- videoFrame->mDisplayWidth,
- videoFrame->mDisplayHeight,
+ width,
+ height,
config);
+
SkBitmap *bitmap =
(SkBitmap *) env->GetIntField(jBitmap, fields.nativeBitmap);
bitmap->lockPixels();
-
- memcpy((uint8_t*)bitmap->getPixels(),
- (uint8_t*)videoFrame + sizeof(VideoFrame), videoFrame->mSize);
-
+ rotate((uint16_t*)bitmap->getPixels(),
+ (uint16_t*)((char*)videoFrame + sizeof(VideoFrame)),
+ videoFrame->mDisplayWidth,
+ videoFrame->mDisplayHeight,
+ videoFrame->mRotationAngle);
bitmap->unlockPixels();
- if (videoFrame->mRotationAngle != 0) {
- SkDevice device(*bitmap);
- SkCanvas canvas(&device);
- canvas.rotate((SkScalar) (videoFrame->mRotationAngle * 1.0));
- canvas.drawBitmap(*bitmap, 0, 0);
- }
-
- LOGV("Return a new bitmap constructed with the rotation matrix");
return jBitmap;
}
@@ -288,22 +343,6 @@
jniThrowException(env, "java/lang/RuntimeException", "Can't find android/graphics/Bitmap");
return;
}
-#if USE_PRIVATE_NATIVE_BITMAP_CONSTUCTOR
- fields.bitmapConstructor = env->GetMethodID(fields.bitmapClazz, "<init>", "(I[BZ[BI)V");
- if (fields.bitmapConstructor == NULL) {
- jniThrowException(env, "java/lang/RuntimeException", "Can't find Bitmap constructor");
- return;
- }
- fields.createBitmapRotationMethod =
- env->GetStaticMethodID(fields.bitmapClazz, "createBitmap",
- "(Landroid/graphics/Bitmap;IIIILandroid/graphics/Matrix;Z)"
- "Landroid/graphics/Bitmap;");
- if (fields.createBitmapRotationMethod == NULL) {
- jniThrowException(env, "java/lang/RuntimeException",
- "Can't find Bitmap.createBitmap method");
- return;
- }
-#else
fields.createBitmapMethod =
env->GetStaticMethodID(fields.bitmapClazz, "createBitmap",
"(IILandroid/graphics/Bitmap$Config;)"
@@ -333,7 +372,6 @@
"Can't find Bitmap$Config.nativeToConfig(int) method");
return;
}
-#endif
}
static void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobject thiz)
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 11ac56c..89b3dab 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -378,14 +378,11 @@
}
void AwesomePlayer::reset() {
- LOGI("reset");
-
Mutex::Autolock autoLock(mLock);
reset_l();
}
void AwesomePlayer::reset_l() {
- LOGI("reset_l");
mDisplayWidth = 0;
mDisplayHeight = 0;
@@ -411,10 +408,6 @@
}
}
- if (mFlags & PREPARING) {
- LOGI("waiting until preparation is completes.");
- }
-
while (mFlags & PREPARING) {
mPreparedCondition.wait(mLock);
}
@@ -438,8 +431,6 @@
}
mAudioSource.clear();
- LOGI("audio source cleared");
-
mTimeSource = NULL;
delete mAudioPlayer;
@@ -480,8 +471,6 @@
IPCThreadState::self()->flushCommands();
}
- LOGI("video source cleared");
-
mDurationUs = -1;
mFlags = 0;
mExtractorFlags = 0;
@@ -498,8 +487,6 @@
mFileSource.clear();
mBitrate = -1;
-
- LOGI("reset_l completed");
}
void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index d842f65..94694a3 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1680,6 +1680,33 @@
return OK;
}
+status_t OMXCodec::applyRotation() {
+ sp<MetaData> meta = mSource->getFormat();
+
+ int32_t rotationDegrees;
+ if (!meta->findInt32(kKeyRotation, &rotationDegrees)) {
+ rotationDegrees = 0;
+ }
+
+ uint32_t transform;
+ switch (rotationDegrees) {
+ case 0: transform = 0; break;
+ case 90: transform = HAL_TRANSFORM_ROT_90; break;
+ case 180: transform = HAL_TRANSFORM_ROT_180; break;
+ case 270: transform = HAL_TRANSFORM_ROT_270; break;
+ default: transform = 0; break;
+ }
+
+ status_t err = OK;
+
+ if (transform) {
+ err = native_window_set_buffers_transform(
+ mNativeWindow.get(), transform);
+ }
+
+ return err;
+}
+
status_t OMXCodec::allocateOutputBuffersFromNativeWindow() {
// Get the number of buffers needed.
OMX_PARAM_PORTDEFINITIONTYPE def;
@@ -1713,6 +1740,11 @@
return err;
}
+ err = applyRotation();
+ if (err != OK) {
+ return err;
+ }
+
// Set up the native window.
// XXX TODO: Get the gralloc usage flags from the OMX plugin!
err = native_window_set_usage(
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 5981139..27c8aea 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -71,6 +71,9 @@
<string name="def_lock_sound" translatable="false">/system/media/audio/ui/Lock.ogg</string>
<string name="def_unlock_sound" translatable="false">/system/media/audio/ui/Unlock.ogg</string>
+ <!-- Notifications use ringer volume -->
+ <bool name="def_notifications_use_ring_volume">true</bool>
+
<!-- Default for Settings.System.VIBRATE_IN_SILENT -->
<bool name="def_vibrate_in_silent">true</bool>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index bc7473e..580113c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1168,6 +1168,11 @@
loadBooleanSetting(stmt, Settings.System.USE_PTP_INTERFACE,
R.bool.def_use_ptp_interface);
+
+ // Set notification volume to follow ringer volume by default
+ loadBooleanSetting(stmt, Settings.System.NOTIFICATIONS_USE_RING_VOLUME,
+ R.bool.def_notifications_use_ring_volume);
+
} finally {
if (stmt != null) stmt.close();
}
diff --git a/services/java/com/android/server/ScreenRotationAnimation.java b/services/java/com/android/server/ScreenRotationAnimation.java
index 2ad9cbe..bef64b3 100644
--- a/services/java/com/android/server/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/ScreenRotationAnimation.java
@@ -23,6 +23,8 @@
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.Slog;
@@ -132,9 +134,11 @@
}
if (screenshot != null) {
- c.drawBitmap(screenshot, 0, 0, new Paint(0));
+ Paint paint = new Paint(0);
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
+ c.drawBitmap(screenshot, 0, 0, paint);
} else {
- c.drawColor(Color.GREEN);
+ c.drawColor(Color.GREEN, PorterDuff.Mode.SRC);
}
mSurface.unlockCanvasAndPost(c);
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 2af291d..d2a1786 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -680,6 +680,7 @@
// stop intercepting input
mDragState.unregister();
+ mInputMonitor.setUpdateInputWindowsNeededLw();
mInputMonitor.updateInputWindowsLw();
// Retain the parameters of any deferred rotation operation so
@@ -2401,7 +2402,8 @@
boolean focusChanged = false;
if (win.canReceiveKeys()) {
- focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS);
+ focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
+ false /*updateInputWindows*/);
if (focusChanged) {
imMayMove = false;
}
@@ -2418,9 +2420,10 @@
//dump();
if (focusChanged) {
- finishUpdateFocusedWindowAfterAssignLayersLocked();
+ finishUpdateFocusedWindowAfterAssignLayersLocked(false /*updateInputWindows*/);
}
-
+ mInputMonitor.updateInputWindowsLw();
+
if (localLOGV) Slog.v(
TAG, "New client " + client.asBinder()
+ ": window=" + win);
@@ -2496,8 +2499,10 @@
win.mExiting = true;
win.mRemoveOnExit = true;
mLayoutNeeded = true;
- updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
+ updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+ false /*updateInputWindows*/);
performLayoutAndPlaceSurfacesLocked();
+ mInputMonitor.updateInputWindowsLw();
if (win.mAppToken != null) {
win.mAppToken.updateReportedVisibilityLocked();
}
@@ -2515,7 +2520,7 @@
&& updateOrientationFromAppTokensLocked(false)) {
mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
}
- updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
+ updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Binder.restoreCallingIdentity(origId);
}
@@ -2613,6 +2618,7 @@
}
}
+ mInputMonitor.setUpdateInputWindowsNeededLw();
mInputMonitor.updateInputWindowsLw();
}
@@ -2863,6 +2869,7 @@
outSurface.release();
}
} catch (Exception e) {
+ mInputMonitor.setUpdateInputWindowsNeededLw();
mInputMonitor.updateInputWindowsLw();
Slog.w(TAG, "Exception thrown when creating surface for client "
@@ -2950,7 +2957,8 @@
if (focusMayChange) {
//System.out.println("Focus may change: " + win.mAttrs.getTitle());
- if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
+ if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+ false /*updateInputWindows*/)) {
imMayMove = false;
}
//System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
@@ -3006,6 +3014,7 @@
inTouchMode = mInTouchMode;
+ mInputMonitor.setUpdateInputWindowsNeededLw();
mInputMonitor.updateInputWindowsLw();
}
@@ -3378,7 +3387,8 @@
if (changed) {
mLayoutNeeded = true;
performLayoutAndPlaceSurfacesLocked();
- updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
+ updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
+ false /*updateInputWindows*/);
}
if (delayed) {
@@ -3388,6 +3398,7 @@
}
}
+ mInputMonitor.setUpdateInputWindowsNeededLw();
mInputMonitor.updateInputWindowsLw();
} else {
Slog.w(TAG, "Attempted to remove non-existing token: " + token);
@@ -3707,7 +3718,7 @@
if (moveFocusNow && changed) {
final long origId = Binder.clearCallingIdentity();
- updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
+ updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Binder.restoreCallingIdentity(origId);
}
}
@@ -3882,7 +3893,8 @@
ttoken.updateLayers();
}
- updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
+ updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+ true /*updateInputWindows*/);
mLayoutNeeded = true;
performLayoutAndPlaceSurfacesLocked();
Binder.restoreCallingIdentity(origId);
@@ -4042,12 +4054,13 @@
if (changed) {
mLayoutNeeded = true;
+ mInputMonitor.setUpdateInputWindowsNeededLw();
if (performLayout) {
- updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
+ updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+ false /*updateInputWindows*/);
performLayoutAndPlaceSurfacesLocked();
- } else {
- mInputMonitor.updateInputWindowsLw();
}
+ mInputMonitor.updateInputWindowsLw();
}
}
@@ -4302,7 +4315,7 @@
if (mFocusedApp == wtoken) {
if (DEBUG_FOCUS) Slog.v(TAG, "Removing focused app token:" + wtoken);
mFocusedApp = null;
- updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
+ updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
mInputMonitor.setFocusedAppLw(null);
}
} else {
@@ -4481,9 +4494,11 @@
reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken);
if (DEBUG_REORDER) Slog.v(TAG, "Final window list:");
if (DEBUG_REORDER) dumpWindowsLocked();
- updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
+ updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+ false /*updateInputWindows*/);
mLayoutNeeded = true;
performLayoutAndPlaceSurfacesLocked();
+ mInputMonitor.updateInputWindowsLw();
}
Binder.restoreCallingIdentity(origId);
}
@@ -4520,11 +4535,13 @@
pos = reAddAppWindowsLocked(pos, wtoken);
if (updateFocusAndLayout) {
- if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
+ if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+ false /*updateInputWindows*/)) {
assignLayersLocked();
}
mLayoutNeeded = true;
performLayoutAndPlaceSurfacesLocked();
+ mInputMonitor.updateInputWindowsLw();
}
}
@@ -4550,11 +4567,13 @@
}
}
- if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
+ if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+ false /*updateInputWindows*/)) {
assignLayersLocked();
}
mLayoutNeeded = true;
performLayoutAndPlaceSurfacesLocked();
+ mInputMonitor.updateInputWindowsLw();
//dump();
}
@@ -5797,6 +5816,9 @@
// When true, input dispatch proceeds normally. Otherwise all events are dropped.
private boolean mInputDispatchEnabled = true;
+ // When true, need to call updateInputWindowsLw().
+ private boolean mUpdateInputWindowsNeeded = true;
+
// Temporary list of windows information to provide to the input dispatcher.
private InputWindowList mTempInputWindows = new InputWindowList();
@@ -5891,8 +5913,17 @@
inputWindow.touchableRegion.setEmpty();
}
+ public void setUpdateInputWindowsNeededLw() {
+ mUpdateInputWindowsNeeded = true;
+ }
+
/* Updates the cached window information provided to the input dispatcher. */
public void updateInputWindowsLw() {
+ if (!mUpdateInputWindowsNeeded) {
+ return;
+ }
+ mUpdateInputWindowsNeeded = false;
+
// Populate the input window list with information about all of the windows that
// could potentially receive input.
// As an optimization, we could try to prune the list of windows but this turns
@@ -6021,7 +6052,7 @@
/* Called when the current input focus changes.
* Layer assignment is assumed to be complete by the time this is called.
*/
- public void setInputFocusLw(WindowState newWindow) {
+ public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) {
if (DEBUG_INPUT) {
Slog.d(TAG, "Input focus has changed to " + newWindow);
}
@@ -6033,9 +6064,13 @@
// forgets to resume.
newWindow.mToken.paused = false;
}
-
+
mInputFocus = newWindow;
- updateInputWindowsLw();
+ setUpdateInputWindowsNeededLw();
+
+ if (updateInputWindows) {
+ updateInputWindowsLw();
+ }
}
}
@@ -6062,6 +6097,7 @@
}
window.paused = true;
+ setUpdateInputWindowsNeededLw();
updateInputWindowsLw();
}
}
@@ -6073,6 +6109,7 @@
}
window.paused = false;
+ setUpdateInputWindowsNeededLw();
updateInputWindowsLw();
}
}
@@ -6549,12 +6586,14 @@
// the actual drag event dispatch stuff in the dragstate
mDragState.register();
+ mInputMonitor.setUpdateInputWindowsNeededLw();
mInputMonitor.updateInputWindowsLw();
if (!mInputManager.transferTouchFocus(callingWin.mInputChannel,
mDragState.mServerChannel)) {
Slog.e(TAG, "Unable to transfer touch focus");
mDragState.unregister();
mDragState = null;
+ mInputMonitor.setUpdateInputWindowsNeededLw();
mInputMonitor.updateInputWindowsLw();
return false;
}
@@ -9151,6 +9190,7 @@
// !!! TODO: ANR the app that has failed to start the drag in time
if (mDragState != null) {
mDragState.unregister();
+ mInputMonitor.setUpdateInputWindowsNeededLw();
mInputMonitor.updateInputWindowsLw();
mDragState.reset();
mDragState = null;
@@ -9441,7 +9481,7 @@
}
}
- private final int performLayoutLockedInner(boolean initial) {
+ private final int performLayoutLockedInner(boolean initial, boolean updateInputWindows) {
if (!mLayoutNeeded) {
return 0;
}
@@ -9549,7 +9589,10 @@
}
// Window frames may have changed. Tell the input dispatcher about it.
- mInputMonitor.updateInputWindowsLw();
+ mInputMonitor.setUpdateInputWindowsNeededLw();
+ if (updateInputWindows) {
+ mInputMonitor.updateInputWindowsLw();
+ }
return mPolicy.finishLayoutLw();
}
@@ -9570,7 +9613,8 @@
if (mFocusMayChange) {
mFocusMayChange = false;
- updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
+ updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+ false /*updateInputWindows*/);
}
// Initialize state of exiting tokens.
@@ -9646,7 +9690,7 @@
// FIRST LOOP: Perform a layout, if needed.
if (repeats < 4) {
- changes = performLayoutLockedInner(repeats == 0);
+ changes = performLayoutLockedInner(repeats == 0, false /*updateInputWindows*/);
if (changes != 0) {
continue;
}
@@ -10103,7 +10147,8 @@
if (!moveInputMethodWindowsIfNeededLocked(true)) {
assignLayersLocked();
}
- updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES);
+ updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
+ false /*updateInputWindows*/);
mFocusMayChange = false;
}
}
@@ -10212,7 +10257,8 @@
if (mFocusMayChange) {
mFocusMayChange = false;
- if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES)) {
+ if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
+ false /*updateInputWindows*/)) {
changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
adjResult = 0;
}
@@ -10224,8 +10270,6 @@
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x"
+ Integer.toHexString(changes));
-
- mInputMonitor.updateInputWindowsLw();
} while (changes != 0);
// THIRD LOOP: Update the surfaces of all windows.
@@ -10679,8 +10723,6 @@
Slog.e(TAG, "Unhandled exception in Window Manager", e);
}
- mInputMonitor.updateInputWindowsLw();
-
Surface.closeTransaction();
if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
@@ -10810,6 +10852,8 @@
requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis());
}
+ // Finally update all input windows now that the window changes have stabilized.
+ mInputMonitor.setUpdateInputWindowsNeededLw();
mInputMonitor.updateInputWindowsLw();
setHoldScreenLocked(holdScreen != null);
@@ -10988,7 +11032,7 @@
}
}
- private boolean updateFocusedWindowLocked(int mode) {
+ private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
WindowState newFocus = computeFocusedWindowLocked();
if (mCurrentFocus != newFocus) {
// This check makes sure that we don't already have the focus
@@ -11009,7 +11053,7 @@
mLayoutNeeded = true;
}
if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
- performLayoutLockedInner(true);
+ performLayoutLockedInner(true /*initial*/, updateInputWindows);
} else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
// Client will do the layout, but we need to assign layers
// for handleNewWindowLocked() below.
@@ -11020,15 +11064,15 @@
if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
// If we defer assigning layers, then the caller is responsible for
// doing this part.
- finishUpdateFocusedWindowAfterAssignLayersLocked();
+ finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows);
}
return true;
}
return false;
}
- private void finishUpdateFocusedWindowAfterAssignLayersLocked() {
- mInputMonitor.setInputFocusLw(mCurrentFocus);
+ private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) {
+ mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
}
private WindowState computeFocusedWindowLocked() {