summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/ApplicationPackageManager.java7
-rw-r--r--core/java/android/app/ContextImpl.java6
-rw-r--r--core/java/android/app/FragmentManager.java2
-rw-r--r--core/java/android/app/IInstrumentationWatcher.aidl2
-rw-r--r--core/java/android/app/NativeActivity.java8
-rw-r--r--core/java/android/appwidget/AppWidgetHost.java20
-rw-r--r--core/java/android/bluetooth/BluetoothDeviceProfileState.java48
-rw-r--r--core/java/android/bluetooth/BluetoothSocket.java6
-rw-r--r--core/java/android/content/Context.java3
-rw-r--r--core/java/android/content/Intent.java18
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java1
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl4
-rw-r--r--core/java/android/content/pm/PackageManager.java2
-rw-r--r--core/java/android/content/pm/UserInfo.java9
-rw-r--r--core/java/android/content/res/TypedArray.java9
-rw-r--r--core/java/android/database/DatabaseUtils.java44
-rw-r--r--core/java/android/net/DhcpStateMachine.java17
-rw-r--r--core/java/android/net/EthernetDataTracker.java4
-rw-r--r--core/java/android/net/arp/ArpPeer.java42
-rw-r--r--core/java/android/os/BatteryStats.java38
-rw-r--r--core/java/android/os/INetworkManagementService.aidl6
-rw-r--r--core/java/android/os/PowerManager.java723
-rw-r--r--core/java/android/os/Trace.java3
-rw-r--r--core/java/android/provider/Settings.java3
-rwxr-xr-xcore/java/android/server/BluetoothService.java2
-rw-r--r--core/java/android/server/search/SearchManagerService.java51
-rw-r--r--core/java/android/server/search/Searchables.java47
-rw-r--r--core/java/android/text/TextDirectionHeuristics.java1
-rw-r--r--core/java/android/util/LocaleUtil.java7
-rw-r--r--core/java/android/view/Gravity.java4
-rw-r--r--core/java/android/view/LayoutInflater.java100
-rw-r--r--core/java/android/view/View.java117
-rw-r--r--core/java/android/view/ViewDebug.java39
-rw-r--r--core/java/android/view/ViewGroup.java27
-rw-r--r--core/java/android/view/ViewRootImpl.java8
-rw-r--r--core/java/android/view/ViewTreeObserver.java179
-rw-r--r--core/java/android/view/VolumePanel.java21
-rw-r--r--core/java/android/view/Window.java4
-rw-r--r--core/java/android/view/WindowManager.java8
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java232
-rw-r--r--core/java/android/webkit/BrowserFrame.java17
-rw-r--r--core/java/android/webkit/CallbackProxy.java40
-rw-r--r--core/java/android/webkit/CookieSyncManager.java4
-rw-r--r--core/java/android/webkit/MockGeolocation.java39
-rw-r--r--core/java/android/webkit/ViewStateSerializer.java10
-rw-r--r--core/java/android/webkit/WebBackForwardList.java132
-rw-r--r--core/java/android/webkit/WebBackForwardListClassic.java166
-rw-r--r--core/java/android/webkit/WebChromeClient.java12
-rw-r--r--core/java/android/webkit/WebHistoryItem.java184
-rw-r--r--core/java/android/webkit/WebHistoryItemClassic.java221
-rw-r--r--core/java/android/webkit/WebSettings.java233
-rw-r--r--core/java/android/webkit/WebSyncManager.java4
-rw-r--r--core/java/android/webkit/WebView.java29
-rw-r--r--core/java/android/webkit/WebViewClassic.java563
-rw-r--r--core/java/android/webkit/WebViewClient.java29
-rw-r--r--core/java/android/webkit/WebViewClientClassicExt.java53
-rw-r--r--core/java/android/webkit/WebViewCore.java73
-rw-r--r--core/java/android/webkit/WebViewDatabaseClassic.java1
-rw-r--r--core/java/android/webkit/WebViewProvider.java5
-rw-r--r--core/java/android/widget/CompoundButton.java39
-rw-r--r--core/java/android/widget/FrameLayout.java6
-rw-r--r--core/java/android/widget/GridView.java20
-rw-r--r--core/java/android/widget/ImageView.java10
-rw-r--r--core/java/android/widget/ProgressBar.java13
-rw-r--r--core/java/android/widget/RadioGroup.java27
-rw-r--r--core/java/android/widget/RemoteViews.java9
-rw-r--r--core/java/android/widget/Spinner.java28
-rw-r--r--core/java/android/widget/Switch.java82
-rw-r--r--core/java/android/widget/TableLayout.java6
-rw-r--r--core/java/android/widget/TableRow.java15
-rw-r--r--core/java/android/widget/TextView.java54
-rw-r--r--core/java/android/widget/Toast.java9
-rw-r--r--core/java/com/android/internal/app/IBatteryStats.aidl8
-rw-r--r--core/java/com/android/internal/appwidget/IAppWidgetHost.aidl1
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java168
-rw-r--r--core/java/com/android/internal/util/AsyncChannel.java10
-rw-r--r--core/java/com/android/internal/util/StateMachine.java311
-rw-r--r--core/java/com/android/internal/widget/LockSettingsService.java16
78 files changed, 2726 insertions, 1793 deletions
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 191a696..9a50a41 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1206,7 +1206,8 @@ final class ApplicationPackageManager extends PackageManager {
return mPM.getUsers();
} catch (RemoteException re) {
ArrayList<UserInfo> users = new ArrayList<UserInfo>();
- UserInfo primary = new UserInfo(0, "Root!", UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY);
+ UserInfo primary = new UserInfo(0, "Root!", null,
+ UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY);
users.add(primary);
return users;
}
@@ -1240,9 +1241,9 @@ final class ApplicationPackageManager extends PackageManager {
* @hide
*/
@Override
- public void updateUserName(int id, String name) {
+ public void setUserName(int id, String name) {
try {
- mPM.updateUserName(id, name);
+ mPM.setUserName(id, name);
} catch (RemoteException re) {
}
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index b902550..5e21403 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1187,6 +1187,9 @@ class ContextImpl extends Context {
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags, int userId) {
IServiceConnection sd;
+ if (conn == null) {
+ throw new IllegalArgumentException("connection is null");
+ }
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
mMainThread.getHandler(), flags);
@@ -1217,6 +1220,9 @@ class ContextImpl extends Context {
@Override
public void unbindService(ServiceConnection conn) {
+ if (conn == null) {
+ throw new IllegalArgumentException("connection is null");
+ }
if (mPackageInfo != null) {
IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
getOuterContext(), conn);
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 39e2423..b0cc37b 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1923,7 +1923,7 @@ final class FragmentManagerImpl extends FragmentManager {
if (mAdded != null) {
for (int i=0; i<mAdded.size(); i++) {
Fragment f = mAdded.get(i);
- if (f != null && !f.mHidden && f.mUserVisibleHint) {
+ if (f != null && !f.mHidden) {
if (f.onContextItemSelected(item)) {
return true;
}
diff --git a/core/java/android/app/IInstrumentationWatcher.aidl b/core/java/android/app/IInstrumentationWatcher.aidl
index 405a3d8..6c8c4d6 100644
--- a/core/java/android/app/IInstrumentationWatcher.aidl
+++ b/core/java/android/app/IInstrumentationWatcher.aidl
@@ -21,7 +21,7 @@ import android.content.ComponentName;
import android.os.Bundle;
/** @hide */
-oneway interface IInstrumentationWatcher
+interface IInstrumentationWatcher
{
void instrumentationStatus(in ComponentName name, int resultCode,
in Bundle results);
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java
index 35cc324..396f910 100644
--- a/core/java/android/app/NativeActivity.java
+++ b/core/java/android/app/NativeActivity.java
@@ -1,6 +1,5 @@
package android.app;
-import com.android.internal.view.IInputMethodCallback;
import com.android.internal.view.IInputMethodSession;
import android.content.Context;
@@ -119,7 +118,7 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback2,
}
}
- static class InputMethodCallback extends IInputMethodCallback.Stub {
+ static final class InputMethodCallback implements InputMethodManager.FinishedEventCallback {
WeakReference<NativeActivity> mNa;
InputMethodCallback(NativeActivity na) {
@@ -133,11 +132,6 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback2,
na.finishPreDispatchKeyEventNative(na.mNativeHandle, seq, handled);
}
}
-
- @Override
- public void sessionCreated(IInputMethodSession session) {
- // Stub -- not for use in the client.
- }
}
@Override
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 08bc0ac..2c19c0c 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -41,7 +41,8 @@ public class AppWidgetHost {
static final int HANDLE_UPDATE = 1;
static final int HANDLE_PROVIDER_CHANGED = 2;
- static final int HANDLE_VIEW_DATA_CHANGED = 3;
+ static final int HANDLE_PROVIDERS_CHANGED = 3;
+ static final int HANDLE_VIEW_DATA_CHANGED = 4;
final static Object sServiceLock = new Object();
static IAppWidgetService sService;
@@ -65,6 +66,11 @@ public class AppWidgetHost {
msg.sendToTarget();
}
+ public void providersChanged() {
+ Message msg = mHandler.obtainMessage(HANDLE_PROVIDERS_CHANGED);
+ msg.sendToTarget();
+ }
+
public void viewDataChanged(int appWidgetId, int viewId) {
Message msg = mHandler.obtainMessage(HANDLE_VIEW_DATA_CHANGED);
msg.arg1 = appWidgetId;
@@ -88,6 +94,10 @@ public class AppWidgetHost {
onProviderChanged(msg.arg1, (AppWidgetProviderInfo)msg.obj);
break;
}
+ case HANDLE_PROVIDERS_CHANGED: {
+ onProvidersChanged();
+ break;
+ }
case HANDLE_VIEW_DATA_CHANGED: {
viewDataChanged(msg.arg1, msg.arg2);
break;
@@ -274,6 +284,14 @@ public class AppWidgetHost {
}
}
+ /**
+ * Called when the set of available widgets changes (ie. widget containing packages
+ * are added, updated or removed, or widget components are enabled or disabled.)
+ */
+ protected void onProvidersChanged() {
+ // Do nothing
+ }
+
void updateAppWidgetView(int appWidgetId, RemoteViews views) {
AppWidgetHostView v;
synchronized (mViews) {
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index c9603bf..020f051 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -304,6 +304,25 @@ public final class BluetoothDeviceProfileState extends StateMachine {
}
}
+ @Override
+ protected void onQuitting() {
+ 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;
+ }
+
private class BondedDevice extends State {
@Override
public void enter() {
@@ -416,26 +435,6 @@ 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;
}
@@ -1341,6 +1340,15 @@ public final class BluetoothDeviceProfileState extends StateMachine {
return mDevice;
}
+ /**
+ * Quit the state machine, only to be called by BluetoothService.
+ *
+ * @hide
+ */
+ public void doQuit() {
+ this.quit();
+ }
+
private void log(String message) {
if (DBG) {
Log.i(TAG, "Device:" + mDevice + " Message:" + message);
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 19d13ef..20e8515 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -242,8 +242,10 @@ public final class BluetoothSocket implements Closeable {
// abortNative(), so this lock should immediately acquire
mLock.writeLock().lock();
try {
- mSocketState = SocketState.CLOSED;
- destroyNative();
+ if (mSocketState != SocketState.CLOSED) {
+ mSocketState = SocketState.CLOSED;
+ destroyNative();
+ }
} finally {
mLock.writeLock().unlock();
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 621113d..2800930 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1379,6 +1379,7 @@ public abstract class Context {
* description (action, category, etc) to match an
* {@link IntentFilter} published by a service.
* @param conn Receives information as the service is started and stopped.
+ * This must be a valid ServiceConnection object; it must not be null.
* @param flags Operation options for the binding. May be 0,
* {@link #BIND_AUTO_CREATE}, {@link #BIND_DEBUG_UNBIND},
* {@link #BIND_NOT_FOREGROUND}, {@link #BIND_ABOVE_CLIENT},
@@ -1414,7 +1415,7 @@ public abstract class Context {
* stop at any time.
*
* @param conn The connection interface previously supplied to
- * bindService().
+ * bindService(). This parameter must not be null.
*
* @see #bindService
*/
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 76dfac4..f22dd44 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -571,7 +571,9 @@ import java.util.Set;
* <li> {@link #EXTRA_INITIAL_INTENTS}
* <li> {@link #EXTRA_INTENT}
* <li> {@link #EXTRA_KEY_EVENT}
+ * <li> {@link #EXTRA_ORIGINATING_URL}
* <li> {@link #EXTRA_PHONE_NUMBER}
+ * <li> {@link #EXTRA_REFERRER}
* <li> {@link #EXTRA_REMOTE_INTENT_TOKEN}
* <li> {@link #EXTRA_REPLACING}
* <li> {@link #EXTRA_SHORTCUT_ICON}
@@ -1286,6 +1288,22 @@ public class Intent implements Parcelable, Cloneable {
= "android.intent.extra.NOT_UNKNOWN_SOURCE";
/**
+ * Used as a string extra field with {@link #ACTION_INSTALL_PACKAGE} and
+ * {@link #ACTION_VIEW} to indicate the URL from which the local APK in the Intent
+ * data field originated from.
+ */
+ public static final String EXTRA_ORIGINATING_URL
+ = "android.intent.extra.ORIGINATING_URL";
+
+ /**
+ * Used as a string extra field with {@link #ACTION_INSTALL_PACKAGE} and
+ * {@link #ACTION_VIEW} to indicate the HTTP referrer associated with the Intent
+ * data field or {@link #EXTRA_ORIGINATING_URL}.
+ */
+ public static final String EXTRA_REFERRER
+ = "android.intent.extra.REFERRER";
+
+ /**
* Used as a boolean extra field with {@link #ACTION_INSTALL_PACKAGE} to install a
* package. Tells the installer UI to skip the confirmation with the user
* if the .apk is replacing an existing one.
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index e1434b3..cbabc7c 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -298,7 +298,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
* activity's manifest.
*
* Default value is false (no support for RTL).
- * @hide
*/
public static final int FLAG_SUPPORTS_RTL = 1<<22;
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 90b4247..0d87df5 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -41,6 +41,7 @@ import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.content.pm.VerifierDeviceIdentity;
import android.net.Uri;
+import android.os.ParcelFileDescriptor;
import android.content.IntentSender;
/**
@@ -359,7 +360,8 @@ interface IPackageManager {
UserInfo createUser(in String name, int flags);
boolean removeUser(int userId);
- void updateUserName(int userId, String name);
+ void setUserName(int userId, String name);
+ ParcelFileDescriptor setUserIcon(int userId);
void installPackageWithVerification(in Uri packageURI, in IPackageInstallObserver observer,
int flags, in String installerPackageName, in Uri verificationURI,
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 6de69b0..f9f7e2d 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2646,7 +2646,7 @@ public abstract class PackageManager {
* @param name the new name for the user
* @hide
*/
- public abstract void updateUserName(int id, String name);
+ public abstract void setUserName(int id, String name);
/**
* Changes the user's properties specified by the flags.
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index ba5331c..68a7257 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -43,12 +43,18 @@ public class UserInfo implements Parcelable {
public int id;
public String name;
+ public String iconPath;
public int flags;
public UserInfo(int id, String name, int flags) {
+ this(id, name, null, flags);
+ }
+
+ public UserInfo(int id, String name, String iconPath, int flags) {
this.id = id;
this.name = name;
this.flags = flags;
+ this.iconPath = iconPath;
}
public boolean isPrimary() {
@@ -68,6 +74,7 @@ public class UserInfo implements Parcelable {
public UserInfo(UserInfo orig) {
name = orig.name;
+ iconPath = orig.iconPath;
id = orig.id;
flags = orig.flags;
}
@@ -84,6 +91,7 @@ public class UserInfo implements Parcelable {
public void writeToParcel(Parcel dest, int parcelableFlags) {
dest.writeInt(id);
dest.writeString(name);
+ dest.writeString(iconPath);
dest.writeInt(flags);
}
@@ -100,6 +108,7 @@ public class UserInfo implements Parcelable {
private UserInfo(Parcel source) {
id = source.readInt();
name = source.readString();
+ iconPath = source.readString();
flags = source.readInt();
}
}
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 2df492e..281b843 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -469,13 +469,20 @@ public class TypedArray {
* {@link android.view.ViewGroup}'s layout_width and layout_height
* attributes. This is only here for performance reasons; applications
* should use {@link #getDimensionPixelSize}.
- *
+ *
* @param index Index of the attribute to retrieve.
* @param name Textual name of attribute for error reporting.
*
* @return Attribute dimension value multiplied by the appropriate
* metric and truncated to integer pixels.
+ *
+ * @throws RuntimeException
+ * if this TypedArray does not contain an entry for <code>index</code>
+ *
+ * @deprecated Use {@link #getLayoutDimension(int, int)} instead.
+ *
*/
+ @Deprecated
public int getLayoutDimension(int index, String name) {
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index a6af5c2..1fc1226 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -50,9 +50,6 @@ public class DatabaseUtils {
private static final String TAG = "DatabaseUtils";
private static final boolean DEBUG = false;
- private static final boolean LOCAL_LOGV = false;
-
- private static final String[] countProjection = new String[]{"count(*)"};
/** One of the values returned by {@link #getSqlStatementType(String)}. */
public static final int STATEMENT_SELECT = 1;
@@ -963,10 +960,15 @@ public class DatabaseUtils {
}
/**
- * This class allows users to do multiple inserts into a table but
- * compile the SQL insert statement only once, which may increase
- * performance.
+ * This class allows users to do multiple inserts into a table using
+ * the same statement.
+ * <p>
+ * This class is not thread-safe.
+ * </p>
+ *
+ * @deprecated Use {@link SQLiteStatement} instead.
*/
+ @Deprecated
public static class InsertHelper {
private final SQLiteDatabase mDb;
private final String mTableName;
@@ -983,6 +985,13 @@ public class DatabaseUtils {
* table_info(...)" command that we depend on.
*/
public static final int TABLE_INFO_PRAGMA_COLUMNNAME_INDEX = 1;
+
+ /**
+ * This field was accidentally exposed in earlier versions of the platform
+ * so we can hide it but we can't remove it.
+ *
+ * @hide
+ */
public static final int TABLE_INFO_PRAGMA_DEFAULT_INDEX = 4;
/**
@@ -1036,7 +1045,7 @@ public class DatabaseUtils {
sb.append(sbv);
mInsertSQL = sb.toString();
- if (LOCAL_LOGV) Log.v(TAG, "insert statement is " + mInsertSQL);
+ if (DEBUG) Log.v(TAG, "insert statement is " + mInsertSQL);
}
private SQLiteStatement getStatement(boolean allowReplace) throws SQLException {
@@ -1069,24 +1078,35 @@ public class DatabaseUtils {
* @return the row ID of the newly inserted row, or -1 if an
* error occurred
*/
- private synchronized long insertInternal(ContentValues values, boolean allowReplace) {
+ private long insertInternal(ContentValues values, boolean allowReplace) {
+ // Start a transaction even though we don't really need one.
+ // This is to help maintain compatibility with applications that
+ // access InsertHelper from multiple threads even though they never should have.
+ // The original code used to lock the InsertHelper itself which was prone
+ // to deadlocks. Starting a transaction achieves the same mutual exclusion
+ // effect as grabbing a lock but without the potential for deadlocks.
+ mDb.beginTransactionNonExclusive();
try {
SQLiteStatement stmt = getStatement(allowReplace);
stmt.clearBindings();
- if (LOCAL_LOGV) Log.v(TAG, "--- inserting in table " + mTableName);
+ if (DEBUG) Log.v(TAG, "--- inserting in table " + mTableName);
for (Map.Entry<String, Object> e: values.valueSet()) {
final String key = e.getKey();
int i = getColumnIndex(key);
DatabaseUtils.bindObjectToProgram(stmt, i, e.getValue());
- if (LOCAL_LOGV) {
+ if (DEBUG) {
Log.v(TAG, "binding " + e.getValue() + " to column " +
i + " (" + key + ")");
}
}
- return stmt.executeInsert();
+ long result = stmt.executeInsert();
+ mDb.setTransactionSuccessful();
+ return result;
} catch (SQLException e) {
Log.e(TAG, "Error inserting " + values + " into table " + mTableName, e);
return -1;
+ } finally {
+ mDb.endTransaction();
}
}
@@ -1223,7 +1243,7 @@ public class DatabaseUtils {
+ "execute");
}
try {
- if (LOCAL_LOGV) Log.v(TAG, "--- doing insert or replace in table " + mTableName);
+ if (DEBUG) Log.v(TAG, "--- doing insert or replace in table " + mTableName);
return mPreparedStatement.executeInsert();
} catch (SQLException e) {
Log.e(TAG, "Error executing InsertHelper with table " + mTableName, e);
diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java
index 397a12a..cc3e34f 100644
--- a/core/java/android/net/DhcpStateMachine.java
+++ b/core/java/android/net/DhcpStateMachine.java
@@ -163,8 +163,21 @@ public class DhcpStateMachine extends StateMachine {
mRegisteredForPreDhcpNotification = true;
}
+ /**
+ * Quit the DhcpStateMachine.
+ *
+ * @hide
+ */
+ public void doQuit() {
+ quit();
+ }
+
class DefaultState extends State {
@Override
+ public void exit() {
+ mContext.unregisterReceiver(mBroadcastReceiver);
+ }
+ @Override
public boolean processMessage(Message message) {
if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
switch (message.what) {
@@ -172,10 +185,6 @@ public class DhcpStateMachine extends StateMachine {
Log.e(TAG, "Error! Failed to handle a DHCP renewal on " + mInterfaceName);
mDhcpRenewWakeLock.release();
break;
- case SM_QUIT_CMD:
- mContext.unregisterReceiver(mBroadcastReceiver);
- //let parent kill the state machine
- return NOT_HANDLED;
default:
Log.e(TAG, "Error! unhandled message " + message);
break;
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index 28bd289..5197c9e 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -230,6 +230,10 @@ public class EthernetDataTracker implements NetworkStateTracker {
mNetworkInfo.setExtraInfo(mHwAddr);
}
}
+
+ // if a DHCP client had previously been started for this interface, then stop it
+ NetworkUtils.stopDhcp(mIface);
+
reconnect();
break;
}
diff --git a/core/java/android/net/arp/ArpPeer.java b/core/java/android/net/arp/ArpPeer.java
index 8e666bc..5f68fdf 100644
--- a/core/java/android/net/arp/ArpPeer.java
+++ b/core/java/android/net/arp/ArpPeer.java
@@ -16,8 +16,12 @@
package android.net.arp;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.RouteInfo;
import android.os.SystemClock;
import android.util.Log;
+
import java.io.IOException;
import java.net.InetAddress;
import java.net.Inet6Address;
@@ -35,6 +39,8 @@ import libcore.net.RawSocket;
* @hide
*/
public class ArpPeer {
+ private static final boolean DBG = false;
+ private static final String TAG = "ArpPeer";
private String mInterfaceName;
private final InetAddress mMyAddr;
private final byte[] mMyMac = new byte[6];
@@ -46,7 +52,6 @@ public class ArpPeer {
private static final int ARP_LENGTH = 28;
private static final int MAC_ADDR_LENGTH = 6;
private static final int IPV4_LENGTH = 4;
- private static final String TAG = "ArpPeer";
public ArpPeer(String interfaceName, InetAddress myAddr, String mac,
InetAddress peer) throws SocketException {
@@ -123,6 +128,41 @@ public class ArpPeer {
return null;
}
+ public static boolean doArp(String myMacAddress, LinkProperties linkProperties,
+ int timeoutMillis, int numArpPings, int minArpResponses) {
+ String interfaceName = linkProperties.getInterfaceName();
+ InetAddress inetAddress = null;
+ InetAddress gateway = null;
+ boolean success;
+
+ for (LinkAddress la : linkProperties.getLinkAddresses()) {
+ inetAddress = la.getAddress();
+ break;
+ }
+
+ for (RouteInfo route : linkProperties.getRoutes()) {
+ gateway = route.getGateway();
+ break;
+ }
+
+ try {
+ ArpPeer peer = new ArpPeer(interfaceName, inetAddress, myMacAddress, gateway);
+ int responses = 0;
+ for (int i=0; i < numArpPings; i++) {
+ if(peer.doArp(timeoutMillis) != null) responses++;
+ }
+ if (DBG) Log.d(TAG, "ARP test result: " + responses + "/" + numArpPings);
+ success = (responses >= minArpResponses);
+ peer.close();
+ } catch (SocketException se) {
+ //Consider an Arp socket creation issue as a successful Arp
+ //test to avoid any wifi connectivity issues
+ Log.e(TAG, "ARP test initiation failure: " + se);
+ success = true;
+ }
+ return success;
+ }
+
public void close() {
try {
mSocket.close();
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 438c536..2aa6fb5 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -71,9 +71,9 @@ public abstract class BatteryStats implements Parcelable {
public static final int FULL_WIFI_LOCK = 5;
/**
- * A constant indicating a scan wifi lock timer
+ * A constant indicating a wifi scan
*/
- public static final int SCAN_WIFI_LOCK = 6;
+ public static final int WIFI_SCAN = 6;
/**
* A constant indicating a wifi multicast timer
@@ -136,7 +136,7 @@ public abstract class BatteryStats implements Parcelable {
private static final String BATTERY_DATA = "bt";
private static final String BATTERY_DISCHARGE_DATA = "dc";
private static final String BATTERY_LEVEL_DATA = "lv";
- private static final String WIFI_LOCK_DATA = "wfl";
+ private static final String WIFI_DATA = "wfl";
private static final String MISC_DATA = "m";
private static final String SCREEN_BRIGHTNESS_DATA = "br";
private static final String SIGNAL_STRENGTH_TIME_DATA = "sgt";
@@ -260,8 +260,8 @@ public abstract class BatteryStats implements Parcelable {
public abstract void noteWifiStoppedLocked();
public abstract void noteFullWifiLockAcquiredLocked();
public abstract void noteFullWifiLockReleasedLocked();
- public abstract void noteScanWifiLockAcquiredLocked();
- public abstract void noteScanWifiLockReleasedLocked();
+ public abstract void noteWifiScanStartedLocked();
+ public abstract void noteWifiScanStoppedLocked();
public abstract void noteWifiMulticastEnabledLocked();
public abstract void noteWifiMulticastDisabledLocked();
public abstract void noteAudioTurnedOnLocked();
@@ -270,7 +270,7 @@ public abstract class BatteryStats implements Parcelable {
public abstract void noteVideoTurnedOffLocked();
public abstract long getWifiRunningTime(long batteryRealtime, int which);
public abstract long getFullWifiLockTime(long batteryRealtime, int which);
- public abstract long getScanWifiLockTime(long batteryRealtime, int which);
+ public abstract long getWifiScanTime(long batteryRealtime, int which);
public abstract long getWifiMulticastTime(long batteryRealtime,
int which);
public abstract long getAudioTurnedOnTime(long batteryRealtime, int which);
@@ -453,7 +453,7 @@ public abstract class BatteryStats implements Parcelable {
public static final int STATE_PHONE_SCANNING_FLAG = 1<<27;
public static final int STATE_WIFI_RUNNING_FLAG = 1<<26;
public static final int STATE_WIFI_FULL_LOCK_FLAG = 1<<25;
- public static final int STATE_WIFI_SCAN_LOCK_FLAG = 1<<24;
+ public static final int STATE_WIFI_SCAN_FLAG = 1<<24;
public static final int STATE_WIFI_MULTICAST_ON_FLAG = 1<<23;
// These are on the lower bits used for the command; if they change
// we need to write another int of data.
@@ -859,7 +859,7 @@ public abstract class BatteryStats implements Parcelable {
new BitDescription(HistoryItem.STATE_WIFI_ON_FLAG, "wifi"),
new BitDescription(HistoryItem.STATE_WIFI_RUNNING_FLAG, "wifi_running"),
new BitDescription(HistoryItem.STATE_WIFI_FULL_LOCK_FLAG, "wifi_full_lock"),
- new BitDescription(HistoryItem.STATE_WIFI_SCAN_LOCK_FLAG, "wifi_scan_lock"),
+ new BitDescription(HistoryItem.STATE_WIFI_SCAN_FLAG, "wifi_scan"),
new BitDescription(HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG, "wifi_multicast"),
new BitDescription(HistoryItem.STATE_BLUETOOTH_ON_FLAG, "bluetooth"),
new BitDescription(HistoryItem.STATE_AUDIO_ON_FLAG, "audio"),
@@ -1326,15 +1326,15 @@ public abstract class BatteryStats implements Parcelable {
long rx = u.getTcpBytesReceived(which);
long tx = u.getTcpBytesSent(which);
long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
- long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
+ long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
- if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
+ if (fullWifiLockOnTime != 0 || wifiScanTime != 0
|| uidWifiRunningTime != 0) {
- dumpLine(pw, uid, category, WIFI_LOCK_DATA,
- fullWifiLockOnTime, scanWifiLockOnTime, uidWifiRunningTime);
+ dumpLine(pw, uid, category, WIFI_DATA,
+ fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime);
}
if (u.hasUserActivity()) {
@@ -1692,7 +1692,7 @@ public abstract class BatteryStats implements Parcelable {
long tcpReceived = u.getTcpBytesReceived(which);
long tcpSent = u.getTcpBytesSent(which);
long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
- long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
+ long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
if (tcpReceived != 0 || tcpSent != 0) {
@@ -1723,7 +1723,7 @@ public abstract class BatteryStats implements Parcelable {
}
}
- if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
+ if (fullWifiLockOnTime != 0 || wifiScanTime != 0
|| uidWifiRunningTime != 0) {
sb.setLength(0);
sb.append(prefix); sb.append(" Wifi Running: ");
@@ -1731,12 +1731,12 @@ public abstract class BatteryStats implements Parcelable {
sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
whichBatteryRealtime)); sb.append(")\n");
sb.append(prefix); sb.append(" Full Wifi Lock: ");
- formatTimeMs(sb, fullWifiLockOnTime / 1000);
- sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
+ formatTimeMs(sb, fullWifiLockOnTime / 1000);
+ sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
whichBatteryRealtime)); sb.append(")\n");
- sb.append(prefix); sb.append(" Scan Wifi Lock: ");
- formatTimeMs(sb, scanWifiLockOnTime / 1000);
- sb.append("("); sb.append(formatRatioLocked(scanWifiLockOnTime,
+ sb.append(prefix); sb.append(" Wifi Scan: ");
+ formatTimeMs(sb, wifiScanTime / 1000);
+ sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
whichBatteryRealtime)); sb.append(")");
pw.println(sb.toString());
}
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index e7ea355..b64a73a 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -218,17 +218,17 @@ interface INetworkManagementService
/**
* Start Wifi Access Point
*/
- void startAccessPoint(in WifiConfiguration wifiConfig, String wlanIface, String softapIface);
+ void startAccessPoint(in WifiConfiguration wifiConfig, String iface);
/**
* Stop Wifi Access Point
*/
- void stopAccessPoint(String wlanIface);
+ void stopAccessPoint(String iface);
/**
* Set Access Point config
*/
- void setAccessPoint(in WifiConfiguration wifiConfig, String wlanIface, String softapIface);
+ void setAccessPoint(in WifiConfiguration wifiConfig, String iface);
/**
** DATA USAGE RELATED
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 903c8b3..318c0ae 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -19,19 +19,21 @@ package android.os;
import android.util.Log;
/**
- * This class gives you control of the power state of the device.
- *
- * <p><b>Device battery life will be significantly affected by the use of this API.</b> Do not
- * acquire WakeLocks unless you really need them, use the minimum levels possible, and be sure
- * to release it as soon as you can.
- *
- * <p>You can obtain an instance of this class by calling
+ * This class gives you control of the power state of the device.
+ *
+ * <p>
+ * <b>Device battery life will be significantly affected by the use of this API.</b>
+ * Do not acquire {@link WakeLock}s unless you really need them, use the minimum levels
+ * possible, and be sure to release them as soon as possible.
+ * </p><p>
+ * You can obtain an instance of this class by calling
* {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
- *
- * <p>The primary API you'll use is {@link #newWakeLock(int, String) newWakeLock()}. This will
- * create a {@link PowerManager.WakeLock} object. You can then use methods on this object to
- * control the power state of the device. In practice it's quite simple:
- *
+ * </p><p>
+ * The primary API you'll use is {@link #newWakeLock(int, String) newWakeLock()}.
+ * This will create a {@link PowerManager.WakeLock} object. You can then use methods
+ * on the wake lock object to control the power state of the device.
+ * </p><p>
+ * In practice it's quite simple:
* {@samplecode
* PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
* PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
@@ -39,11 +41,11 @@ import android.util.Log;
* ..screen will stay on during this section..
* wl.release();
* }
- *
- * <p>The following flags are defined, with varying effects on system power. <i>These flags are
- * mutually exclusive - you may only specify one of them.</i>
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
+ * </p><p>
+ * The following flags are defined, with varying effects on system power.
+ * <i>These flags are mutually exclusive - you may only specify one of them.</i>
*
+ * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
* <thead>
* <tr><th>Flag Value</th>
* <th>CPU</th> <th>Screen</th> <th>Keyboard</th></tr>
@@ -67,15 +69,16 @@ import android.util.Log;
* </tr>
* </tbody>
* </table>
- *
- * <p>*<i>If you hold a partial wakelock, the CPU will continue to run, irrespective of any timers
- * and even after the user presses the power button. In all other wakelocks, the CPU will run, but
- * the user can still put the device to sleep using the power button.</i>
- *
- * <p>In addition, you can add two more flags, which affect behavior of the screen only. <i>These
- * flags have no effect when combined with a {@link #PARTIAL_WAKE_LOCK}.</i>
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
+ * </p><p>
+ * *<i>If you hold a partial wake lock, the CPU will continue to run, regardless of any
+ * display timeouts or the state of the screen and even after the user presses the power button.
+ * In all other wake locks, the CPU will run, but the user can still put the device to sleep
+ * using the power button.</i>
+ * </p><p>
+ * In addition, you can add two more flags, which affect behavior of the screen only.
+ * <i>These flags have no effect when combined with a {@link #PARTIAL_WAKE_LOCK}.</i>
*
+ * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
* <thead>
* <tr><th>Flag Value</th> <th>Description</th></tr>
* </thead>
@@ -96,73 +99,77 @@ import android.util.Log;
* </tr>
* </tbody>
* </table>
- *
+ * </p><p>
* Any application using a WakeLock must request the {@code android.permission.WAKE_LOCK}
* permission in an {@code &lt;uses-permission&gt;} element of the application's manifest.
+ * </p>
*/
-public class PowerManager
-{
+public final class PowerManager {
private static final String TAG = "PowerManager";
-
- /**
+
+ /*
* These internal values define the underlying power elements that we might
* want to control individually. Eventually we'd like to expose them.
*/
- private static final int WAKE_BIT_CPU_STRONG = 1;
- private static final int WAKE_BIT_CPU_WEAK = 2;
- private static final int WAKE_BIT_SCREEN_DIM = 4;
- private static final int WAKE_BIT_SCREEN_BRIGHT = 8;
- private static final int WAKE_BIT_KEYBOARD_BRIGHT = 16;
- private static final int WAKE_BIT_PROXIMITY_SCREEN_OFF = 32;
-
+ private static final int WAKE_BIT_CPU_STRONG = 1 << 0;
+ private static final int WAKE_BIT_CPU_WEAK = 1 << 1;
+ private static final int WAKE_BIT_SCREEN_DIM = 1 << 2;
+ private static final int WAKE_BIT_SCREEN_BRIGHT = 1 << 3;
+ private static final int WAKE_BIT_KEYBOARD_BRIGHT = 1 << 4;
+ private static final int WAKE_BIT_PROXIMITY_SCREEN_OFF = 1 << 5;
+
private static final int LOCK_MASK = WAKE_BIT_CPU_STRONG
- | WAKE_BIT_CPU_WEAK
- | WAKE_BIT_SCREEN_DIM
- | WAKE_BIT_SCREEN_BRIGHT
- | WAKE_BIT_KEYBOARD_BRIGHT
- | WAKE_BIT_PROXIMITY_SCREEN_OFF;
+ | WAKE_BIT_CPU_WEAK
+ | WAKE_BIT_SCREEN_DIM
+ | WAKE_BIT_SCREEN_BRIGHT
+ | WAKE_BIT_KEYBOARD_BRIGHT
+ | WAKE_BIT_PROXIMITY_SCREEN_OFF;
/**
- * Wake lock that ensures that the CPU is running. The screen might
- * not be on.
+ * Wake lock level: Ensures that the CPU is running; the screen and keyboard
+ * backlight will be allowed to go off.
*/
public static final int PARTIAL_WAKE_LOCK = WAKE_BIT_CPU_STRONG;
/**
- * Wake lock that ensures that the screen and keyboard are on at
+ * Wake lock level: Ensures that the screen and keyboard backlight are on at
* full brightness.
*
- * <p class="note">Most applications should strongly consider using
- * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
- * This window flag will be correctly managed by the platform
- * as the user moves between applications and doesn't require a special permission.</p>
+ * <p class="note">
+ * Most applications should strongly consider using
+ * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead
+ * of managing their own wake locks. This window flag will be correctly managed
+ * by the platform as the user moves between applications and doesn't require
+ * a special permission.
+ * </p>
*/
public static final int FULL_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT
- | WAKE_BIT_KEYBOARD_BRIGHT;
+ | WAKE_BIT_KEYBOARD_BRIGHT;
/**
+ * Wake lock level: Ensures that the screen is on at full brightness;
+ * the keyboard backlight will be allowed to go off.
+ *
* @deprecated Most applications should use
* {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead
* of this type of wake lock, as it will be correctly managed by the platform
* as the user moves between applications and doesn't require a special permission.
- *
- * Wake lock that ensures that the screen is on at full brightness;
- * the keyboard backlight will be allowed to go off.
*/
@Deprecated
public static final int SCREEN_BRIGHT_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT;
/**
- * Wake lock that ensures that the screen is on (but may be dimmed);
+ * Wake lock level: Ensures that the screen is on (but may be dimmed);
* the keyboard backlight will be allowed to go off.
*/
public static final int SCREEN_DIM_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_DIM;
/**
- * Wake lock that turns the screen off when the proximity sensor activates.
- * Since not all devices have proximity sensors, use
- * {@link #getSupportedWakeLockFlags() getSupportedWakeLockFlags()} to determine if
- * this wake lock mode is supported.
+ * Wake lock level: Turns the screen off when the proximity sensor activates.
+ * <p>
+ * Since not all devices have proximity sensors, use {@link #getSupportedWakeLockFlags()}
+ * to determine whether this wake lock level is supported.
+ * </p>
*
* {@hide}
*/
@@ -170,7 +177,7 @@ public class PowerManager
/**
* Flag for {@link WakeLock#release release(int)} to defer releasing a
- * {@link #WAKE_BIT_PROXIMITY_SCREEN_OFF} wakelock until the proximity sensor returns
+ * {@link #WAKE_BIT_PROXIMITY_SCREEN_OFF} wake lock until the proximity sensor returns
* a negative value.
*
* {@hide}
@@ -178,25 +185,29 @@ public class PowerManager
public static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1;
/**
+ * Wake lock flag: Turn the screen on when the wake lock is acquired.
+ * <p>
* Normally wake locks don't actually wake the device, they just cause
- * it to remain on once it's already on. Think of the video player
- * app as the normal behavior. Notifications that pop up and want
+ * the screen to remain on once it's already on. Think of the video player
+ * application as the normal behavior. Notifications that pop up and want
* the device to be on are the exception; use this flag to be like them.
- * <p>
- * Does not work with PARTIAL_WAKE_LOCKs.
+ * </p><p>
+ * Cannot be used with {@link #PARTIAL_WAKE_LOCK}.
+ * </p>
*/
- public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000;
+ public static final int ACQUIRE_CAUSES_WAKEUP = 1 << 28;
/**
- * When this wake lock is released, poke the user activity timer
+ * Wake lock flag: When this wake lock is released, poke the user activity timer
* so the screen stays on for a little longer.
* <p>
- * Will not turn the screen on if it is not already on. See {@link #ACQUIRE_CAUSES_WAKEUP}
- * if you want that.
- * <p>
- * Does not work with PARTIAL_WAKE_LOCKs.
+ * Will not turn the screen on if it is not already on.
+ * See {@link #ACQUIRE_CAUSES_WAKEUP} if you want that.
+ * </p><p>
+ * Cannot be used with {@link #PARTIAL_WAKE_LOCK}.
+ * </p>
*/
- public static final int ON_AFTER_RELEASE = 0x20000000;
+ public static final int ON_AFTER_RELEASE = 1 << 29;
/**
* Brightness value to use when battery is low.
@@ -222,78 +233,305 @@ public class PowerManager
*/
public static final int BRIGHTNESS_OFF = 0;
+ final IPowerManager mService;
+ final Handler mHandler;
+
+ /**
+ * {@hide}
+ */
+ public PowerManager(IPowerManager service, Handler handler) {
+ mService = service;
+ mHandler = handler;
+ }
+
+ /**
+ * Creates a new wake lock with the specified level and flags.
+ * <p>
+ * The {@code levelAndFlags} parameter specifies a wake lock level and optional flags
+ * combined using the logical OR operator.
+ * </p><p>
+ * The wake lock levels are: {@link #PARTIAL_WAKE_LOCK},
+ * {@link #FULL_WAKE_LOCK}, {@link #SCREEN_DIM_WAKE_LOCK}
+ * and {@link #SCREEN_BRIGHT_WAKE_LOCK}. Exactly one wake lock level must be
+ * specified as part of the {@code levelAndFlags} parameter.
+ * </p><p>
+ * The wake lock flags are: {@link #ACQUIRE_CAUSES_WAKEUP}
+ * and {@link #ON_AFTER_RELEASE}. Multiple flags can be combined as part of the
+ * {@code levelAndFlags} parameters.
+ * </p><p>
+ * Call {@link WakeLock#acquire() acquire()} on the object to acquire the
+ * wake lock, and {@link WakeLock#release release()} when you are done.
+ * </p><p>
+ * {@samplecode
+ * PowerManager pm = (PowerManager)mContext.getSystemService(
+ * Context.POWER_SERVICE);
+ * PowerManager.WakeLock wl = pm.newWakeLock(
+ * PowerManager.SCREEN_DIM_WAKE_LOCK
+ * | PowerManager.ON_AFTER_RELEASE,
+ * TAG);
+ * wl.acquire();
+ * // ... do work...
+ * wl.release();
+ * }
+ * </p><p>
+ * Although a wake lock can be created without special permissions,
+ * the {@link android.Manifest.permission#WAKE_LOCK} permission is
+ * required to actually acquire or release the wake lock that is returned.
+ * </p><p class="note">
+ * If using this to keep the screen on, you should strongly consider using
+ * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead.
+ * This window flag will be correctly managed by the platform
+ * as the user moves between applications and doesn't require a special permission.
+ * </p>
+ *
+ * @param levelAndFlags Combination of wake lock level and flag values defining
+ * the requested behavior of the WakeLock.
+ * @param tag Your class name (or other tag) for debugging purposes.
+ *
+ * @see WakeLock#acquire()
+ * @see WakeLock#release()
+ * @see #PARTIAL_WAKE_LOCK
+ * @see #FULL_WAKE_LOCK
+ * @see #SCREEN_DIM_WAKE_LOCK
+ * @see #SCREEN_BRIGHT_WAKE_LOCK
+ * @see #ACQUIRE_CAUSES_WAKEUP
+ * @see #ON_AFTER_RELEASE
+ */
+ public WakeLock newWakeLock(int levelAndFlags, String tag) {
+ switch (levelAndFlags & LOCK_MASK) {
+ case PARTIAL_WAKE_LOCK:
+ case SCREEN_DIM_WAKE_LOCK:
+ case SCREEN_BRIGHT_WAKE_LOCK:
+ case FULL_WAKE_LOCK:
+ case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
+ break;
+ default:
+ throw new IllegalArgumentException("Must specify a wake lock level.");
+ }
+ if (tag == null) {
+ throw new IllegalArgumentException("The tag must not be null.");
+ }
+ return new WakeLock(levelAndFlags, tag);
+ }
+
+ /**
+ * Notifies the power manager that user activity happened.
+ * <p>
+ * Turns the device from whatever state it's in to full on, and resets
+ * the auto-off timer.
+ * </p><p>
+ * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+ * </p>
+ *
+ * @param when The time of the user activity, in the {@link SystemClock#uptimeMillis()}
+ * time base. This timestamp is used to correctly order the user activity with
+ * other power management functions. It should be set
+ * to the timestamp of the input event that caused the user activity.
+ * @param noChangeLights If true, does not cause the keyboard backlight to turn on
+ * because of this event. This is set when the power key is pressed.
+ * We want the device to stay on while the button is down, but we're about
+ * to turn off the screen so we don't want the keyboard backlight to turn on again.
+ * Otherwise the lights flash on and then off and it looks weird.
+ */
+ public void userActivity(long when, boolean noChangeLights) {
+ try {
+ mService.userActivity(when, noChangeLights);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * Forces the device to go to sleep.
+ * <p>
+ * Overrides all the wake locks that are held. This is what happen when the power
+ * key is pressed to turn off the screen.
+ * </p><p>
+ * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+ * </p>
+ *
+ * @param time The time when the request to go to sleep was issued, in the
+ * {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
+ * order the user activity with other power management functions. It should be set
+ * to the timestamp of the input event that caused the request to go to sleep.
+ */
+ public void goToSleep(long time) {
+ try {
+ mService.goToSleep(time);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * Sets the brightness of the backlights (screen, keyboard, button).
+ * <p>
+ * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+ * </p>
+ *
+ * @param brightness The brightness value from 0 to 255.
+ *
+ * {@hide}
+ */
+ public void setBacklightBrightness(int brightness) {
+ try {
+ mService.setBacklightBrightness(brightness);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * Returns the set of wake lock levels and flags for {@link #newWakeLock}
+ * that are supported on the device.
+ * <p>
+ * For example, to test to see if the {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK}
+ * is supported:
+ * {@samplecode
+ * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+ * int supportedFlags = pm.getSupportedWakeLockFlags();
+ * boolean proximitySupported = ((supportedFlags & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)
+ * == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK);
+ * }
+ * </p>
+ *
+ * @return The set of supported WakeLock flags.
+ *
+ * {@hide}
+ */
+ public int getSupportedWakeLockFlags() {
+ try {
+ return mService.getSupportedWakeLockFlags();
+ } catch (RemoteException e) {
+ return 0;
+ }
+ }
+
+ /**
+ * Returns whether the screen is currently on.
+ * <p>
+ * Only indicates whether the screen is on. The screen could be either bright or dim.
+ * </p><p>
+ * {@samplecode
+ * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+ * boolean isScreenOn = pm.isScreenOn();
+ * }
+ * </p>
+ *
+ * @return whether the screen is on (bright or dim).
+ */
+ public boolean isScreenOn() {
+ try {
+ return mService.isScreenOn();
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
/**
- * Class lets you say that you need to have the device on.
+ * Reboot the device. Will not return if the reboot is successful.
* <p>
- * Call release when you are done and don't need the lock anymore.
+ * Requires the {@link android.Manifest.permission#REBOOT} permission.
+ * </p>
+ *
+ * @param reason code to pass to the kernel (e.g., "recovery") to
+ * request special boot modes, or null.
+ */
+ public void reboot(String reason) {
+ try {
+ mService.reboot(reason);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * A wake lock is a mechanism to indicate that your application needs
+ * to have the device stay on.
* <p>
* Any application using a WakeLock must request the {@code android.permission.WAKE_LOCK}
* permission in an {@code &lt;uses-permission&gt;} element of the application's manifest.
+ * Obtain a wake lock by calling {@link PowerManager#newWakeLock(int, String)}.
+ * </p><p>
+ * Call {@link #acquire()} to acquire the wake lock and force the device to stay
+ * on at the level that was requested when the wake lock was created.
+ * </p><p>
+ * Call {@link #release()} when you are done and don't need the lock anymore.
+ * It is very important to do this as soon as possible to avoid running down the
+ * device's battery excessively.
+ * </p>
*/
- public class WakeLock
- {
- static final int RELEASE_WAKE_LOCK = 1;
-
- Runnable mReleaser = new Runnable() {
+ public final class WakeLock {
+ private final int mFlags;
+ private final String mTag;
+ private final IBinder mToken;
+ private int mCount;
+ private boolean mRefCounted = true;
+ private boolean mHeld;
+ private WorkSource mWorkSource;
+
+ private final Runnable mReleaser = new Runnable() {
public void run() {
release();
}
};
-
- int mFlags;
- String mTag;
- IBinder mToken;
- int mCount = 0;
- boolean mRefCounted = true;
- boolean mHeld = false;
- WorkSource mWorkSource;
-
- WakeLock(int flags, String tag)
- {
- switch (flags & LOCK_MASK) {
- case PARTIAL_WAKE_LOCK:
- case SCREEN_DIM_WAKE_LOCK:
- case SCREEN_BRIGHT_WAKE_LOCK:
- case FULL_WAKE_LOCK:
- case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
- break;
- default:
- throw new IllegalArgumentException();
- }
+ WakeLock(int flags, String tag) {
mFlags = flags;
mTag = tag;
mToken = new Binder();
}
+ @Override
+ protected void finalize() throws Throwable {
+ synchronized (mToken) {
+ if (mHeld) {
+ Log.wtf(TAG, "WakeLock finalized while still held: " + mTag);
+ try {
+ mService.releaseWakeLock(mToken, 0);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ }
+
/**
- * Sets whether this WakeLock is ref counted.
- *
- * <p>Wake locks are reference counted by default.
+ * Sets whether this WakeLock is reference counted.
+ * <p>
+ * Wake locks are reference counted by default. If a wake lock is
+ * reference counted, then each call to {@link #acquire()} must be
+ * balanced by an equal number of calls to {@link #release()}. If a wake
+ * lock is not reference counted, then one call to {@link #release()} is
+ * sufficient to undo the effect of all previous calls to {@link #acquire()}.
+ * </p>
*
- * @param value true for ref counted, false for not ref counted.
+ * @param value True to make the wake lock reference counted, false to
+ * make the wake lock non-reference counted.
*/
- public void setReferenceCounted(boolean value)
- {
- mRefCounted = value;
+ public void setReferenceCounted(boolean value) {
+ synchronized (mToken) {
+ mRefCounted = value;
+ }
}
/**
- * Makes sure the device is on at the level you asked when you created
- * the wake lock.
+ * Acquires the wake lock.
+ * <p>
+ * Ensures that the device is on at the level requested when
+ * the wake lock was created.
+ * </p>
*/
- public void acquire()
- {
+ public void acquire() {
synchronized (mToken) {
acquireLocked();
}
}
/**
- * Makes sure the device is on at the level you asked when you created
- * the wake lock. The lock will be released after the given timeout.
- *
- * @param timeout Release the lock after the give timeout in milliseconds.
+ * Acquires the wake lock with a timeout.
+ * <p>
+ * Ensures that the device is on at the level requested when
+ * the wake lock was created. The lock will be released after the given timeout
+ * expires.
+ * </p>
+ *
+ * @param timeout The timeout after which to release the wake lock, in milliseconds.
*/
public void acquire(long timeout) {
synchronized (mToken) {
@@ -301,37 +539,42 @@ public class PowerManager
mHandler.postDelayed(mReleaser, timeout);
}
}
-
+
private void acquireLocked() {
if (!mRefCounted || mCount++ == 0) {
mHandler.removeCallbacks(mReleaser);
- try {
- mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource);
- } catch (RemoteException e) {
+ if (!mHeld) {
+ try {
+ mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource);
+ } catch (RemoteException e) {
+ }
+ mHeld = true;
}
- mHeld = true;
}
}
/**
- * Release your claim to the CPU or screen being on.
- *
+ * Releases the wake lock.
* <p>
- * It may turn off shortly after you release it, or it may not if there
- * are other wake locks held.
+ * This method releases your claim to the CPU or screen being on.
+ * The screen may turn off shortly after you release the wake lock, or it may
+ * not if there are other wake locks still held.
+ * </p>
*/
public void release() {
release(0);
}
/**
- * Release your claim to the CPU or screen being on.
- * @param flags Combination of flag values to modify the release behavior.
- * Currently only {@link #WAIT_FOR_PROXIMITY_NEGATIVE} is supported.
- *
+ * Releases the wake lock with flags to modify the release behavior.
* <p>
- * It may turn off shortly after you release it, or it may not if there
- * are other wake locks held.
+ * This method releases your claim to the CPU or screen being on.
+ * The screen may turn off shortly after you release the wake lock, or it may
+ * not if there are other wake locks still held.
+ * </p>
+ *
+ * @param flags Combination of flag values to modify the release behavior.
+ * Currently only {@link #WAIT_FOR_PROXIMITY_NEGATIVE} is supported.
*
* {@hide}
*/
@@ -339,11 +582,13 @@ public class PowerManager
synchronized (mToken) {
if (!mRefCounted || --mCount == 0) {
mHandler.removeCallbacks(mReleaser);
- try {
- mService.releaseWakeLock(mToken, flags);
- } catch (RemoteException e) {
+ if (mHeld) {
+ try {
+ mService.releaseWakeLock(mToken, flags);
+ } catch (RemoteException e) {
+ }
+ mHeld = false;
}
- mHeld = false;
}
if (mCount < 0) {
throw new RuntimeException("WakeLock under-locked " + mTag);
@@ -351,23 +596,40 @@ public class PowerManager
}
}
- public boolean isHeld()
- {
+ /**
+ * Returns true if the wake lock has been acquired but not yet released.
+ *
+ * @return True if the wake lock is held.
+ */
+ public boolean isHeld() {
synchronized (mToken) {
return mHeld;
}
}
+ /**
+ * Sets the work source associated with the wake lock.
+ * <p>
+ * The work source is used to determine on behalf of which application
+ * the wake lock is being held. This is useful in the case where a
+ * service is performing work on behalf of an application so that the
+ * cost of that work can be accounted to the application.
+ * </p>
+ *
+ * @param ws The work source, or null if none.
+ */
public void setWorkSource(WorkSource ws) {
synchronized (mToken) {
if (ws != null && ws.size() == 0) {
ws = null;
}
- boolean changed = true;
+
+ final boolean changed;
if (ws == null) {
+ changed = mWorkSource != null;
mWorkSource = null;
} else if (mWorkSource == null) {
- changed = mWorkSource != null;
+ changed = true;
mWorkSource = new WorkSource(ws);
} else {
changed = mWorkSource.diff(ws);
@@ -375,6 +637,7 @@ public class PowerManager
mWorkSource.set(ws);
}
}
+
if (changed && mHeld) {
try {
mService.updateWakeLockWorkSource(mToken, mWorkSource);
@@ -384,6 +647,7 @@ public class PowerManager
}
}
+ @Override
public String toString() {
synchronized (mToken) {
return "WakeLock{"
@@ -391,194 +655,5 @@ public class PowerManager
+ " held=" + mHeld + ", refCount=" + mCount + "}";
}
}
-
- @Override
- protected void finalize() throws Throwable
- {
- synchronized (mToken) {
- if (mHeld) {
- Log.wtf(TAG, "WakeLock finalized while still held: " + mTag);
- try {
- mService.releaseWakeLock(mToken, 0);
- } catch (RemoteException e) {
- }
- }
- }
- }
- }
-
- /**
- * Get a wake lock at the level of the flags parameter. Call
- * {@link WakeLock#acquire() acquire()} on the object to acquire the
- * wake lock, and {@link WakeLock#release release()} when you are done.
- *
- * {@samplecode
- *PowerManager pm = (PowerManager)mContext.getSystemService(
- * Context.POWER_SERVICE);
- *PowerManager.WakeLock wl = pm.newWakeLock(
- * PowerManager.SCREEN_DIM_WAKE_LOCK
- * | PowerManager.ON_AFTER_RELEASE,
- * TAG);
- *wl.acquire();
- * // ...
- *wl.release();
- * }
- *
- * <p class="note">If using this to keep the screen on, you should strongly consider using
- * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead.
- * This window flag will be correctly managed by the platform
- * as the user moves between applications and doesn't require a special permission.</p>
- *
- * @param flags Combination of flag values defining the requested behavior of the WakeLock.
- * @param tag Your class name (or other tag) for debugging purposes.
- *
- * @see WakeLock#acquire()
- * @see WakeLock#release()
- */
- public WakeLock newWakeLock(int flags, String tag)
- {
- if (tag == null) {
- throw new NullPointerException("tag is null in PowerManager.newWakeLock");
- }
- return new WakeLock(flags, tag);
- }
-
- /**
- * User activity happened.
- * <p>
- * Turns the device from whatever state it's in to full on, and resets
- * the auto-off timer.
- *
- * @param when is used to order this correctly with the wake lock calls.
- * This time should be in the {@link SystemClock#uptimeMillis
- * SystemClock.uptimeMillis()} time base.
- * @param noChangeLights should be true if you don't want the lights to
- * turn on because of this event. This is set when the power
- * key goes down. We want the device to stay on while the button
- * is down, but we're about to turn off. Otherwise the lights
- * flash on and then off and it looks weird.
- */
- public void userActivity(long when, boolean noChangeLights)
- {
- try {
- mService.userActivity(when, noChangeLights);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Force the device to go to sleep. Overrides all the wake locks that are
- * held.
- *
- * @param time is used to order this correctly with the wake lock calls.
- * The time should be in the {@link SystemClock#uptimeMillis
- * SystemClock.uptimeMillis()} time base.
- */
- public void goToSleep(long time)
- {
- try {
- mService.goToSleep(time);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * sets the brightness of the backlights (screen, keyboard, button).
- *
- * @param brightness value from 0 to 255
- *
- * {@hide}
- */
- public void setBacklightBrightness(int brightness)
- {
- try {
- mService.setBacklightBrightness(brightness);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Returns the set of flags for {@link #newWakeLock(int, String) newWakeLock()}
- * that are supported on the device.
- * For example, to test to see if the {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK}
- * is supported:
- *
- * {@samplecode
- * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
- * int supportedFlags = pm.getSupportedWakeLockFlags();
- * boolean proximitySupported = ((supportedFlags & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)
- * == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK);
- * }
- *
- * @return the set of supported WakeLock flags.
- *
- * {@hide}
- */
- public int getSupportedWakeLockFlags()
- {
- try {
- return mService.getSupportedWakeLockFlags();
- } catch (RemoteException e) {
- return 0;
- }
- }
-
- /**
- * Returns whether the screen is currently on. The screen could be bright
- * or dim.
- *
- * {@samplecode
- * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
- * boolean isScreenOn = pm.isScreenOn();
- * }
- *
- * @return whether the screen is on (bright or dim).
- */
- public boolean isScreenOn()
- {
- try {
- return mService.isScreenOn();
- } catch (RemoteException e) {
- return false;
- }
}
-
- /**
- * Reboot the device. Will not return if the reboot is
- * successful. Requires the {@link android.Manifest.permission#REBOOT}
- * permission.
- *
- * @param reason code to pass to the kernel (e.g., "recovery") to
- * request special boot modes, or null.
- */
- public void reboot(String reason)
- {
- try {
- mService.reboot(reason);
- } catch (RemoteException e) {
- }
- }
-
- private PowerManager()
- {
- }
-
- /**
- * {@hide}
- */
- public PowerManager(IPowerManager service, Handler handler)
- {
- mService = service;
- mHandler = handler;
- }
-
- /**
- * TODO: It would be nice to be able to set the poke lock here,
- * but I'm not sure what would be acceptable as an interface -
- * either a PokeLock object (like WakeLock) or, possibly just a
- * method call to set the poke lock.
- */
-
- IPowerManager mService;
- Handler mHandler;
}
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index d2050b7..59d0f7a 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -39,11 +39,12 @@ public final class Trace {
public static final long TRACE_TAG_SYNC_MANAGER = 1L << 7;
public static final long TRACE_TAG_AUDIO = 1L << 8;
public static final long TRACE_TAG_VIDEO = 1L << 9;
+ public static final long TRACE_TAG_CAMERA = 1L << 10;
public static final int TRACE_FLAGS_START_BIT = 1;
public static final String[] TRACE_TAGS = {
"Graphics", "Input", "View", "WebView", "Window Manager",
- "Activity Manager", "Sync Manager", "Audio", "Video",
+ "Activity Manager", "Sync Manager", "Audio", "Video", "Camera",
};
public static final String PROPERTY_TRACE_TAG_ENABLEFLAGS = "debug.atrace.tags.enableflags";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a90dd8c..d9f6bf1 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4279,6 +4279,9 @@ public final class Settings {
/** Timeout for package verification. {@hide} */
public static final String PACKAGE_VERIFIER_TIMEOUT = "verifier_timeout";
+ /** Default response code for package verification. {@hide} */
+ public static final String PACKAGE_VERIFIER_DEFAULT_RESPONSE = "verifier_default_response";
+
/** {@hide} */
public static final String
READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT = "read_external_storage_enforced_default";
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 97c0209..6296b11 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -2448,7 +2448,7 @@ public class BluetoothService extends IBluetooth.Stub {
BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
if (state == null) return;
- state.quit();
+ state.doQuit();
mDeviceProfileState.remove(address);
}
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index c783e6a..2411cec 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -29,9 +29,12 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
+import android.os.Binder;
import android.os.Process;
+import android.os.UserId;
import android.provider.Settings;
import android.util.Log;
+import android.util.SparseArray;
import java.util.List;
@@ -48,7 +51,7 @@ public class SearchManagerService extends ISearchManager.Stub {
private final Context mContext;
// This field is initialized lazily in getSearchables(), and then never modified.
- private Searchables mSearchables;
+ private SparseArray<Searchables> mSearchables;
private ContentObserver mGlobalSearchObserver;
@@ -66,14 +69,24 @@ public class SearchManagerService extends ISearchManager.Stub {
mContext.getContentResolver());
}
- private synchronized Searchables getSearchables() {
+ private synchronized Searchables getSearchables(int userId) {
if (mSearchables == null) {
- Log.i(TAG, "Building list of searchable activities");
new MyPackageMonitor().register(mContext, null, true);
- mSearchables = new Searchables(mContext);
- mSearchables.buildSearchableList();
+ mSearchables = new SparseArray<Searchables>();
}
- return mSearchables;
+ Searchables searchables = mSearchables.get(userId);
+
+ long origId = Binder.clearCallingIdentity();
+ boolean userExists = mContext.getPackageManager().getUser(userId) != null;
+ Binder.restoreCallingIdentity(origId);
+
+ if (searchables == null && userExists) {
+ Log.i(TAG, "Building list of searchable activities for userId=" + userId);
+ searchables = new Searchables(mContext, userId);
+ searchables.buildSearchableList();
+ mSearchables.append(userId, searchables);
+ }
+ return searchables;
}
/**
@@ -87,7 +100,7 @@ public class SearchManagerService extends ISearchManager.Stub {
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
mContext.unregisterReceiver(BootCompletedReceiver.this);
- getSearchables();
+ getSearchables(0);
}
}.start();
}
@@ -109,8 +122,12 @@ public class SearchManagerService extends ISearchManager.Stub {
}
private void updateSearchables() {
- // Update list of searchable activities
- getSearchables().buildSearchableList();
+ synchronized (SearchManagerService.this) {
+ // Update list of searchable activities
+ for (int i = 0; i < mSearchables.size(); i++) {
+ getSearchables(mSearchables.keyAt(i)).buildSearchableList();
+ }
+ }
// Inform all listeners that the list of searchables has been updated.
Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
@@ -132,7 +149,11 @@ public class SearchManagerService extends ISearchManager.Stub {
@Override
public void onChange(boolean selfChange) {
- getSearchables().buildSearchableList();
+ synchronized (SearchManagerService.this) {
+ for (int i = 0; i < mSearchables.size(); i++) {
+ getSearchables(mSearchables.keyAt(i)).buildSearchableList();
+ }
+ }
Intent intent = new Intent(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
mContext.sendBroadcast(intent);
@@ -156,32 +177,32 @@ public class SearchManagerService extends ISearchManager.Stub {
Log.e(TAG, "getSearchableInfo(), activity == null");
return null;
}
- return getSearchables().getSearchableInfo(launchActivity);
+ return getSearchables(UserId.getCallingUserId()).getSearchableInfo(launchActivity);
}
/**
* Returns a list of the searchable activities that can be included in global search.
*/
public List<SearchableInfo> getSearchablesInGlobalSearch() {
- return getSearchables().getSearchablesInGlobalSearchList();
+ return getSearchables(UserId.getCallingUserId()).getSearchablesInGlobalSearchList();
}
public List<ResolveInfo> getGlobalSearchActivities() {
- return getSearchables().getGlobalSearchActivities();
+ return getSearchables(UserId.getCallingUserId()).getGlobalSearchActivities();
}
/**
* Gets the name of the global search activity.
*/
public ComponentName getGlobalSearchActivity() {
- return getSearchables().getGlobalSearchActivity();
+ return getSearchables(UserId.getCallingUserId()).getGlobalSearchActivity();
}
/**
* Gets the name of the web search activity.
*/
public ComponentName getWebSearchActivity() {
- return getSearchables().getWebSearchActivity();
+ return getSearchables(UserId.getCallingUserId()).getWebSearchActivity();
}
}
diff --git a/core/java/android/server/search/Searchables.java b/core/java/android/server/search/Searchables.java
index f24d52f..4e00ef9 100644
--- a/core/java/android/server/search/Searchables.java
+++ b/core/java/android/server/search/Searchables.java
@@ -16,6 +16,7 @@
package android.server.search;
+import android.app.AppGlobals;
import android.app.SearchManager;
import android.app.SearchableInfo;
import android.content.ComponentName;
@@ -23,9 +24,11 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
+import android.os.RemoteException;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
@@ -38,6 +41,7 @@ import java.util.List;
/**
* This class maintains the information about all searchable activities.
+ * This is a hidden class.
*/
public class Searchables {
@@ -65,12 +69,18 @@ public class Searchables {
public static String ENHANCED_GOOGLE_SEARCH_COMPONENT_NAME =
"com.google.android.providers.enhancedgooglesearch/.Launcher";
+ // Cache the package manager instance
+ private IPackageManager mPm;
+ // User for which this Searchables caches information
+ private int mUserId;
+
/**
*
* @param context Context to use for looking up activities etc.
*/
- public Searchables (Context context) {
+ public Searchables (Context context, int userId) {
mContext = context;
+ mUserId = userId;
}
/**
@@ -195,16 +205,14 @@ public class Searchables {
ArrayList<SearchableInfo> newSearchablesInGlobalSearchList
= new ArrayList<SearchableInfo>();
- final PackageManager pm = mContext.getPackageManager();
-
// Use intent resolver to generate list of ACTION_SEARCH & ACTION_WEB_SEARCH receivers.
List<ResolveInfo> searchList;
final Intent intent = new Intent(Intent.ACTION_SEARCH);
- searchList = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
+ searchList = queryIntentActivities(intent, PackageManager.GET_META_DATA);
List<ResolveInfo> webSearchInfoList;
final Intent webSearchIntent = new Intent(Intent.ACTION_WEB_SEARCH);
- webSearchInfoList = pm.queryIntentActivities(webSearchIntent, PackageManager.GET_META_DATA);
+ webSearchInfoList = queryIntentActivities(webSearchIntent, PackageManager.GET_META_DATA);
// analyze each one, generate a Searchables record, and record
if (searchList != null || webSearchInfoList != null) {
@@ -262,10 +270,8 @@ public class Searchables {
// Step 1 : Query the package manager for a list
// of activities that can handle the GLOBAL_SEARCH intent.
Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
- PackageManager pm = mContext.getPackageManager();
List<ResolveInfo> activities =
- pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
-
+ queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (activities != null && !activities.isEmpty()) {
// Step 2: Rank matching activities according to our heuristics.
Collections.sort(activities, GLOBAL_SEARCH_RANKER);
@@ -301,10 +307,8 @@ public class Searchables {
Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
intent.setComponent(globalSearch);
- PackageManager pm = mContext.getPackageManager();
- List<ResolveInfo> activities =
- pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
-
+ List<ResolveInfo> activities = queryIntentActivities(intent,
+ PackageManager.MATCH_DEFAULT_ONLY);
if (activities != null && !activities.isEmpty()) {
return true;
}
@@ -374,9 +378,8 @@ public class Searchables {
}
Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
intent.setPackage(globalSearchActivity.getPackageName());
- PackageManager pm = mContext.getPackageManager();
List<ResolveInfo> activities =
- pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (activities != null && !activities.isEmpty()) {
ActivityInfo ai = activities.get(0).activityInfo;
@@ -387,6 +390,22 @@ public class Searchables {
return null;
}
+ private List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
+ if (mPm == null) {
+ mPm = AppGlobals.getPackageManager();
+ }
+ List<ResolveInfo> activities = null;
+ try {
+ activities =
+ mPm.queryIntentActivities(intent,
+ intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+ flags, mUserId);
+ } catch (RemoteException re) {
+ // Local call
+ }
+ return activities;
+ }
+
/**
* Returns the list of searchable activities.
*/
diff --git a/core/java/android/text/TextDirectionHeuristics.java b/core/java/android/text/TextDirectionHeuristics.java
index be2840b..bbaa173 100644
--- a/core/java/android/text/TextDirectionHeuristics.java
+++ b/core/java/android/text/TextDirectionHeuristics.java
@@ -22,6 +22,7 @@ import android.view.View;
/**
* Some objects that implement TextDirectionHeuristic.
+ *
* @hide
*/
public class TextDirectionHeuristics {
diff --git a/core/java/android/util/LocaleUtil.java b/core/java/android/util/LocaleUtil.java
index 93f5cd3..60526e1 100644
--- a/core/java/android/util/LocaleUtil.java
+++ b/core/java/android/util/LocaleUtil.java
@@ -24,7 +24,6 @@ import libcore.icu.ICU;
/**
* Various utilities for Locales
*
- * @hide
*/
public class LocaleUtil {
@@ -41,8 +40,7 @@ public class LocaleUtil {
* {@link View#LAYOUT_DIRECTION_LTR} or
* {@link View#LAYOUT_DIRECTION_RTL}.
*
- * Warning: this code does not support vertical scripts.
- * @hide
+ * Be careful: this code will need to be updated when vertical scripts will be supported
*/
public static int getLayoutDirectionFromLocale(Locale locale) {
if (locale != null && !locale.equals(Locale.ROOT)) {
@@ -68,7 +66,8 @@ public class LocaleUtil {
* {@link View#LAYOUT_DIRECTION_LTR} or
* {@link View#LAYOUT_DIRECTION_RTL}.
*
- * Warning: this code does not support vertical scripts.
+ * Be careful: this code will need to be updated when vertical scripts will be supported
+ *
* @hide
*/
private static int getLayoutDirectionFromFirstChar(Locale locale) {
diff --git a/core/java/android/view/Gravity.java b/core/java/android/view/Gravity.java
index 4547aa6..f031fe7 100644
--- a/core/java/android/view/Gravity.java
+++ b/core/java/android/view/Gravity.java
@@ -155,7 +155,6 @@ public class Gravity
*
* @see {@link View#LAYOUT_DIRECTION_LTR}
* @see {@link View#LAYOUT_DIRECTION_RTL}
- * @hide
*/
public static void apply(int gravity, int w, int h, Rect container,
Rect outRect, int layoutDirection) {
@@ -293,7 +292,6 @@ public class Gravity
*
* @see {@link View#LAYOUT_DIRECTION_LTR}
* @see {@link View#LAYOUT_DIRECTION_RTL}
- * @hide
*/
public static void apply(int gravity, int w, int h, Rect container,
int xAdj, int yAdj, Rect outRect, int layoutDirection) {
@@ -374,7 +372,6 @@ public class Gravity
*
* @see {@link View#LAYOUT_DIRECTION_LTR}
* @see {@link View#LAYOUT_DIRECTION_RTL}
- * @hide
*/
public static void applyDisplay(int gravity, Rect display, Rect inoutObj, int layoutDirection) {
int absGravity = getAbsoluteGravity(gravity, layoutDirection);
@@ -411,7 +408,6 @@ public class Gravity
* @param gravity The gravity to convert to absolute (horizontal) values.
* @param layoutDirection The layout direction.
* @return gravity converted to absolute (horizontal) values.
- * @hide
*/
public static int getAbsoluteGravity(int gravity, int layoutDirection) {
int result = gravity;
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 26a5b26..f692e05 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -20,6 +20,7 @@ import android.graphics.Canvas;
import android.os.Handler;
import android.os.Message;
import android.widget.FrameLayout;
+import com.android.internal.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -43,20 +44,20 @@ import java.util.HashMap;
*
* <pre>LayoutInflater inflater = (LayoutInflater)context.getSystemService
* (Context.LAYOUT_INFLATER_SERVICE);</pre>
- *
+ *
* <p>
* To create a new LayoutInflater with an additional {@link Factory} for your
* own views, you can use {@link #cloneInContext} to clone an existing
* ViewFactory, and then call {@link #setFactory} on it to include your
* Factory.
- *
+ *
* <p>
* For performance reasons, view inflation relies heavily on pre-processing of
* XML files that is done at build time. Therefore, it is not currently possible
* to use LayoutInflater with an XmlPullParser over a plain XML file at runtime;
* it only works with an XmlPullParser returned from a compiled resource
* (R.<em>something</em> file.)
- *
+ *
* @see Context#getSystemService
*/
public abstract class LayoutInflater {
@@ -82,7 +83,7 @@ public abstract class LayoutInflater {
private static final HashMap<String, Constructor<? extends View>> sConstructorMap =
new HashMap<String, Constructor<? extends View>>();
-
+
private HashMap<String, Boolean> mFilterMap;
private static final String TAG_MERGE = "merge";
@@ -93,36 +94,36 @@ public abstract class LayoutInflater {
/**
* Hook to allow clients of the LayoutInflater to restrict the set of Views that are allowed
* to be inflated.
- *
+ *
*/
public interface Filter {
/**
* Hook to allow clients of the LayoutInflater to restrict the set of Views
* that are allowed to be inflated.
- *
+ *
* @param clazz The class object for the View that is about to be inflated
- *
+ *
* @return True if this class is allowed to be inflated, or false otherwise
*/
@SuppressWarnings("unchecked")
boolean onLoadClass(Class clazz);
}
-
+
public interface Factory {
/**
* Hook you can supply that is called when inflating from a LayoutInflater.
* You can use this to customize the tag names available in your XML
* layout files.
- *
+ *
* <p>
* Note that it is good practice to prefix these custom names with your
* package (i.e., com.coolcompany.apps) to avoid conflicts with system
* names.
- *
+ *
* @param name Tag name to be inflated.
* @param context The context the view is being created in.
* @param attrs Inflation attributes as specified in XML file.
- *
+ *
* @return View Newly created view. Return null for the default
* behavior.
*/
@@ -150,14 +151,14 @@ public abstract class LayoutInflater {
private static class FactoryMerger implements Factory2 {
private final Factory mF1, mF2;
private final Factory2 mF12, mF22;
-
+
FactoryMerger(Factory f1, Factory2 f12, Factory f2, Factory2 f22) {
mF1 = f1;
mF2 = f2;
mF12 = f12;
mF22 = f22;
}
-
+
public View onCreateView(String name, Context context, AttributeSet attrs) {
View v = mF1.onCreateView(name, context, attrs);
if (v != null) return v;
@@ -172,13 +173,13 @@ public abstract class LayoutInflater {
: mF2.onCreateView(name, context, attrs);
}
}
-
+
/**
* Create a new LayoutInflater instance associated with a particular Context.
* Applications will almost always want to use
* {@link Context#getSystemService Context.getSystemService()} to retrieve
* the standard {@link Context#LAYOUT_INFLATER_SERVICE Context.INFLATER_SERVICE}.
- *
+ *
* @param context The Context in which this LayoutInflater will create its
* Views; most importantly, this supplies the theme from which the default
* values for their attributes are retrieved.
@@ -191,7 +192,7 @@ public abstract class LayoutInflater {
* Create a new LayoutInflater instance that is a copy of an existing
* LayoutInflater, optionally with its Context changed. For use in
* implementing {@link #cloneInContext}.
- *
+ *
* @param original The original LayoutInflater to copy.
* @param newContext The new Context to use.
*/
@@ -202,7 +203,7 @@ public abstract class LayoutInflater {
mPrivateFactory = original.mPrivateFactory;
mFilter = original.mFilter;
}
-
+
/**
* Obtains the LayoutInflater from the given context.
*/
@@ -220,15 +221,15 @@ public abstract class LayoutInflater {
* pointing to a different Context than the original. This is used by
* {@link ContextThemeWrapper} to create a new LayoutInflater to go along
* with the new Context theme.
- *
+ *
* @param newContext The new Context to associate with the new LayoutInflater.
* May be the same as the original Context if desired.
- *
+ *
* @return Returns a brand spanking new LayoutInflater object associated with
* the given Context.
*/
public abstract LayoutInflater cloneInContext(Context newContext);
-
+
/**
* Return the context we are running in, for access to resources, class
* loader, etc.
@@ -264,7 +265,7 @@ public abstract class LayoutInflater {
* called on each element name as the xml is parsed. If the factory returns
* a View, that is added to the hierarchy. If it returns null, the next
* factory default {@link #onCreateView} method is called.
- *
+ *
* <p>If you have an existing
* LayoutInflater and want to add your own factory to it, use
* {@link #cloneInContext} to clone the existing instance and then you
@@ -320,13 +321,13 @@ public abstract class LayoutInflater {
public Filter getFilter() {
return mFilter;
}
-
+
/**
* Sets the {@link Filter} to by this LayoutInflater. If a view is attempted to be inflated
* which is not allowed by the {@link Filter}, the {@link #inflate(int, ViewGroup)} call will
* throw an {@link InflateException}. This filter will replace any previous filter set on this
* LayoutInflater.
- *
+ *
* @param filter The Filter which restricts the set of Views that are allowed to be inflated.
* This filter will replace any previous filter set on this LayoutInflater.
*/
@@ -340,7 +341,7 @@ public abstract class LayoutInflater {
/**
* Inflate a new view hierarchy from the specified xml resource. Throws
* {@link InflateException} if there is an error.
- *
+ *
* @param resource ID for an XML layout resource to load (e.g.,
* <code>R.layout.main_page</code>)
* @param root Optional view to be the parent of the generated hierarchy.
@@ -360,7 +361,7 @@ public abstract class LayoutInflater {
* reasons, view inflation relies heavily on pre-processing of XML files
* that is done at build time. Therefore, it is not currently possible to
* use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
- *
+ *
* @param parser XML dom node containing the description of the view
* hierarchy.
* @param root Optional view to be the parent of the generated hierarchy.
@@ -375,7 +376,7 @@ public abstract class LayoutInflater {
/**
* Inflate a new view hierarchy from the specified xml resource. Throws
* {@link InflateException} if there is an error.
- *
+ *
* @param resource ID for an XML layout resource to load (e.g.,
* <code>R.layout.main_page</code>)
* @param root Optional view to be the parent of the generated hierarchy (if
@@ -407,7 +408,7 @@ public abstract class LayoutInflater {
* reasons, view inflation relies heavily on pre-processing of XML files
* that is done at build time. Therefore, it is not currently possible to
* use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
- *
+ *
* @param parser XML dom node containing the description of the view
* hierarchy.
* @param root Optional view to be the parent of the generated hierarchy (if
@@ -442,7 +443,7 @@ public abstract class LayoutInflater {
}
final String name = parser.getName();
-
+
if (DEBUG) {
System.out.println("**************************");
System.out.println("Creating root view: "
@@ -528,17 +529,17 @@ public abstract class LayoutInflater {
* Low-level function for instantiating a view by name. This attempts to
* instantiate a view class of the given <var>name</var> found in this
* LayoutInflater's ClassLoader.
- *
+ *
* <p>
* There are two things that can happen in an error case: either the
* exception describing the error will be thrown, or a null will be
* returned. You must deal with both possibilities -- the former will happen
* the first time createView() is called for a class of a particular name,
* the latter every time there-after for that class name.
- *
+ *
* @param name The full name of the class to be instantiated.
* @param attrs The XML attributes supplied for this instance.
- *
+ *
* @return View The newly instantiated view, or null.
*/
public final View createView(String name, String prefix, AttributeSet attrs)
@@ -551,7 +552,7 @@ public abstract class LayoutInflater {
// Class not found in the cache, see if it's real, and try to add it
clazz = mContext.getClassLoader().loadClass(
prefix != null ? (prefix + name) : name).asSubclass(View.class);
-
+
if (mFilter != null && clazz != null) {
boolean allowed = mFilter.onLoadClass(clazz);
if (!allowed) {
@@ -569,7 +570,7 @@ public abstract class LayoutInflater {
// New class -- remember whether it is allowed
clazz = mContext.getClassLoader().loadClass(
prefix != null ? (prefix + name) : name).asSubclass(View.class);
-
+
boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
mFilterMap.put(name, allowed);
if (!allowed) {
@@ -632,10 +633,10 @@ public abstract class LayoutInflater {
* given the xml element name. Override it to handle custom view objects. If
* you override this in your subclass be sure to call through to
* super.onCreateView(name) for names you do not recognize.
- *
+ *
* @param name The fully qualified class name of the View to be create.
* @param attrs An AttributeSet of attributes to apply to the View.
- *
+ *
* @return View The View created.
*/
protected View onCreateView(String name, AttributeSet attrs)
@@ -679,7 +680,7 @@ public abstract class LayoutInflater {
if (view == null && mPrivateFactory != null) {
view = mPrivateFactory.onCreateView(parent, name, mContext, attrs);
}
-
+
if (view == null) {
if (-1 == name.indexOf('.')) {
view = onCreateView(parent, name, attrs);
@@ -726,7 +727,7 @@ public abstract class LayoutInflater {
}
final String name = parser.getName();
-
+
if (TAG_REQUEST_FOCUS.equals(name)) {
parseRequestFocus(parser, parent);
} else if (TAG_INCLUDE.equals(name)) {
@@ -741,7 +742,7 @@ public abstract class LayoutInflater {
final ViewGroup viewGroup = (ViewGroup) parent;
final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
rInflate(parser, view, attrs, true);
- viewGroup.addView(view, params);
+ viewGroup.addView(view, params);
} else {
final View view = createViewFromTag(parent, name, attrs);
final ViewGroup viewGroup = (ViewGroup) parent;
@@ -810,21 +811,14 @@ public abstract class LayoutInflater {
// We try to load the layout params set in the <include /> tag. If
// they don't exist, we will rely on the layout params set in the
// included XML file.
- // During a layoutparams generation, a runtime exception is thrown
- // if either layout_width or layout_height is missing. We catch
- // this exception and set localParams accordingly: true means we
- // successfully loaded layout params from the <include /> tag,
- // false means we need to rely on the included layout params.
- ViewGroup.LayoutParams params = null;
- try {
- params = group.generateLayoutParams(attrs);
- } catch (RuntimeException e) {
- params = group.generateLayoutParams(childAttrs);
- } finally {
- if (params != null) {
- view.setLayoutParams(params);
- }
- }
+ TypedArray ta = getContext().obtainStyledAttributes(attrs,
+ R.styleable.ViewGroup_Layout);
+ boolean definesBothWidthAndHeight =
+ ta.hasValue(R.styleable.ViewGroup_Layout_layout_width) &&
+ ta.hasValue(R.styleable.ViewGroup_Layout_layout_height);
+ AttributeSet attributes = definesBothWidthAndHeight ? attrs : childAttrs;
+ view.setLayoutParams(group.generateLayoutParams(attributes));
+ ta.recycle();
// Inflate all children.
rInflate(childParser, view, childAttrs, true);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index fa555d2..a6a5427 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -343,9 +343,10 @@ import java.util.concurrent.CopyOnWriteArrayList;
* Padding can be used to offset the content of the view by a specific amount of
* pixels. For instance, a left padding of 2 will push the view's content by
* 2 pixels to the right of the left edge. Padding can be set using the
- * {@link #setPadding(int, int, int, int)} method and queried by calling
- * {@link #getPaddingLeft()}, {@link #getPaddingTop()}, {@link #getPaddingRight()},
- * {@link #getPaddingBottom()}.
+ * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
+ * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
+ * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
+ * {@link #getPaddingEnd()}.
* </p>
*
* <p>
@@ -627,6 +628,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
* @attr ref android.R.styleable#View_paddingLeft
* @attr ref android.R.styleable#View_paddingRight
* @attr ref android.R.styleable#View_paddingTop
+ * @attr ref android.R.styleable#View_paddingStart
+ * @attr ref android.R.styleable#View_paddingEnd
* @attr ref android.R.styleable#View_saveEnabled
* @attr ref android.R.styleable#View_rotation
* @attr ref android.R.styleable#View_rotationX
@@ -648,6 +651,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
* @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
* @attr ref android.R.styleable#View_soundEffectsEnabled
* @attr ref android.R.styleable#View_tag
+ * @attr ref android.R.styleable#View_textAlignment
* @attr ref android.R.styleable#View_transformPivotX
* @attr ref android.R.styleable#View_transformPivotY
* @attr ref android.R.styleable#View_translationX
@@ -656,7 +660,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
*
* @see android.view.ViewGroup
*/
-public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Callback,
+public class View implements Drawable.Callback, KeyEvent.Callback,
AccessibilityEventSource {
private static final boolean DBG = false;
@@ -1801,28 +1805,24 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/**
* Horizontal layout direction of this view is from Left to Right.
* Use with {@link #setLayoutDirection}.
- * @hide
*/
public static final int LAYOUT_DIRECTION_LTR = 0;
/**
* Horizontal layout direction of this view is from Right to Left.
* Use with {@link #setLayoutDirection}.
- * @hide
*/
public static final int LAYOUT_DIRECTION_RTL = 1;
/**
* Horizontal layout direction of this view is inherited from its parent.
* Use with {@link #setLayoutDirection}.
- * @hide
*/
public static final int LAYOUT_DIRECTION_INHERIT = 2;
/**
* Horizontal layout direction of this view is from deduced from the default language
* script for the locale. Use with {@link #setLayoutDirection}.
- * @hide
*/
public static final int LAYOUT_DIRECTION_LOCALE = 3;
@@ -1887,7 +1887,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/**
* Text direction is inherited thru {@link ViewGroup}
- * @hide
*/
public static final int TEXT_DIRECTION_INHERIT = 0;
@@ -1895,7 +1894,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Text direction is using "first strong algorithm". The first strong directional character
* determines the paragraph direction. If there is no strong directional character, the
* paragraph direction is the view's resolved layout direction.
- * @hide
*/
public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
@@ -1903,31 +1901,26 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
* any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
* If there are neither, the paragraph direction is the view's resolved layout direction.
- * @hide
*/
public static final int TEXT_DIRECTION_ANY_RTL = 2;
/**
* Text direction is forced to LTR.
- * @hide
*/
public static final int TEXT_DIRECTION_LTR = 3;
/**
* Text direction is forced to RTL.
- * @hide
*/
public static final int TEXT_DIRECTION_RTL = 4;
/**
* Text direction is coming from the system Locale.
- * @hide
*/
public static final int TEXT_DIRECTION_LOCALE = 5;
/**
* Default text direction is inherited
- * @hide
*/
protected static int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
@@ -1985,7 +1978,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/*
* Default text alignment. The text alignment of this View is inherited from its parent.
* Use with {@link #setTextAlignment(int)}
- * @hide
*/
public static final int TEXT_ALIGNMENT_INHERIT = 0;
@@ -1994,7 +1986,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
*
* Use with {@link #setTextAlignment(int)}
- * @hide
*/
public static final int TEXT_ALIGNMENT_GRAVITY = 1;
@@ -2002,7 +1993,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Align to the start of the paragraph, e.g. ALIGN_NORMAL.
*
* Use with {@link #setTextAlignment(int)}
- * @hide
*/
public static final int TEXT_ALIGNMENT_TEXT_START = 2;
@@ -2010,7 +2000,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
*
* Use with {@link #setTextAlignment(int)}
- * @hide
*/
public static final int TEXT_ALIGNMENT_TEXT_END = 3;
@@ -2018,7 +2007,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Center the paragraph, e.g. ALIGN_CENTER.
*
* Use with {@link #setTextAlignment(int)}
- * @hide
*/
public static final int TEXT_ALIGNMENT_CENTER = 4;
@@ -2027,7 +2015,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* layoutDirection is LTR, and ALIGN_RIGHT otherwise.
*
* Use with {@link #setTextAlignment(int)}
- * @hide
*/
public static final int TEXT_ALIGNMENT_VIEW_START = 5;
@@ -2036,13 +2023,11 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* layoutDirection is LTR, and ALIGN_LEFT otherwise.
*
* Use with {@link #setTextAlignment(int)}
- * @hide
*/
public static final int TEXT_ALIGNMENT_VIEW_END = 6;
/**
* Default text alignment is inherited
- * @hide
*/
protected static int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
@@ -3881,6 +3866,15 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
}
+ // Apply layout direction to the new Drawables if needed
+ final int layoutDirection = getResolvedLayoutDirection();
+ if (track != null) {
+ track.setLayoutDirection(layoutDirection);
+ }
+ if (thumb != null) {
+ thumb.setLayoutDirection(layoutDirection);
+ }
+
// Re-apply user/background padding so that scrollbar(s) get added
resolvePadding();
}
@@ -5652,9 +5646,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* {@link #LAYOUT_DIRECTION_RTL},
* {@link #LAYOUT_DIRECTION_INHERIT} or
* {@link #LAYOUT_DIRECTION_LOCALE}.
- *
* @attr ref android.R.styleable#View_layoutDirection
- * @hide
*/
@ViewDebug.ExportedProperty(category = "layout", mapping = {
@ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "LTR"),
@@ -5676,7 +5668,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* {@link #LAYOUT_DIRECTION_LOCALE}.
*
* @attr ref android.R.styleable#View_layoutDirection
- * @hide
*/
@RemotableViewMethod
public void setLayoutDirection(int layoutDirection) {
@@ -5696,7 +5687,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
*
* @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
* {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
- * @hide
*/
@ViewDebug.ExportedProperty(category = "layout", mapping = {
@ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
@@ -5716,7 +5706,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* layout attribute and/or the inherited value from the parent
*
* @return true if the layout is right-to-left.
- * @hide
*/
@ViewDebug.ExportedProperty(category = "layout")
public boolean isLayoutRtl() {
@@ -11495,7 +11484,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
* that the parent directionality can and will be resolved before its children.
* Will call {@link View#onResolvedLayoutDirectionChanged} when resolution is done.
- * @hide
*/
public void resolveLayoutDirection() {
// Clear any previous layout direction resolution
@@ -11540,14 +11528,12 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Called when layout direction has been resolved.
*
* The default implementation does nothing.
- * @hide
*/
public void onResolvedLayoutDirectionChanged() {
}
/**
* Resolve padding depending on layout direction.
- * @hide
*/
public void resolvePadding() {
// If the user specified the absolute padding (either with android:padding or
@@ -11607,7 +11593,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
*
* @see {@link #LAYOUT_DIRECTION_LTR}
* @see {@link #LAYOUT_DIRECTION_RTL}
- * @hide
*/
public void onPaddingChanged(int layoutDirection) {
}
@@ -11616,7 +11601,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Check if layout direction resolution can be done.
*
* @return true if layout direction resolution can be done otherwise return false.
- * @hide
*/
public boolean canResolveLayoutDirection() {
switch (getLayoutDirection()) {
@@ -11630,7 +11614,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/**
* Reset the resolved layout direction. Will call {@link View#onResolvedLayoutDirectionReset}
* when reset is done.
- * @hide
*/
public void resetResolvedLayoutDirection() {
// Reset the current resolved bits
@@ -11647,7 +11630,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* resolved layout direction, or to inform child views that inherit their layout direction.
*
* The default implementation does nothing.
- * @hide
*/
public void onResolvedLayoutDirectionReset() {
}
@@ -11657,7 +11639,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
*
* @param locale Locale to check
* @return true if the Locale uses an RTL script.
- * @hide
*/
protected static boolean isLayoutDirectionRtl(Locale locale) {
return (LAYOUT_DIRECTION_RTL == LocaleUtil.getLayoutDirectionFromLocale(locale));
@@ -13963,13 +13944,29 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
/**
- * Return the layout direction of a given Drawable.
- *
- * @param who the Drawable to query
- * @hide
- */
- public int getResolvedLayoutDirection(Drawable who) {
- return (who == mBackground) ? getResolvedLayoutDirection() : LAYOUT_DIRECTION_DEFAULT;
+ * Resolve the Drawables depending on the layout direction. This is implicitly supposing
+ * that the View directionality can and will be resolved before its Drawables.
+ *
+ * Will call {@link View#onResolveDrawables} when resolution is done.
+ */
+ public void resolveDrawables() {
+ if (mBackground != null) {
+ mBackground.setLayoutDirection(getResolvedLayoutDirection());
+ }
+ onResolveDrawables(getResolvedLayoutDirection());
+ }
+
+ /**
+ * Called when layout direction has been resolved.
+ *
+ * The default implementation does nothing.
+ *
+ * @param layoutDirection The resolved layout direction.
+ *
+ * @see {@link #LAYOUT_DIRECTION_LTR}
+ * @see {@link #LAYOUT_DIRECTION_RTL}
+ */
+ public void onResolveDrawables(int layoutDirection) {
}
/**
@@ -14238,8 +14235,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
padding = new Rect();
sThreadLocal.set(padding);
}
+ background.setLayoutDirection(getResolvedLayoutDirection());
if (background.getPadding(padding)) {
- switch (background.getResolvedLayoutDirectionSelf()) {
+ switch (background.getLayoutDirection()) {
case LAYOUT_DIRECTION_RTL:
setPadding(padding.right, padding.top, padding.left, padding.bottom);
break;
@@ -14402,13 +14400,19 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/**
* Sets the relative padding. The view may add on the space required to display
* the scrollbars, depending on the style and visibility of the scrollbars.
+ * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
+ * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
* from the values set in this call.
*
+ * @attr ref android.R.styleable#View_padding
+ * @attr ref android.R.styleable#View_paddingBottom
+ * @attr ref android.R.styleable#View_paddingStart
+ * @attr ref android.R.styleable#View_paddingEnd
+ * @attr ref android.R.styleable#View_paddingTop
* @param start the start padding in pixels
* @param top the top padding in pixels
* @param end the end padding in pixels
* @param bottom the bottom padding in pixels
- * @hide
*/
public void setPaddingRelative(int start, int top, int end, int bottom) {
mUserPaddingStart = start;
@@ -14462,7 +14466,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* required to display the scrollbars as well.
*
* @return the start padding in pixels
- * @hide
*/
public int getPaddingStart() {
return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
@@ -14486,7 +14489,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* required to display the scrollbars as well.
*
* @return the end padding in pixels
- * @hide
*/
public int getPaddingEnd() {
return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
@@ -14495,10 +14497,11 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/**
* Return if the padding as been set thru relative values
- * {@link #setPaddingRelative(int, int, int, int)}
+ * {@link #setPaddingRelative(int, int, int, int)} or thru
+ * @attr ref android.R.styleable#View_paddingStart or
+ * @attr ref android.R.styleable#View_paddingEnd
*
* @return true if the padding is relative or false if it is not.
- * @hide
*/
public boolean isPaddingRelative() {
return mUserPaddingRelative;
@@ -16297,7 +16300,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* {@link #TEXT_DIRECTION_LTR},
* {@link #TEXT_DIRECTION_RTL},
* {@link #TEXT_DIRECTION_LOCALE}
- * @hide
*/
@ViewDebug.ExportedProperty(category = "text", mapping = {
@ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
@@ -16322,7 +16324,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* {@link #TEXT_DIRECTION_LTR},
* {@link #TEXT_DIRECTION_RTL},
* {@link #TEXT_DIRECTION_LOCALE}
- * @hide
*/
public void setTextDirection(int textDirection) {
if (getTextDirection() != textDirection) {
@@ -16352,7 +16353,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* {@link #TEXT_DIRECTION_LTR},
* {@link #TEXT_DIRECTION_RTL},
* {@link #TEXT_DIRECTION_LOCALE}
- * @hide
*/
public int getResolvedTextDirection() {
// The text direction will be resolved only if needed
@@ -16365,7 +16365,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/**
* Resolve the text direction. Will call {@link View#onResolvedTextDirectionChanged} when
* resolution is done.
- * @hide
*/
public void resolveTextDirection() {
// Reset any previous text direction resolution
@@ -16426,7 +16425,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* resolution should override this method.
*
* The default implementation does nothing.
- * @hide
*/
public void onResolvedTextDirectionChanged() {
}
@@ -16435,7 +16433,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Check if text direction resolution can be done.
*
* @return true if text direction resolution can be done otherwise return false.
- * @hide
*/
public boolean canResolveTextDirection() {
switch (getTextDirection()) {
@@ -16450,7 +16447,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Reset resolved text direction. Text direction can be resolved with a call to
* getResolvedTextDirection(). Will call {@link View#onResolvedTextDirectionReset} when
* reset is done.
- * @hide
*/
public void resetResolvedTextDirection() {
mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
@@ -16461,7 +16457,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Called when text direction is reset. Subclasses that care about text direction reset should
* override this method and do a reset of the text direction of their children. The default
* implementation does nothing.
- * @hide
*/
public void onResolvedTextDirectionReset() {
}
@@ -16479,7 +16474,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* {@link #TEXT_ALIGNMENT_TEXT_END},
* {@link #TEXT_ALIGNMENT_VIEW_START},
* {@link #TEXT_ALIGNMENT_VIEW_END}
- * @hide
*/
@ViewDebug.ExportedProperty(category = "text", mapping = {
@ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
@@ -16508,7 +16502,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* {@link #TEXT_ALIGNMENT_VIEW_END}
*
* @attr ref android.R.styleable#View_textAlignment
- * @hide
*/
public void setTextAlignment(int textAlignment) {
if (textAlignment != getTextAlignment()) {
@@ -16538,7 +16531,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* {@link #TEXT_ALIGNMENT_TEXT_END},
* {@link #TEXT_ALIGNMENT_VIEW_START},
* {@link #TEXT_ALIGNMENT_VIEW_END}
- * @hide
*/
@ViewDebug.ExportedProperty(category = "text", mapping = {
@ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
@@ -16560,7 +16552,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/**
* Resolve the text alignment. Will call {@link View#onResolvedTextAlignmentChanged} when
* resolution is done.
- * @hide
*/
public void resolveTextAlignment() {
// Reset any previous text alignment resolution
@@ -16625,7 +16616,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Check if text alignment resolution can be done.
*
* @return true if text alignment resolution can be done otherwise return false.
- * @hide
*/
public boolean canResolveTextAlignment() {
switch (getTextAlignment()) {
@@ -16641,7 +16631,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* resolution should override this method.
*
* The default implementation does nothing.
- * @hide
*/
public void onResolvedTextAlignmentChanged() {
}
@@ -16650,7 +16639,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Reset resolved text alignment. Text alignment can be resolved with a call to
* getResolvedTextAlignment(). Will call {@link View#onResolvedTextAlignmentReset} when
* reset is done.
- * @hide
*/
public void resetResolvedTextAlignment() {
// Reset any previous text alignment resolution
@@ -16662,7 +16650,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Called when text alignment is reset. Subclasses that care about text alignment reset should
* override this method and do a reset of the text alignment of their children. The default
* implementation does nothing.
- * @hide
*/
public void onResolvedTextAlignmentReset() {
}
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index dd671dc..00d4fc7 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -255,6 +255,35 @@ public class ViewDebug {
boolean retrieveReturn() default false;
}
+ /**
+ * Allows a View to inject custom children into HierarchyViewer. For example,
+ * WebView uses this to add its internal layer tree as a child to itself
+ * @hide
+ */
+ public interface HierarchyHandler {
+ /**
+ * Dumps custom children to hierarchy viewer.
+ * See ViewDebug.dumpViewWithProperties(Context, View, BufferedWriter, int)
+ * for the format
+ *
+ * An empty implementation should simply do nothing
+ *
+ * @param out The output writer
+ * @param level The indentation level
+ */
+ public void dumpViewHierarchyWithProperties(BufferedWriter out, int level);
+
+ /**
+ * Returns a View to enable grabbing screenshots from custom children
+ * returned in dumpViewHierarchyWithProperties.
+ *
+ * @param className The className of the view to find
+ * @param hashCode The hashCode of the view to find
+ * @return the View to capture from, or null if not found
+ */
+ public View findHierarchyView(String className, int hashCode);
+ }
+
private static HashMap<Class<?>, Method[]> mCapturedViewMethodsForClasses = null;
private static HashMap<Class<?>, Field[]> mCapturedViewFieldsForClasses = null;
@@ -759,6 +788,13 @@ public class ViewDebug {
} else if (isRequestedView(view, className, hashCode)) {
return view;
}
+ if (view instanceof HierarchyHandler) {
+ final View found = ((HierarchyHandler)view)
+ .findHierarchyView(className, hashCode);
+ if (found != null) {
+ return found;
+ }
+ }
}
return null;
@@ -783,6 +819,9 @@ public class ViewDebug {
dumpViewWithProperties(context, view, out, level + 1);
}
}
+ if (group instanceof HierarchyHandler) {
+ ((HierarchyHandler)group).dumpViewHierarchyWithProperties(out, level + 1);
+ }
}
private static boolean dumpViewWithProperties(Context context, View view,
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 044627c..257b861 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5243,9 +5243,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
}
- /**
- * @hide
- */
@Override
public void onResolvedLayoutDirectionReset() {
// Take care of resetting the children resolution too
@@ -5258,9 +5255,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
}
- /**
- * @hide
- */
@Override
public void onResolvedTextDirectionReset() {
// Take care of resetting the children resolution too
@@ -5273,9 +5267,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
}
- /**
- * @hide
- */
@Override
public void onResolvedTextAlignmentReset() {
// Take care of resetting the children resolution too
@@ -5446,15 +5437,19 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
/**
- * Extracts the layout parameters from the supplied attributes.
+ * Extracts the <code>width</code> and <code>height</code> layout parameters
+ * from the supplied TypedArray, <code>a</code>, and assigns them
+ * to the appropriate fields. If, <code>a</code>, does not contain an
+ * entry for either attribute, the value, {@link ViewGroup.LayoutParams#WRAP_CONTENT},
+ * is used as a default.
*
* @param a the style attributes to extract the parameters from
* @param widthAttr the identifier of the width attribute
* @param heightAttr the identifier of the height attribute
*/
protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
- width = a.getLayoutDimension(widthAttr, "layout_width");
- height = a.getLayoutDimension(heightAttr, "layout_height");
+ width = a.getLayoutDimension(widthAttr, WRAP_CONTENT);
+ height = a.getLayoutDimension(heightAttr, WRAP_CONTENT);
}
/**
@@ -5466,7 +5461,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*
* {@link View#LAYOUT_DIRECTION_LTR}
* {@link View#LAYOUT_DIRECTION_RTL}
- * @hide
*/
public void onResolveLayoutDirection(int layoutDirection) {
}
@@ -5558,7 +5552,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* The start margin in pixels of the child.
* Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value
* to this field.
- * @hide
*/
@ViewDebug.ExportedProperty(category = "layout")
public int startMargin = DEFAULT_RELATIVE;
@@ -5567,7 +5560,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* The end margin in pixels of the child.
* Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value
* to this field.
- * @hide
*/
@ViewDebug.ExportedProperty(category = "layout")
public int endMargin = DEFAULT_RELATIVE;
@@ -5686,6 +5678,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginTop
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginBottom
+ *
* @hide
*/
public void setMarginsRelative(int start, int top, int end, int bottom) {
@@ -5701,7 +5694,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginStart
*
* @return the start margin in pixels.
- * @hide
*/
public int getMarginStart() {
return startMargin;
@@ -5713,7 +5705,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
*
* @return the end margin in pixels.
- * @hide
*/
public int getMarginEnd() {
return endMargin;
@@ -5726,7 +5717,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
*
* @return true if either marginStart or marginEnd has been set
- * @hide
*/
public boolean isMarginRelative() {
return (startMargin != DEFAULT_RELATIVE) || (endMargin != DEFAULT_RELATIVE);
@@ -5735,7 +5725,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
/**
* This will be called by {@link android.view.View#requestLayout()}. Left and Right margins
* may be overridden depending on layout direction.
- * @hide
*/
@Override
public void onResolveLayoutDirection(int layoutDirection) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6959b84..17783a4 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -76,7 +76,6 @@ import android.widget.Scroller;
import com.android.internal.R;
import com.android.internal.policy.PolicyManager;
import com.android.internal.view.BaseSurfaceHolder;
-import com.android.internal.view.IInputMethodCallback;
import com.android.internal.view.IInputMethodSession;
import com.android.internal.view.RootViewSurfaceTaker;
@@ -4662,23 +4661,20 @@ public final class ViewRootImpl implements ViewParent,
}
}
- static class InputMethodCallback extends IInputMethodCallback.Stub {
+ static final class InputMethodCallback implements InputMethodManager.FinishedEventCallback {
private WeakReference<ViewRootImpl> mViewAncestor;
public InputMethodCallback(ViewRootImpl viewAncestor) {
mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
}
+ @Override
public void finishedEvent(int seq, boolean handled) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
viewAncestor.dispatchImeFinishedEvent(seq, handled);
}
}
-
- public void sessionCreated(IInputMethodSession session) {
- // Stub -- not for use in the client.
- }
}
static class W extends IWindow.Stub {
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index 1c5d436..cfcf3c0 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -32,12 +32,18 @@ import java.util.concurrent.CopyOnWriteArrayList;
* for more information.
*/
public final class ViewTreeObserver {
+ // Recursive listeners use CopyOnWriteArrayList
private CopyOnWriteArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners;
- private CopyOnWriteArrayList<OnGlobalLayoutListener> mOnGlobalLayoutListeners;
private CopyOnWriteArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners;
- private CopyOnWriteArrayList<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners;
- private CopyOnWriteArrayList<OnScrollChangedListener> mOnScrollChangedListeners;
- private ArrayList<OnPreDrawListener> mOnPreDrawListeners;
+
+ // Non-recursive listeners use CopyOnWriteArray
+ // Any listener invoked from ViewRootImpl.performTraversals() should not be recursive
+ private CopyOnWriteArray<OnGlobalLayoutListener> mOnGlobalLayoutListeners;
+ private CopyOnWriteArray<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners;
+ private CopyOnWriteArray<OnScrollChangedListener> mOnScrollChangedListeners;
+ private CopyOnWriteArray<OnPreDrawListener> mOnPreDrawListeners;
+
+ // These listeners cannot be mutated during dispatch
private ArrayList<OnDrawListener> mOnDrawListeners;
private boolean mAlive = true;
@@ -147,7 +153,7 @@ public final class ViewTreeObserver {
* windows behind it should be placed.
*/
public final Rect contentInsets = new Rect();
-
+
/**
* Offsets from the frame of the window at which windows behind it
* are visible.
@@ -166,13 +172,13 @@ public final class ViewTreeObserver {
* can be touched.
*/
public static final int TOUCHABLE_INSETS_FRAME = 0;
-
+
/**
* Option for {@link #setTouchableInsets(int)}: the area inside of
* the content insets can be touched.
*/
public static final int TOUCHABLE_INSETS_CONTENT = 1;
-
+
/**
* Option for {@link #setTouchableInsets(int)}: the area inside of
* the visible insets can be touched.
@@ -195,7 +201,7 @@ public final class ViewTreeObserver {
}
int mTouchableInsets;
-
+
void reset() {
contentInsets.setEmpty();
visibleInsets.setEmpty();
@@ -231,7 +237,7 @@ public final class ViewTreeObserver {
mTouchableInsets = other.mTouchableInsets;
}
}
-
+
/**
* Interface definition for a callback to be invoked when layout has
* completed and the client can compute its interior insets.
@@ -363,7 +369,7 @@ public final class ViewTreeObserver {
checkIsAlive();
if (mOnGlobalLayoutListeners == null) {
- mOnGlobalLayoutListeners = new CopyOnWriteArrayList<OnGlobalLayoutListener>();
+ mOnGlobalLayoutListeners = new CopyOnWriteArray<OnGlobalLayoutListener>();
}
mOnGlobalLayoutListeners.add(listener);
@@ -413,7 +419,7 @@ public final class ViewTreeObserver {
checkIsAlive();
if (mOnPreDrawListeners == null) {
- mOnPreDrawListeners = new ArrayList<OnPreDrawListener>();
+ mOnPreDrawListeners = new CopyOnWriteArray<OnPreDrawListener>();
}
mOnPreDrawListeners.add(listener);
@@ -485,7 +491,7 @@ public final class ViewTreeObserver {
checkIsAlive();
if (mOnScrollChangedListeners == null) {
- mOnScrollChangedListeners = new CopyOnWriteArrayList<OnScrollChangedListener>();
+ mOnScrollChangedListeners = new CopyOnWriteArray<OnScrollChangedListener>();
}
mOnScrollChangedListeners.add(listener);
@@ -558,7 +564,7 @@ public final class ViewTreeObserver {
if (mOnComputeInternalInsetsListeners == null) {
mOnComputeInternalInsetsListeners =
- new CopyOnWriteArrayList<OnComputeInternalInsetsListener>();
+ new CopyOnWriteArray<OnComputeInternalInsetsListener>();
}
mOnComputeInternalInsetsListeners.add(listener);
@@ -640,10 +646,16 @@ public final class ViewTreeObserver {
// perform the dispatching. The iterator is a safe guard against listeners that
// could mutate the list by calling the various add/remove methods. This prevents
// the array from being modified while we iterate it.
- final CopyOnWriteArrayList<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners;
+ final CopyOnWriteArray<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners;
if (listeners != null && listeners.size() > 0) {
- for (OnGlobalLayoutListener listener : listeners) {
- listener.onGlobalLayout();
+ CopyOnWriteArray.Access<OnGlobalLayoutListener> access = listeners.start();
+ try {
+ int count = access.size();
+ for (int i = 0; i < count; i++) {
+ access.get(i).onGlobalLayout();
+ }
+ } finally {
+ listeners.end();
}
}
}
@@ -658,17 +670,17 @@ public final class ViewTreeObserver {
*/
@SuppressWarnings("unchecked")
public final boolean dispatchOnPreDraw() {
- // NOTE: we *must* clone the listener list to perform the dispatching.
- // The clone is a safe guard against listeners that
- // could mutate the list by calling the various add/remove methods. This prevents
- // the array from being modified while we process it.
boolean cancelDraw = false;
- if (mOnPreDrawListeners != null && mOnPreDrawListeners.size() > 0) {
- final ArrayList<OnPreDrawListener> listeners =
- (ArrayList<OnPreDrawListener>) mOnPreDrawListeners.clone();
- int numListeners = listeners.size();
- for (int i = 0; i < numListeners; ++i) {
- cancelDraw |= !(listeners.get(i).onPreDraw());
+ final CopyOnWriteArray<OnPreDrawListener> listeners = mOnPreDrawListeners;
+ if (listeners != null && listeners.size() > 0) {
+ CopyOnWriteArray.Access<OnPreDrawListener> access = listeners.start();
+ try {
+ int count = access.size();
+ for (int i = 0; i < count; i++) {
+ cancelDraw |= !(access.get(i).onPreDraw());
+ }
+ } finally {
+ listeners.end();
}
}
return cancelDraw;
@@ -710,10 +722,16 @@ public final class ViewTreeObserver {
// perform the dispatching. The iterator is a safe guard against listeners that
// could mutate the list by calling the various add/remove methods. This prevents
// the array from being modified while we iterate it.
- final CopyOnWriteArrayList<OnScrollChangedListener> listeners = mOnScrollChangedListeners;
+ final CopyOnWriteArray<OnScrollChangedListener> listeners = mOnScrollChangedListeners;
if (listeners != null && listeners.size() > 0) {
- for (OnScrollChangedListener listener : listeners) {
- listener.onScrollChanged();
+ CopyOnWriteArray.Access<OnScrollChangedListener> access = listeners.start();
+ try {
+ int count = access.size();
+ for (int i = 0; i < count; i++) {
+ access.get(i).onScrollChanged();
+ }
+ } finally {
+ listeners.end();
}
}
}
@@ -722,11 +740,11 @@ public final class ViewTreeObserver {
* Returns whether there are listeners for computing internal insets.
*/
final boolean hasComputeInternalInsetsListeners() {
- final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners =
+ final CopyOnWriteArray<OnComputeInternalInsetsListener> listeners =
mOnComputeInternalInsetsListeners;
return (listeners != null && listeners.size() > 0);
}
-
+
/**
* Calls all listeners to compute the current insets.
*/
@@ -735,12 +753,105 @@ public final class ViewTreeObserver {
// perform the dispatching. The iterator is a safe guard against listeners that
// could mutate the list by calling the various add/remove methods. This prevents
// the array from being modified while we iterate it.
- final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners =
+ final CopyOnWriteArray<OnComputeInternalInsetsListener> listeners =
mOnComputeInternalInsetsListeners;
if (listeners != null && listeners.size() > 0) {
- for (OnComputeInternalInsetsListener listener : listeners) {
- listener.onComputeInternalInsets(inoutInfo);
+ CopyOnWriteArray.Access<OnComputeInternalInsetsListener> access = listeners.start();
+ try {
+ int count = access.size();
+ for (int i = 0; i < count; i++) {
+ access.get(i).onComputeInternalInsets(inoutInfo);
+ }
+ } finally {
+ listeners.end();
+ }
+ }
+ }
+
+ /**
+ * Copy on write array. This array is not thread safe, and only one loop can
+ * iterate over this array at any given time. This class avoids allocations
+ * until a concurrent modification happens.
+ *
+ * Usage:
+ *
+ * CopyOnWriteArray.Access<MyData> access = array.start();
+ * try {
+ * for (int i = 0; i < access.size(); i++) {
+ * MyData d = access.get(i);
+ * }
+ * } finally {
+ * access.end();
+ * }
+ */
+ static class CopyOnWriteArray<T> {
+ private ArrayList<T> mData = new ArrayList<T>();
+ private ArrayList<T> mDataCopy;
+
+ private final Access<T> mAccess = new Access<T>();
+
+ private boolean mStart;
+
+ static class Access<T> {
+ private ArrayList<T> mData;
+ private int mSize;
+
+ T get(int index) {
+ return mData.get(index);
+ }
+
+ int size() {
+ return mSize;
+ }
+ }
+
+ CopyOnWriteArray() {
+ }
+
+ private ArrayList<T> getArray() {
+ if (mStart) {
+ if (mDataCopy == null) mDataCopy = new ArrayList<T>(mData);
+ return mDataCopy;
}
+ return mData;
+ }
+
+ Access<T> start() {
+ if (mStart) throw new IllegalStateException("Iteration already started");
+ mStart = true;
+ mDataCopy = null;
+ mAccess.mData = mData;
+ mAccess.mSize = mData.size();
+ return mAccess;
+ }
+
+ void end() {
+ if (!mStart) throw new IllegalStateException("Iteration not started");
+ mStart = false;
+ if (mDataCopy != null) {
+ mData = mDataCopy;
+ }
+ mDataCopy = null;
+ }
+
+ int size() {
+ return getArray().size();
+ }
+
+ void add(T item) {
+ getArray().add(item);
+ }
+
+ void addAll(CopyOnWriteArray<T> array) {
+ getArray().addAll(array.mData);
+ }
+
+ void remove(T item) {
+ getArray().remove(item);
+ }
+
+ void clear() {
+ getArray().clear();
}
}
}
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index cf9bcdd..4d4e985c 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -104,6 +104,9 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
private boolean mShowCombinedVolumes;
private boolean mVoiceCapable;
+ // True if we want to play tones on the system stream when the master stream is specified.
+ private final boolean mPlayMasterStreamTones;
+
/** Dialog containing all the sliders */
private final Dialog mDialog;
/** Dialog's content view */
@@ -282,6 +285,13 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
mMoreButton.setOnClickListener(this);
}
+ boolean masterVolumeOnly = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_useMasterVolume);
+ boolean masterVolumeKeySounds = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_useVolumeKeySounds);
+
+ mPlayMasterStreamTones = masterVolumeOnly && masterVolumeKeySounds;
+
listenToRingerMode();
}
@@ -790,7 +800,16 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
* Lock on this VolumePanel instance as long as you use the returned ToneGenerator.
*/
private ToneGenerator getOrCreateToneGenerator(int streamType) {
- if (streamType == STREAM_MASTER) return null;
+ if (streamType == STREAM_MASTER) {
+ // For devices that use the master volume setting only but still want to
+ // play a volume-changed tone, direct the master volume pseudostream to
+ // the system stream's tone generator.
+ if (mPlayMasterStreamTones) {
+ streamType = AudioManager.STREAM_SYSTEM;
+ } else {
+ return null;
+ }
+ }
synchronized (this) {
if (mToneGenerators[streamType] == null) {
try {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index b0e90db..ec4114e 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -718,6 +718,7 @@ public abstract class Window {
* per {@link #setFlags}.
* @param flags The flag bits to be set.
* @see #setFlags
+ * @see #clearFlags
*/
public void addFlags(int flags) {
setFlags(flags, flags);
@@ -728,6 +729,7 @@ public abstract class Window {
* per {@link #setFlags}.
* @param flags The flag bits to be cleared.
* @see #setFlags
+ * @see #addFlags
*/
public void clearFlags(int flags) {
setFlags(0, flags);
@@ -749,6 +751,8 @@ public abstract class Window {
*
* @param flags The new window flags (see WindowManager.LayoutParams).
* @param mask Which of the window flag bits to modify.
+ * @see #addFlags
+ * @see #clearFlags
*/
public void setFlags(int flags, int mask) {
final WindowManager.LayoutParams attrs = getAttributes();
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index d94275b..e6a29ea 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -162,6 +162,7 @@ public interface WindowManager extends ViewManager {
@ViewDebug.IntToString(from = TYPE_APPLICATION_MEDIA, to = "TYPE_APPLICATION_MEDIA"),
@ViewDebug.IntToString(from = TYPE_APPLICATION_SUB_PANEL, to = "TYPE_APPLICATION_SUB_PANEL"),
@ViewDebug.IntToString(from = TYPE_APPLICATION_ATTACHED_DIALOG, to = "TYPE_APPLICATION_ATTACHED_DIALOG"),
+ @ViewDebug.IntToString(from = TYPE_APPLICATION_MEDIA_OVERLAY, to = "TYPE_APPLICATION_MEDIA_OVERLAY"),
@ViewDebug.IntToString(from = TYPE_STATUS_BAR, to = "TYPE_STATUS_BAR"),
@ViewDebug.IntToString(from = TYPE_SEARCH_BAR, to = "TYPE_SEARCH_BAR"),
@ViewDebug.IntToString(from = TYPE_PHONE, to = "TYPE_PHONE"),
@@ -170,8 +171,6 @@ public interface WindowManager extends ViewManager {
@ViewDebug.IntToString(from = TYPE_TOAST, to = "TYPE_TOAST"),
@ViewDebug.IntToString(from = TYPE_SYSTEM_OVERLAY, to = "TYPE_SYSTEM_OVERLAY"),
@ViewDebug.IntToString(from = TYPE_PRIORITY_PHONE, to = "TYPE_PRIORITY_PHONE"),
- @ViewDebug.IntToString(from = TYPE_STATUS_BAR_PANEL, to = "TYPE_STATUS_BAR_PANEL"),
- @ViewDebug.IntToString(from = TYPE_STATUS_BAR_SUB_PANEL, to = "TYPE_STATUS_BAR_SUB_PANEL"),
@ViewDebug.IntToString(from = TYPE_SYSTEM_DIALOG, to = "TYPE_SYSTEM_DIALOG"),
@ViewDebug.IntToString(from = TYPE_KEYGUARD_DIALOG, to = "TYPE_KEYGUARD_DIALOG"),
@ViewDebug.IntToString(from = TYPE_SYSTEM_ERROR, to = "TYPE_SYSTEM_ERROR"),
@@ -185,7 +184,10 @@ public interface WindowManager extends ViewManager {
@ViewDebug.IntToString(from = TYPE_POINTER, to = "TYPE_POINTER"),
@ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR, to = "TYPE_NAVIGATION_BAR"),
@ViewDebug.IntToString(from = TYPE_VOLUME_OVERLAY, to = "TYPE_VOLUME_OVERLAY"),
- @ViewDebug.IntToString(from = TYPE_BOOT_PROGRESS, to = "TYPE_BOOT_PROGRESS")
+ @ViewDebug.IntToString(from = TYPE_BOOT_PROGRESS, to = "TYPE_BOOT_PROGRESS"),
+ @ViewDebug.IntToString(from = TYPE_HIDDEN_NAV_CONSUMER, to = "TYPE_HIDDEN_NAV_CONSUMER"),
+ @ViewDebug.IntToString(from = TYPE_DREAM, to = "TYPE_DREAM"),
+ @ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR_PANEL, to = "TYPE_NAVIGATION_BAR_PANEL")
})
public int type;
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index d2cc2d8..89932cc 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -35,6 +35,7 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.text.style.SuggestionSpan;
import android.util.Log;
import android.util.PrintWriterPrinter;
@@ -225,6 +226,13 @@ public final class InputMethodManager {
*/
public static final int CONTROL_START_INITIAL = 1<<8;
+ /**
+ * Timeout in milliseconds for delivering a key to an IME.
+ */
+ static final long INPUT_METHOD_NOT_RESPONDING_TIMEOUT = 2500;
+
+ private static final int MAX_PENDING_EVENT_POOL_SIZE = 4;
+
final IInputMethodManager mService;
final Looper mMainLooper;
@@ -312,12 +320,17 @@ public final class InputMethodManager {
*/
IInputMethodSession mCurMethod;
+ PendingEvent mPendingEventPool;
+ int mPendingEventPoolSize;
+ PendingEvent mFirstPendingEvent;
+
// -----------------------------------------------------------
static final int MSG_DUMP = 1;
static final int MSG_BIND = 2;
static final int MSG_UNBIND = 3;
static final int MSG_SET_ACTIVE = 4;
+ static final int MSG_EVENT_TIMEOUT = 5;
class H extends Handler {
H(Looper looper) {
@@ -413,6 +426,17 @@ public final class InputMethodManager {
}
return;
}
+ case MSG_EVENT_TIMEOUT: {
+ // Even though the message contains both the sequence number
+ // and the PendingEvent object itself, we only pass the
+ // sequence number to the timeoutEvent function because it's
+ // possible for the PendingEvent object to be dequeued and
+ // recycled concurrently. To avoid a possible race, we make
+ // a point of always looking up the PendingEvent within the
+ // queue given only the sequence number of the event.
+ timeoutEvent(msg.arg1);
+ return;
+ }
}
}
}
@@ -476,6 +500,18 @@ public final class InputMethodManager {
};
final InputConnection mDummyInputConnection = new BaseInputConnection(this, false);
+
+ final IInputMethodCallback mInputMethodCallback = new IInputMethodCallback.Stub() {
+ @Override
+ public void finishedEvent(int seq, boolean handled) {
+ InputMethodManager.this.finishedEvent(seq, handled);
+ }
+
+ @Override
+ public void sessionCreated(IInputMethodSession session) {
+ // Stub -- not for use in the client.
+ }
+ };
InputMethodManager(IInputMethodManager service, Looper looper) {
mService = service;
@@ -1105,6 +1141,7 @@ public final class InputMethodManager {
if (res.id != null) {
mBindSequence = res.sequence;
mCurMethod = res.method;
+ mCurId = res.id;
} else if (mCurMethod == null) {
// This means there is no input method available.
if (DEBUG) Log.v(TAG, "ABORT input: no input method!");
@@ -1511,76 +1548,159 @@ public final class InputMethodManager {
* @hide
*/
public void dispatchKeyEvent(Context context, int seq, KeyEvent key,
- IInputMethodCallback callback) {
+ FinishedEventCallback callback) {
+ boolean handled = false;
synchronized (mH) {
if (DEBUG) Log.d(TAG, "dispatchKeyEvent");
-
- if (mCurMethod == null) {
- try {
- callback.finishedEvent(seq, false);
- } catch (RemoteException e) {
- }
- return;
- }
-
- if (key.getAction() == KeyEvent.ACTION_DOWN
- && key.getKeyCode() == KeyEvent.KEYCODE_SYM) {
- showInputMethodPicker();
- try {
- callback.finishedEvent(seq, true);
- } catch (RemoteException e) {
- }
- return;
- }
- try {
- if (DEBUG) Log.v(TAG, "DISPATCH KEY: " + mCurMethod);
- mCurMethod.dispatchKeyEvent(seq, key, callback);
- } catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId + " dropping: " + key, e);
- try {
- callback.finishedEvent(seq, false);
- } catch (RemoteException ex) {
+
+ if (mCurMethod != null) {
+ if (key.getAction() == KeyEvent.ACTION_DOWN
+ && key.getKeyCode() == KeyEvent.KEYCODE_SYM) {
+ showInputMethodPickerLocked();
+ handled = true;
+ } else {
+ try {
+ if (DEBUG) Log.v(TAG, "DISPATCH KEY: " + mCurMethod);
+ final long startTime = SystemClock.uptimeMillis();
+ mCurMethod.dispatchKeyEvent(seq, key, mInputMethodCallback);
+ enqueuePendingEventLocked(startTime, seq, mCurId, callback);
+ return;
+ } catch (RemoteException e) {
+ Log.w(TAG, "IME died: " + mCurId + " dropping: " + key, e);
+ }
}
}
}
+
+ callback.finishedEvent(seq, handled);
}
/**
* @hide
*/
void dispatchTrackballEvent(Context context, int seq, MotionEvent motion,
- IInputMethodCallback callback) {
+ FinishedEventCallback callback) {
synchronized (mH) {
if (DEBUG) Log.d(TAG, "dispatchTrackballEvent");
-
- if (mCurMethod == null || mCurrentTextBoxAttribute == null) {
+
+ if (mCurMethod != null && mCurrentTextBoxAttribute != null) {
try {
- callback.finishedEvent(seq, false);
+ if (DEBUG) Log.v(TAG, "DISPATCH TRACKBALL: " + mCurMethod);
+ final long startTime = SystemClock.uptimeMillis();
+ mCurMethod.dispatchTrackballEvent(seq, motion, mInputMethodCallback);
+ enqueuePendingEventLocked(startTime, seq, mCurId, callback);
+ return;
} catch (RemoteException e) {
+ Log.w(TAG, "IME died: " + mCurId + " dropping trackball: " + motion, e);
}
- return;
}
-
- try {
- if (DEBUG) Log.v(TAG, "DISPATCH TRACKBALL: " + mCurMethod);
- mCurMethod.dispatchTrackballEvent(seq, motion, callback);
- } catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId + " dropping trackball: " + motion, e);
- try {
- callback.finishedEvent(seq, false);
- } catch (RemoteException ex) {
- }
+ }
+
+ callback.finishedEvent(seq, false);
+ }
+
+ void finishedEvent(int seq, boolean handled) {
+ final FinishedEventCallback callback;
+ synchronized (mH) {
+ PendingEvent p = dequeuePendingEventLocked(seq);
+ if (p == null) {
+ return; // spurious, event already finished or timed out
}
+ mH.removeMessages(MSG_EVENT_TIMEOUT, p);
+ callback = p.mCallback;
+ recyclePendingEventLocked(p);
}
+ callback.finishedEvent(seq, handled);
}
- public void showInputMethodPicker() {
+ void timeoutEvent(int seq) {
+ final FinishedEventCallback callback;
synchronized (mH) {
- try {
- mService.showInputMethodPickerFromClient(mClient);
- } catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
+ PendingEvent p = dequeuePendingEventLocked(seq);
+ if (p == null) {
+ return; // spurious, event already finished or timed out
}
+ long delay = SystemClock.uptimeMillis() - p.mStartTime;
+ Log.w(TAG, "Timeout waiting for IME to handle input event after "
+ + delay + "ms: " + p.mInputMethodId);
+ callback = p.mCallback;
+ recyclePendingEventLocked(p);
+ }
+ callback.finishedEvent(seq, false);
+ }
+
+ private void enqueuePendingEventLocked(
+ long startTime, int seq, String inputMethodId, FinishedEventCallback callback) {
+ PendingEvent p = obtainPendingEventLocked(startTime, seq, inputMethodId, callback);
+ p.mNext = mFirstPendingEvent;
+ mFirstPendingEvent = p;
+
+ Message msg = mH.obtainMessage(MSG_EVENT_TIMEOUT, seq, 0, p);
+ msg.setAsynchronous(true);
+ mH.sendMessageDelayed(msg, INPUT_METHOD_NOT_RESPONDING_TIMEOUT);
+ }
+
+ private PendingEvent dequeuePendingEventLocked(int seq) {
+ PendingEvent p = mFirstPendingEvent;
+ if (p == null) {
+ return null;
+ }
+ if (p.mSeq == seq) {
+ mFirstPendingEvent = p.mNext;
+ } else {
+ PendingEvent prev = p;
+ do {
+ p = prev.mNext;
+ if (p == null) {
+ return null;
+ }
+ } while (p.mSeq != seq);
+ prev.mNext = p.mNext;
+ }
+ p.mNext = null;
+ return p;
+ }
+
+ private PendingEvent obtainPendingEventLocked(
+ long startTime, int seq, String inputMethodId, FinishedEventCallback callback) {
+ PendingEvent p = mPendingEventPool;
+ if (p != null) {
+ mPendingEventPoolSize -= 1;
+ mPendingEventPool = p.mNext;
+ p.mNext = null;
+ } else {
+ p = new PendingEvent();
+ }
+
+ p.mStartTime = startTime;
+ p.mSeq = seq;
+ p.mInputMethodId = inputMethodId;
+ p.mCallback = callback;
+ return p;
+ }
+
+ private void recyclePendingEventLocked(PendingEvent p) {
+ p.mInputMethodId = null;
+ p.mCallback = null;
+
+ if (mPendingEventPoolSize < MAX_PENDING_EVENT_POOL_SIZE) {
+ mPendingEventPoolSize += 1;
+ p.mNext = mPendingEventPool;
+ mPendingEventPool = p;
+ }
+ }
+
+ public void showInputMethodPicker() {
+ synchronized (mH) {
+ showInputMethodPickerLocked();
+ }
+ }
+
+ private void showInputMethodPickerLocked() {
+ try {
+ mService.showInputMethodPickerFromClient(mClient);
+ } catch (RemoteException e) {
+ Log.w(TAG, "IME died: " + mCurId, e);
}
}
@@ -1773,4 +1893,22 @@ public final class InputMethodManager {
+ " mCursorCandStart=" + mCursorCandStart
+ " mCursorCandEnd=" + mCursorCandEnd);
}
+
+ /**
+ * Callback that is invoked when an input event that was dispatched to
+ * the IME has been finished.
+ * @hide
+ */
+ public interface FinishedEventCallback {
+ public void finishedEvent(int seq, boolean handled);
+ }
+
+ private static final class PendingEvent {
+ public PendingEvent mNext;
+
+ public long mStartTime;
+ public int mSeq;
+ public String mInputMethodId;
+ public FinishedEventCallback mCallback;
+ }
}
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 5108990..fe812af 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -74,6 +74,7 @@ class BrowserFrame extends Handler {
private final CallbackProxy mCallbackProxy;
private final WebSettingsClassic mSettings;
private final Context mContext;
+ private final WebViewDatabaseClassic mDatabase;
private final WebViewCore mWebViewCore;
/* package */ boolean mLoadInitFromJava;
private int mLoadType;
@@ -242,6 +243,7 @@ class BrowserFrame extends Handler {
mSettings = settings;
mContext = context;
mCallbackProxy = proxy;
+ mDatabase = WebViewDatabaseClassic.getInstance(appContext);
mWebViewCore = w;
mSearchBox = new SearchBoxImpl(mWebViewCore, mCallbackProxy);
@@ -424,8 +426,7 @@ class BrowserFrame extends Handler {
if (h != null) {
String url = WebTextView.urlForAutoCompleteData(h.getUrl());
if (url != null) {
- WebViewDatabaseClassic.getInstance(mContext).setFormData(
- url, data);
+ mDatabase.setFormData(url, data);
}
}
}
@@ -497,9 +498,8 @@ class BrowserFrame extends Handler {
if (item != null) {
WebAddress uri = new WebAddress(item.getUrl());
String schemePlusHost = uri.getScheme() + uri.getHost();
- String[] up =
- WebViewDatabaseClassic.getInstance(mContext)
- .getUsernamePassword(schemePlusHost);
+ String[] up = mDatabase.getUsernamePassword(
+ schemePlusHost);
if (up != null && up[0] != null) {
setUsernamePassword(up[0], up[1]);
}
@@ -800,10 +800,10 @@ class BrowserFrame extends Handler {
// the post data (there could be another form on the
// page and that was posted instead.
String postString = new String(postData);
- WebViewDatabaseClassic db = WebViewDatabaseClassic.getInstance(mContext);
if (postString.contains(URLEncoder.encode(username)) &&
postString.contains(URLEncoder.encode(password))) {
- String[] saved = db.getUsernamePassword(schemePlusHost);
+ String[] saved = mDatabase.getUsernamePassword(
+ schemePlusHost);
if (saved != null) {
// null username implies that user has chosen not to
// save password
@@ -811,8 +811,7 @@ class BrowserFrame extends Handler {
// non-null username implies that user has
// chosen to save password, so update the
// recorded password
- db.setUsernamePassword(schemePlusHost, username,
- password);
+ mDatabase.setUsernamePassword(schemePlusHost, username, password);
}
} else {
// CallbackProxy will handle creating the resume
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 2d9f60d..8b7cecf 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -71,7 +71,7 @@ class CallbackProxy extends Handler {
// Start with 100 to indicate it is not in load for the empty page.
private volatile int mLatestProgress = 100;
// Back/Forward list
- private final WebBackForwardList mBackForwardList;
+ private final WebBackForwardListClassic mBackForwardList;
// Back/Forward list client
private volatile WebBackForwardListClient mWebBackForwardListClient;
// Used to call startActivity during url override.
@@ -117,7 +117,6 @@ class CallbackProxy extends Handler {
private static final int ADD_HISTORY_ITEM = 135;
private static final int HISTORY_INDEX_CHANGED = 136;
private static final int AUTH_CREDENTIALS = 137;
- private static final int SET_INSTALLABLE_WEBAPP = 138;
private static final int NOTIFY_SEARCHBOX_LISTENERS = 139;
private static final int AUTO_LOGIN = 140;
private static final int CLIENT_CERT_REQUEST = 141;
@@ -188,7 +187,7 @@ class CallbackProxy extends Handler {
// Used to start a default activity.
mContext = context;
mWebView = w;
- mBackForwardList = new WebBackForwardList(this);
+ mBackForwardList = new WebBackForwardListClassic(this);
}
protected synchronized void blockMessages() {
@@ -249,7 +248,7 @@ class CallbackProxy extends Handler {
* Get the Back/Forward list to return to the user or to update the cached
* history list.
*/
- public WebBackForwardList getBackForwardList() {
+ public WebBackForwardListClassic getBackForwardList() {
return mBackForwardList;
}
@@ -403,17 +402,18 @@ class CallbackProxy extends Handler {
break;
case PROCEEDED_AFTER_SSL_ERROR:
- if (mWebViewClient != null) {
- mWebViewClient.onProceededAfterSslError(mWebView.getWebView(),
+ if (mWebViewClient != null && mWebViewClient instanceof WebViewClientClassicExt) {
+ ((WebViewClientClassicExt) mWebViewClient).onProceededAfterSslError(
+ mWebView.getWebView(),
(SslError) msg.obj);
}
break;
case CLIENT_CERT_REQUEST:
- if (mWebViewClient != null) {
- HashMap<String, Object> map =
- (HashMap<String, Object>) msg.obj;
- mWebViewClient.onReceivedClientCertRequest(mWebView.getWebView(),
+ if (mWebViewClient != null && mWebViewClient instanceof WebViewClientClassicExt) {
+ HashMap<String, Object> map = (HashMap<String, Object>) msg.obj;
+ ((WebViewClientClassicExt) mWebViewClient).onReceivedClientCertRequest(
+ mWebView.getWebView(),
(ClientCertRequestHandler) map.get("handler"),
(String) map.get("host_and_port"));
}
@@ -857,11 +857,6 @@ class CallbackProxy extends Handler {
host, realm, username, password);
break;
}
- case SET_INSTALLABLE_WEBAPP:
- if (mWebChromeClient != null) {
- mWebChromeClient.setInstallableWebApp();
- }
- break;
case NOTIFY_SEARCHBOX_LISTENERS: {
SearchBoxImpl searchBox = (SearchBoxImpl) mWebView.getSearchBox();
@@ -1081,7 +1076,7 @@ class CallbackProxy extends Handler {
}
public void onProceededAfterSslError(SslError error) {
- if (mWebViewClient == null) {
+ if (mWebViewClient == null || !(mWebViewClient instanceof WebViewClientClassicExt)) {
return;
}
Message msg = obtainMessage(PROCEEDED_AFTER_SSL_ERROR);
@@ -1092,7 +1087,7 @@ class CallbackProxy extends Handler {
public void onReceivedClientCertRequest(ClientCertRequestHandler handler, String host_and_port) {
// Do an unsynchronized quick check to avoid posting if no callback has
// been set.
- if (mWebViewClient == null) {
+ if (mWebViewClient == null || !(mWebViewClient instanceof WebViewClientClassicExt)) {
handler.cancel();
return;
}
@@ -1301,7 +1296,7 @@ class CallbackProxy extends Handler {
public void onReceivedIcon(Bitmap icon) {
// The current item might be null if the icon was already stored in the
// database and this is a new WebView.
- WebHistoryItem i = mBackForwardList.getCurrentItem();
+ WebHistoryItemClassic i = mBackForwardList.getCurrentItem();
if (i != null) {
i.setFavicon(icon);
}
@@ -1316,7 +1311,7 @@ class CallbackProxy extends Handler {
/* package */ void onReceivedTouchIconUrl(String url, boolean precomposed) {
// We should have a current item but we do not want to crash so check
// for null.
- WebHistoryItem i = mBackForwardList.getCurrentItem();
+ WebHistoryItemClassic i = mBackForwardList.getCurrentItem();
if (i != null) {
i.setTouchIconUrl(url, precomposed);
}
@@ -1608,13 +1603,6 @@ class CallbackProxy extends Handler {
sendMessage(msg);
}
- void setInstallableWebApp() {
- if (mWebChromeClient == null) {
- return;
- }
- sendMessage(obtainMessage(SET_INSTALLABLE_WEBAPP));
- }
-
boolean canShowAlertDialog() {
// We can only display the alert dialog if mContext is
// an Activity context.
diff --git a/core/java/android/webkit/CookieSyncManager.java b/core/java/android/webkit/CookieSyncManager.java
index 4e99335..276bcae 100644
--- a/core/java/android/webkit/CookieSyncManager.java
+++ b/core/java/android/webkit/CookieSyncManager.java
@@ -86,10 +86,8 @@ public final class CookieSyncManager extends WebSyncManager {
throw new IllegalArgumentException("Invalid context argument");
}
- JniUtil.setContext(context);
- Context appContext = context.getApplicationContext();
if (sRef == null) {
- sRef = new CookieSyncManager(appContext);
+ sRef = new CookieSyncManager(context);
}
return sRef;
}
diff --git a/core/java/android/webkit/MockGeolocation.java b/core/java/android/webkit/MockGeolocation.java
index fbda492..885c6c2 100644
--- a/core/java/android/webkit/MockGeolocation.java
+++ b/core/java/android/webkit/MockGeolocation.java
@@ -17,21 +17,29 @@
package android.webkit;
/**
- * This class is simply a container for the methods used to configure WebKit's
- * mock Geolocation service for use in LayoutTests.
+ * Used to configure the mock Geolocation client for the LayoutTests.
* @hide
*/
public final class MockGeolocation {
+ private WebViewCore mWebViewCore;
- // Global instance of a MockGeolocation
- private static MockGeolocation sMockGeolocation;
+ public MockGeolocation(WebViewCore webViewCore) {
+ mWebViewCore = webViewCore;
+ }
+
+ /**
+ * Sets use of the mock Geolocation client. Also resets that client.
+ */
+ public void setUseMock() {
+ nativeSetUseMock(mWebViewCore);
+ }
/**
* Set the position for the mock Geolocation service.
*/
public void setPosition(double latitude, double longitude, double accuracy) {
// This should only ever be called on the WebKit thread.
- nativeSetPosition(latitude, longitude, accuracy);
+ nativeSetPosition(mWebViewCore, latitude, longitude, accuracy);
}
/**
@@ -39,21 +47,18 @@ public final class MockGeolocation {
*/
public void setError(int code, String message) {
// This should only ever be called on the WebKit thread.
- nativeSetError(code, message);
+ nativeSetError(mWebViewCore, code, message);
}
- /**
- * Get the global instance of MockGeolocation.
- * @return The global MockGeolocation instance.
- */
- public static MockGeolocation getInstance() {
- if (sMockGeolocation == null) {
- sMockGeolocation = new MockGeolocation();
- }
- return sMockGeolocation;
+ public void setPermission(boolean allow) {
+ // This should only ever be called on the WebKit thread.
+ nativeSetPermission(mWebViewCore, allow);
}
// Native functions
- private static native void nativeSetPosition(double latitude, double longitude, double accuracy);
- private static native void nativeSetError(int code, String message);
+ private static native void nativeSetUseMock(WebViewCore webViewCore);
+ private static native void nativeSetPosition(WebViewCore webViewCore, double latitude,
+ double longitude, double accuracy);
+ private static native void nativeSetError(WebViewCore webViewCore, int code, String message);
+ private static native void nativeSetPermission(WebViewCore webViewCore, boolean allow);
}
diff --git a/core/java/android/webkit/ViewStateSerializer.java b/core/java/android/webkit/ViewStateSerializer.java
index c161085..096d4cda 100644
--- a/core/java/android/webkit/ViewStateSerializer.java
+++ b/core/java/android/webkit/ViewStateSerializer.java
@@ -16,7 +16,6 @@
package android.webkit;
import android.graphics.Point;
-import android.graphics.Region;
import android.webkit.WebViewCore.DrawData;
import java.io.DataInputStream;
@@ -68,6 +67,15 @@ class ViewStateSerializer {
return draw;
}
+ public static void dumpLayerHierarchy(int baseLayer, OutputStream out, int level) {
+ nativeDumpLayerHierarchy(baseLayer, level, out,
+ new byte[WORKING_STREAM_STORAGE]);
+ }
+
+
+ private static native void nativeDumpLayerHierarchy(int baseLayer, int level,
+ OutputStream out, byte[] storage);
+
private static native boolean nativeSerializeViewState(int baseLayer,
OutputStream stream, byte[] storage);
diff --git a/core/java/android/webkit/WebBackForwardList.java b/core/java/android/webkit/WebBackForwardList.java
index 79e634e..bfef2e7 100644
--- a/core/java/android/webkit/WebBackForwardList.java
+++ b/core/java/android/webkit/WebBackForwardList.java
@@ -17,7 +17,6 @@
package android.webkit;
import java.io.Serializable;
-import java.util.ArrayList;
/**
* This class contains the back/forward list for a WebView.
@@ -25,22 +24,11 @@ import java.util.ArrayList;
* inspect the entries in the list.
*/
public class WebBackForwardList implements Cloneable, Serializable {
- // Current position in the list.
- private int mCurrentIndex;
- // ArrayList of WebHistoryItems for maintaining our copy.
- private ArrayList<WebHistoryItem> mArray;
- // Flag to indicate that the list is invalid
- private boolean mClearPending;
- // CallbackProxy to issue client callbacks.
- private final CallbackProxy mCallbackProxy;
/**
- * Construct a back/forward list used by clients of WebView.
+ * @hide
*/
- /*package*/ WebBackForwardList(CallbackProxy proxy) {
- mCurrentIndex = -1;
- mArray = new ArrayList<WebHistoryItem>();
- mCallbackProxy = proxy;
+ public WebBackForwardList() {
}
/**
@@ -49,7 +37,7 @@ public class WebBackForwardList implements Cloneable, Serializable {
* @return The current history item.
*/
public synchronized WebHistoryItem getCurrentItem() {
- return getItemAtIndex(mCurrentIndex);
+ throw new MustOverrideException();
}
/**
@@ -58,7 +46,7 @@ public class WebBackForwardList implements Cloneable, Serializable {
* @return The current index from 0...n or -1 if the list is empty.
*/
public synchronized int getCurrentIndex() {
- return mCurrentIndex;
+ throw new MustOverrideException();
}
/**
@@ -67,10 +55,7 @@ public class WebBackForwardList implements Cloneable, Serializable {
* @param index The index to retrieve.
*/
public synchronized WebHistoryItem getItemAtIndex(int index) {
- if (index < 0 || index >= getSize()) {
- return null;
- }
- return mArray.get(index);
+ throw new MustOverrideException();
}
/**
@@ -78,78 +63,7 @@ public class WebBackForwardList implements Cloneable, Serializable {
* @return The size of the list.
*/
public synchronized int getSize() {
- return mArray.size();
- }
-
- /**
- * Mark the back/forward list as having a pending clear. This is used on the
- * UI side to mark the list as being invalid during the clearHistory method.
- */
- /*package*/ synchronized void setClearPending() {
- mClearPending = true;
- }
-
- /**
- * Return the status of the clear flag. This is used on the UI side to
- * determine if the list is valid for checking things like canGoBack.
- */
- /*package*/ synchronized boolean getClearPending() {
- return mClearPending;
- }
-
- /**
- * Add a new history item to the list. This will remove all items after the
- * current item and append the new item to the end of the list. Called from
- * the WebCore thread only. Synchronized because the UI thread may be
- * reading the array or the current index.
- * @param item A new history item.
- */
- /*package*/ synchronized void addHistoryItem(WebHistoryItem item) {
- // Update the current position because we are going to add the new item
- // in that slot.
- ++mCurrentIndex;
- // If the current position is not at the end, remove all history items
- // after the current item.
- final int size = mArray.size();
- final int newPos = mCurrentIndex;
- if (newPos != size) {
- for (int i = size - 1; i >= newPos; i--) {
- final WebHistoryItem h = mArray.remove(i);
- }
- }
- // Add the item to the list.
- mArray.add(item);
- if (mCallbackProxy != null) {
- mCallbackProxy.onNewHistoryItem(item);
- }
- }
-
- /**
- * Clear the back/forward list. Called from the WebCore thread.
- */
- /*package*/ synchronized void close(int nativeFrame) {
- // Clear the array first because nativeClose will call addHistoryItem
- // with the current item.
- mArray.clear();
- mCurrentIndex = -1;
- nativeClose(nativeFrame);
- // Reset the clear flag
- mClearPending = false;
- }
-
- /* Remove the item at the given index. Called by JNI only. */
- private synchronized void removeHistoryItem(int index) {
- // XXX: This is a special case. Since the callback is only triggered
- // when removing the first item, we can assert that the index is 0.
- // This lets us change the current index without having to query the
- // native BackForwardList.
- if (DebugFlags.WEB_BACK_FORWARD_LIST && (index != 0)) {
- throw new AssertionError();
- }
- final WebHistoryItem h = mArray.remove(index);
- // XXX: If we ever add another callback for removing history items at
- // any index, this will no longer be valid.
- mCurrentIndex--;
+ throw new MustOverrideException();
}
/**
@@ -158,39 +72,7 @@ public class WebBackForwardList implements Cloneable, Serializable {
* webkit package classes.
*/
protected synchronized WebBackForwardList clone() {
- WebBackForwardList l = new WebBackForwardList(null);
- if (mClearPending) {
- // If a clear is pending, return a copy with only the current item.
- l.addHistoryItem(getCurrentItem());
- return l;
- }
- l.mCurrentIndex = mCurrentIndex;
- int size = getSize();
- l.mArray = new ArrayList<WebHistoryItem>(size);
- for (int i = 0; i < size; i++) {
- // Add a copy of each WebHistoryItem
- l.mArray.add(mArray.get(i).clone());
- }
- return l;
- }
-
- /**
- * Set the new history index.
- * @param newIndex The new history index.
- */
- /*package*/ synchronized void setCurrentIndex(int newIndex) {
- mCurrentIndex = newIndex;
- if (mCallbackProxy != null) {
- mCallbackProxy.onIndexChanged(getItemAtIndex(newIndex), newIndex);
- }
+ throw new MustOverrideException();
}
- /**
- * Restore the history index.
- */
- /*package*/ static native synchronized void restoreIndex(int nativeFrame,
- int index);
-
- /* Close the native list. */
- private static native void nativeClose(int nativeFrame);
}
diff --git a/core/java/android/webkit/WebBackForwardListClassic.java b/core/java/android/webkit/WebBackForwardListClassic.java
new file mode 100644
index 0000000..2a14e6b
--- /dev/null
+++ b/core/java/android/webkit/WebBackForwardListClassic.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+
+/* package */ class WebBackForwardListClassic extends WebBackForwardList implements Cloneable,
+ Serializable {
+
+ // Current position in the list.
+ private int mCurrentIndex;
+ // ArrayList of WebHistoryItems for maintaining our copy.
+ private ArrayList<WebHistoryItemClassic> mArray;
+ // Flag to indicate that the list is invalid
+ private boolean mClearPending;
+ // CallbackProxy to issue client callbacks.
+ private final CallbackProxy mCallbackProxy;
+
+ /*package*/ WebBackForwardListClassic(CallbackProxy proxy) {
+ mCurrentIndex = -1;
+ mArray = new ArrayList<WebHistoryItemClassic>();
+ mCallbackProxy = proxy;
+ }
+
+ public synchronized WebHistoryItemClassic getCurrentItem() {
+ return getItemAtIndex(mCurrentIndex);
+ }
+
+ public synchronized int getCurrentIndex() {
+ return mCurrentIndex;
+ }
+
+ public synchronized WebHistoryItemClassic getItemAtIndex(int index) {
+ if (index < 0 || index >= getSize()) {
+ return null;
+ }
+ return mArray.get(index);
+ }
+
+ public synchronized int getSize() {
+ return mArray.size();
+ }
+
+ /**
+ * Mark the back/forward list as having a pending clear. This is used on the
+ * UI side to mark the list as being invalid during the clearHistory method.
+ */
+ /*package*/ synchronized void setClearPending() {
+ mClearPending = true;
+ }
+
+ /**
+ * Return the status of the clear flag. This is used on the UI side to
+ * determine if the list is valid for checking things like canGoBack.
+ */
+ /*package*/ synchronized boolean getClearPending() {
+ return mClearPending;
+ }
+
+ /**
+ * Add a new history item to the list. This will remove all items after the
+ * current item and append the new item to the end of the list. Called from
+ * the WebCore thread only. Synchronized because the UI thread may be
+ * reading the array or the current index.
+ * @param item A new history item.
+ */
+ /*package*/ synchronized void addHistoryItem(WebHistoryItem item) {
+ // Update the current position because we are going to add the new item
+ // in that slot.
+ ++mCurrentIndex;
+ // If the current position is not at the end, remove all history items
+ // after the current item.
+ final int size = mArray.size();
+ final int newPos = mCurrentIndex;
+ if (newPos != size) {
+ for (int i = size - 1; i >= newPos; i--) {
+ final WebHistoryItem h = mArray.remove(i);
+ }
+ }
+ // Add the item to the list.
+ mArray.add((WebHistoryItemClassic) item);
+ if (mCallbackProxy != null) {
+ mCallbackProxy.onNewHistoryItem(item);
+ }
+ }
+
+ /**
+ * Clear the back/forward list. Called from the WebCore thread.
+ */
+ /*package*/ synchronized void close(int nativeFrame) {
+ // Clear the array first because nativeClose will call addHistoryItem
+ // with the current item.
+ mArray.clear();
+ mCurrentIndex = -1;
+ nativeClose(nativeFrame);
+ // Reset the clear flag
+ mClearPending = false;
+ }
+
+ /* Remove the item at the given index. Called by JNI only. */
+ private synchronized void removeHistoryItem(int index) {
+ // XXX: This is a special case. Since the callback is only triggered
+ // when removing the first item, we can assert that the index is 0.
+ // This lets us change the current index without having to query the
+ // native BackForwardList.
+ if (DebugFlags.WEB_BACK_FORWARD_LIST && (index != 0)) {
+ throw new AssertionError();
+ }
+ final WebHistoryItem h = mArray.remove(index);
+ // XXX: If we ever add another callback for removing history items at
+ // any index, this will no longer be valid.
+ mCurrentIndex--;
+ }
+
+ public synchronized WebBackForwardListClassic clone() {
+ WebBackForwardListClassic l = new WebBackForwardListClassic(null);
+ if (mClearPending) {
+ // If a clear is pending, return a copy with only the current item.
+ l.addHistoryItem(getCurrentItem());
+ return l;
+ }
+ l.mCurrentIndex = mCurrentIndex;
+ int size = getSize();
+ l.mArray = new ArrayList<WebHistoryItemClassic>(size);
+ for (int i = 0; i < size; i++) {
+ // Add a copy of each WebHistoryItem
+ l.mArray.add(mArray.get(i).clone());
+ }
+ return l;
+ }
+
+ /**
+ * Set the new history index.
+ * @param newIndex The new history index.
+ */
+ /*package*/ synchronized void setCurrentIndex(int newIndex) {
+ mCurrentIndex = newIndex;
+ if (mCallbackProxy != null) {
+ mCallbackProxy.onIndexChanged(getItemAtIndex(newIndex), newIndex);
+ }
+ }
+
+ /**
+ * Restore the history index.
+ */
+ /*package*/ static native synchronized void restoreIndex(int nativeFrame,
+ int index);
+
+ /* Close the native list. */
+ private static native void nativeClose(int nativeFrame);
+}
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 4e8790b..01c047b 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -297,7 +297,12 @@ public class WebChromeClient {
* will continue to occur if the script does not finish at the next check
* point.
* @return boolean Whether the JavaScript execution should be interrupted.
+ * @deprecated This method is no longer supported and will not be invoked.
*/
+ // This method was only called when using the JSC javascript engine. V8 became
+ // the default JS engine with Froyo and support for building with JSC was
+ // removed in b/5495373. V8 does not have a mechanism for making a callback such
+ // as this.
public boolean onJsTimeout() {
return true;
}
@@ -372,13 +377,6 @@ public class WebChromeClient {
}
/**
- * Tell the client that the page being viewed is web app capable,
- * i.e. has specified the fullscreen-web-app-capable meta tag.
- * @hide
- */
- public void setInstallableWebApp() { }
-
- /**
* Tell the client that the page being viewed has an autofillable
* form and the user would like to set a profile up.
* @param msg A Message to send once the user has successfully
diff --git a/core/java/android/webkit/WebHistoryItem.java b/core/java/android/webkit/WebHistoryItem.java
index 788d05c..3e0b177 100644
--- a/core/java/android/webkit/WebHistoryItem.java
+++ b/core/java/android/webkit/WebHistoryItem.java
@@ -18,9 +18,6 @@ package android.webkit;
import android.graphics.Bitmap;
-import java.net.MalformedURLException;
-import java.net.URL;
-
/**
* A convenience class for accessing fields in an entry in the back/forward list
* of a WebView. Each WebHistoryItem is a snapshot of the requested history
@@ -28,67 +25,8 @@ import java.net.URL;
* @see WebBackForwardList
*/
public class WebHistoryItem implements Cloneable {
- // Global identifier count.
- private static int sNextId = 0;
- // Unique identifier.
- private final int mId;
- // A point to a native WebHistoryItem instance which contains the actual data
- private int mNativeBridge;
- // The favicon for this item.
- private Bitmap mFavicon;
- // The pre-flattened data used for saving the state.
- private byte[] mFlattenedData;
- // The apple-touch-icon url for use when adding the site to the home screen,
- // as obtained from a <link> element in the page.
- private String mTouchIconUrlFromLink;
- // If no <link> is specified, this holds the default location of the
- // apple-touch-icon.
- private String mTouchIconUrlServerDefault;
- // Custom client data that is not flattened or read by native code.
- private Object mCustomData;
-
- /**
- * Basic constructor that assigns a unique id to the item. Called by JNI
- * only.
- */
- private WebHistoryItem(int nativeBridge) {
- synchronized (WebHistoryItem.class) {
- mId = sNextId++;
- }
- mNativeBridge = nativeBridge;
- nativeRef(mNativeBridge);
- }
-
- protected void finalize() throws Throwable {
- if (mNativeBridge != 0) {
- nativeUnref(mNativeBridge);
- mNativeBridge = 0;
- }
- }
- /**
- * Construct a new WebHistoryItem with initial flattened data.
- * @param data The pre-flattened data coming from restoreState.
- */
- /*package*/ WebHistoryItem(byte[] data) {
- mFlattenedData = data;
- synchronized (WebHistoryItem.class) {
- mId = sNextId++;
- }
- }
-
- /**
- * Construct a clone of a WebHistoryItem from the given item.
- * @param item The history item to clone.
- */
- private WebHistoryItem(WebHistoryItem item) {
- mFlattenedData = item.mFlattenedData;
- mId = item.mId;
- mFavicon = item.mFavicon;
- mNativeBridge = item.mNativeBridge;
- if (mNativeBridge != 0) {
- nativeRef(mNativeBridge);
- }
+ /* package */ WebHistoryItem() {
}
/**
@@ -100,7 +38,7 @@ public class WebHistoryItem implements Cloneable {
*/
@Deprecated
public int getId() {
- return mId;
+ throw new MustOverrideException();
}
/**
@@ -112,8 +50,7 @@ public class WebHistoryItem implements Cloneable {
* to synchronize this method.
*/
public String getUrl() {
- if (mNativeBridge == 0) return null;
- return nativeGetUrl(mNativeBridge);
+ throw new MustOverrideException();
}
/**
@@ -123,8 +60,7 @@ public class WebHistoryItem implements Cloneable {
* @return The original url of this history item.
*/
public String getOriginalUrl() {
- if (mNativeBridge == 0) return null;
- return nativeGetOriginalUrl(mNativeBridge);
+ throw new MustOverrideException();
}
/**
@@ -134,8 +70,7 @@ public class WebHistoryItem implements Cloneable {
* to synchronize this method.
*/
public String getTitle() {
- if (mNativeBridge == 0) return null;
- return nativeGetTitle(mNativeBridge);
+ throw new MustOverrideException();
}
/**
@@ -145,119 +80,14 @@ public class WebHistoryItem implements Cloneable {
* to synchronize this method.
*/
public Bitmap getFavicon() {
- if (mFavicon == null && mNativeBridge != 0) {
- mFavicon = nativeGetFavicon(mNativeBridge);
- }
- return mFavicon;
- }
-
- /**
- * Return the touch icon url.
- * If no touch icon <link> tag was specified, returns
- * <host>/apple-touch-icon.png. The DownloadTouchIcon class that
- * attempts to retrieve the touch icon will handle the case where
- * that file does not exist. An icon set by a <link> tag is always
- * used in preference to an icon saved on the server.
- * @hide
- */
- public String getTouchIconUrl() {
- if (mTouchIconUrlFromLink != null) {
- return mTouchIconUrlFromLink;
- } else if (mTouchIconUrlServerDefault != null) {
- return mTouchIconUrlServerDefault;
- }
-
- try {
- URL url = new URL(getOriginalUrl());
- mTouchIconUrlServerDefault = new URL(url.getProtocol(), url.getHost(), url.getPort(),
- "/apple-touch-icon.png").toString();
- } catch (MalformedURLException e) {
- return null;
- }
- return mTouchIconUrlServerDefault;
- }
-
- /**
- * Return the custom data provided by the client.
- * @hide
- */
- public Object getCustomData() {
- return mCustomData;
- }
-
- /**
- * Set the custom data field.
- * @param data An Object containing any data the client wishes to associate
- * with the item.
- * @hide
- */
- public void setCustomData(Object data) {
- // NOTE: WebHistoryItems are used in multiple threads. However, the
- // public facing apis are all getters with the exception of this one
- // api. Since this api is exclusive to clients, we don't make any
- // promises about thread safety.
- mCustomData = data;
- }
-
- /**
- * Set the favicon.
- * @param icon A Bitmap containing the favicon for this history item.
- * Note: The VM ensures 32-bit atomic read/write operations so we don't have
- * to synchronize this method.
- */
- /*package*/ void setFavicon(Bitmap icon) {
- mFavicon = icon;
- }
-
- /**
- * Set the touch icon url. Will not overwrite an icon that has been
- * set already from a <link> tag, unless the new icon is precomposed.
- * @hide
- */
- /*package*/ void setTouchIconUrl(String url, boolean precomposed) {
- if (precomposed || mTouchIconUrlFromLink == null) {
- mTouchIconUrlFromLink = url;
- }
- }
-
- /**
- * Get the pre-flattened data.
- * Note: The VM ensures 32-bit atomic read/write operations so we don't have
- * to synchronize this method.
- */
- /*package*/ byte[] getFlattenedData() {
- if (mNativeBridge != 0) {
- return nativeGetFlattenedData(mNativeBridge);
- }
- return mFlattenedData;
- }
-
- /**
- * Inflate this item.
- * Note: The VM ensures 32-bit atomic read/write operations so we don't have
- * to synchronize this method.
- */
- /*package*/ void inflate(int nativeFrame) {
- mNativeBridge = inflate(nativeFrame, mFlattenedData);
- mFlattenedData = null;
+ throw new MustOverrideException();
}
/**
* Clone the history item for use by clients of WebView.
*/
protected synchronized WebHistoryItem clone() {
- return new WebHistoryItem(this);
+ throw new MustOverrideException();
}
- /* Natively inflate this item, this method is called in the WebCore thread.
- */
- private native int inflate(int nativeFrame, byte[] data);
- private native void nativeRef(int nptr);
- private native void nativeUnref(int nptr);
- private native String nativeGetTitle(int nptr);
- private native String nativeGetUrl(int nptr);
- private native String nativeGetOriginalUrl(int nptr);
- private native byte[] nativeGetFlattenedData(int nptr);
- private native Bitmap nativeGetFavicon(int nptr);
-
}
diff --git a/core/java/android/webkit/WebHistoryItemClassic.java b/core/java/android/webkit/WebHistoryItemClassic.java
new file mode 100644
index 0000000..1620fbf
--- /dev/null
+++ b/core/java/android/webkit/WebHistoryItemClassic.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.graphics.Bitmap;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/* package */ class WebHistoryItemClassic extends WebHistoryItem implements Cloneable {
+ // Global identifier count.
+ private static int sNextId = 0;
+ // Unique identifier.
+ private final int mId;
+ // A point to a native WebHistoryItem instance which contains the actual data
+ private int mNativeBridge;
+ // The favicon for this item.
+ private Bitmap mFavicon;
+ // The pre-flattened data used for saving the state.
+ private byte[] mFlattenedData;
+ // The apple-touch-icon url for use when adding the site to the home screen,
+ // as obtained from a <link> element in the page.
+ private String mTouchIconUrlFromLink;
+ // If no <link> is specified, this holds the default location of the
+ // apple-touch-icon.
+ private String mTouchIconUrlServerDefault;
+ // Custom client data that is not flattened or read by native code.
+ private Object mCustomData;
+
+ /**
+ * Basic constructor that assigns a unique id to the item. Called by JNI
+ * only.
+ */
+ private WebHistoryItemClassic(int nativeBridge) {
+ synchronized (WebHistoryItemClassic.class) {
+ mId = sNextId++;
+ }
+ mNativeBridge = nativeBridge;
+ nativeRef(mNativeBridge);
+ }
+
+ protected void finalize() throws Throwable {
+ if (mNativeBridge != 0) {
+ nativeUnref(mNativeBridge);
+ mNativeBridge = 0;
+ }
+ }
+
+ /**
+ * Construct a new WebHistoryItem with initial flattened data.
+ * @param data The pre-flattened data coming from restoreState.
+ */
+ /*package*/ WebHistoryItemClassic(byte[] data) {
+ mFlattenedData = data;
+ synchronized (WebHistoryItemClassic.class) {
+ mId = sNextId++;
+ }
+ }
+
+ /**
+ * Construct a clone of a WebHistoryItem from the given item.
+ * @param item The history item to clone.
+ */
+ private WebHistoryItemClassic(WebHistoryItemClassic item) {
+ mFlattenedData = item.mFlattenedData;
+ mId = item.mId;
+ mFavicon = item.mFavicon;
+ mNativeBridge = item.mNativeBridge;
+ if (mNativeBridge != 0) {
+ nativeRef(mNativeBridge);
+ }
+ }
+
+ @Deprecated
+ public int getId() {
+ return mId;
+ }
+
+ public String getUrl() {
+ if (mNativeBridge == 0) return null;
+ return nativeGetUrl(mNativeBridge);
+ }
+
+ public String getOriginalUrl() {
+ if (mNativeBridge == 0) return null;
+ return nativeGetOriginalUrl(mNativeBridge);
+ }
+
+ public String getTitle() {
+ if (mNativeBridge == 0) return null;
+ return nativeGetTitle(mNativeBridge);
+ }
+
+ public Bitmap getFavicon() {
+ if (mFavicon == null && mNativeBridge != 0) {
+ mFavicon = nativeGetFavicon(mNativeBridge);
+ }
+ return mFavicon;
+ }
+
+ /**
+ * Return the touch icon url.
+ * If no touch icon <link> tag was specified, returns
+ * <host>/apple-touch-icon.png. The DownloadTouchIcon class that
+ * attempts to retrieve the touch icon will handle the case where
+ * that file does not exist. An icon set by a <link> tag is always
+ * used in preference to an icon saved on the server.
+ * @hide
+ */
+ public String getTouchIconUrl() {
+ if (mTouchIconUrlFromLink != null) {
+ return mTouchIconUrlFromLink;
+ } else if (mTouchIconUrlServerDefault != null) {
+ return mTouchIconUrlServerDefault;
+ }
+
+ try {
+ URL url = new URL(getOriginalUrl());
+ mTouchIconUrlServerDefault = new URL(url.getProtocol(), url.getHost(), url.getPort(),
+ "/apple-touch-icon.png").toString();
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ return mTouchIconUrlServerDefault;
+ }
+
+ /**
+ * Return the custom data provided by the client.
+ * @hide
+ */
+ public Object getCustomData() {
+ return mCustomData;
+ }
+
+ /**
+ * Set the custom data field.
+ * @param data An Object containing any data the client wishes to associate
+ * with the item.
+ * @hide
+ */
+ public void setCustomData(Object data) {
+ // NOTE: WebHistoryItems are used in multiple threads. However, the
+ // public facing apis are all getters with the exception of this one
+ // api. Since this api is exclusive to clients, we don't make any
+ // promises about thread safety.
+ mCustomData = data;
+ }
+
+ /**
+ * Set the favicon.
+ * @param icon A Bitmap containing the favicon for this history item.
+ * Note: The VM ensures 32-bit atomic read/write operations so we don't have
+ * to synchronize this method.
+ */
+ /*package*/ void setFavicon(Bitmap icon) {
+ mFavicon = icon;
+ }
+
+ /**
+ * Set the touch icon url. Will not overwrite an icon that has been
+ * set already from a <link> tag, unless the new icon is precomposed.
+ * @hide
+ */
+ /*package*/ void setTouchIconUrl(String url, boolean precomposed) {
+ if (precomposed || mTouchIconUrlFromLink == null) {
+ mTouchIconUrlFromLink = url;
+ }
+ }
+
+ /**
+ * Get the pre-flattened data.
+ * Note: The VM ensures 32-bit atomic read/write operations so we don't have
+ * to synchronize this method.
+ */
+ /*package*/ byte[] getFlattenedData() {
+ if (mNativeBridge != 0) {
+ return nativeGetFlattenedData(mNativeBridge);
+ }
+ return mFlattenedData;
+ }
+
+ /**
+ * Inflate this item.
+ * Note: The VM ensures 32-bit atomic read/write operations so we don't have
+ * to synchronize this method.
+ */
+ /*package*/ void inflate(int nativeFrame) {
+ mNativeBridge = inflate(nativeFrame, mFlattenedData);
+ mFlattenedData = null;
+ }
+
+ public synchronized WebHistoryItemClassic clone() {
+ return new WebHistoryItemClassic(this);
+ }
+
+ /* Natively inflate this item, this method is called in the WebCore thread.
+ */
+ private native int inflate(int nativeFrame, byte[] data);
+ private native void nativeRef(int nptr);
+ private native void nativeUnref(int nptr);
+ private native String nativeGetTitle(int nptr);
+ private native String nativeGetUrl(int nptr);
+ private native String nativeGetOriginalUrl(int nptr);
+ private native byte[] nativeGetFlattenedData(int nptr);
+ private native Bitmap nativeGetFavicon(int nptr);
+
+}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index fa3cb20..f2a041a 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -153,7 +153,8 @@ public abstract class WebSettings {
}
/**
- * Enables dumping the pages navigation cache to a text file.
+ * Enables dumping the pages navigation cache to a text file. The default
+ * is false.
*
* @deprecated This method is now obsolete.
*/
@@ -165,6 +166,8 @@ public abstract class WebSettings {
/**
* Gets whether dumping the navigation cache is enabled.
*
+ * @return whether dumping the navigation cache is enabled
+ * @see #setNavDump
* @deprecated This method is now obsolete.
*/
@Deprecated
@@ -285,14 +288,18 @@ public abstract class WebSettings {
}
/**
- * Sets whether the WebView loads a page with overview mode.
+ * Sets whether the WebView loads pages in overview mode. The default is
+ * false.
*/
public void setLoadWithOverviewMode(boolean overview) {
throw new MustOverrideException();
}
/**
- * Gets whether this WebView loads pages with overview mode.
+ * Gets whether this WebView loads pages in overview mode.
+ *
+ * @return whether this WebView loads pages in overview mode
+ * @see #setLoadWithOverviewMode
*/
public boolean getLoadWithOverviewMode() {
throw new MustOverrideException();
@@ -344,38 +351,45 @@ public abstract class WebSettings {
}
/**
- * Sets whether the WebView is saving form data.
+ * Sets whether the WebView should save form data. The default is true,
+ * unless in private browsing mode, when the value is always false.
*/
public void setSaveFormData(boolean save) {
throw new MustOverrideException();
}
/**
- * Gets whether the WebView is saving form data and displaying prior
- * entries/autofill++. Always false in private browsing mode.
+ * Gets whether the WebView saves form data. Always false in private
+ * browsing mode.
+ *
+ * @return whether the WebView saves form data
+ * @see #setSaveFormData
*/
public boolean getSaveFormData() {
throw new MustOverrideException();
}
/**
- * Stores whether the WebView is saving password.
+ * Sets whether the WebView should save passwords. The default is true.
*/
public void setSavePassword(boolean save) {
throw new MustOverrideException();
}
/**
- * Gets whether the WebView is saving password.
+ * Gets whether the WebView saves passwords.
+ *
+ * @return whether the WebView saves passwords
+ * @see #setSavePassword
*/
public boolean getSavePassword() {
throw new MustOverrideException();
}
/**
- * Sets the text zoom of the page in percent. Default is 100.
+ * Sets the text zoom of the page in percent. The default is 100.
*
- * @param textZoom the percent value for increasing or decreasing the text
+ * @param textZoom the text zoom in percent
*/
public synchronized void setTextZoom(int textZoom) {
throw new MustOverrideException();
@@ -384,7 +398,7 @@ public abstract class WebSettings {
/**
* Gets the text zoom of the page in percent.
*
- * @return a percent value describing the text zoom
+ * @return the text zoom of the page in percent
* @see #setTextSizeZoom
*/
public synchronized int getTextZoom() {
@@ -392,11 +406,10 @@ public abstract class WebSettings {
}
/**
- * Sets the text size of the page.
+ * Sets the text size of the page. The default is {@link TextSize#NORMAL}.
*
- * @param t the TextSize value for increasing or decreasing the text
- * @see WebSettings.TextSize
- * @deprecated Use {@link #setTextZoom(int)} instead.
+ * @param t the text size as a {@link TextSize} value
+ * @deprecated Use {@link #setTextZoom} instead.
*/
public synchronized void setTextSize(TextSize t) {
throw new MustOverrideException();
@@ -404,33 +417,33 @@ public abstract class WebSettings {
/**
* Gets the text size of the page. If the text size was previously specified
- * in percent using {@link #setTextZoom(int)}, this will return
- * the closest matching {@link TextSize}.
+ * in percent using {@link #setTextZoom}, this will return the closest
+ * matching {@link TextSize}.
*
- * @return a TextSize enum value describing the text size
- * @see WebSettings.TextSize
- * @deprecated Use {@link #getTextZoom()} instead.
+ * @return the text size as a {@link TextSize} value
+ * @see #setTextSize
+ * @deprecated Use {@link #getTextZoom} instead.
*/
public synchronized TextSize getTextSize() {
throw new MustOverrideException();
}
/**
- * Sets the default zoom density of the page. This should be called from UI
- * thread.
+ * Sets the default zoom density of the page. This must be called from the UI
+ * thread. The default is {@link ZoomDensity#MEDIUM}.
*
- * @param zoom a ZoomDensity value
- * @see WebSettings.ZoomDensity
+ * @param zoom the zoom density
*/
public void setDefaultZoom(ZoomDensity zoom) {
throw new MustOverrideException();
}
/**
- * Gets the default zoom density of the page. This should be called from UI
- * thread.
- * @return a ZoomDensity value
- * @see WebSettings.ZoomDensity
+ * Gets the default zoom density of the page. This should be called from
+ * the UI thread.
+ *
+ * @return the zoom density
+ * @see #setDefaultZoom
*/
public ZoomDensity getDefaultZoom() {
throw new MustOverrideException();
@@ -438,6 +451,7 @@ public abstract class WebSettings {
/**
* Enables using light touches to make a selection and activate mouseovers.
+ * The default is false.
*/
public void setLightTouchEnabled(boolean enabled) {
throw new MustOverrideException();
@@ -445,6 +459,9 @@ public abstract class WebSettings {
/**
* Gets whether light touches are enabled.
+ *
+ * @return whether light touches are enabled
+ * @see #setLightTouchEnabled
*/
public boolean getLightTouchEnabled() {
throw new MustOverrideException();
@@ -474,11 +491,16 @@ public abstract class WebSettings {
}
/**
- * Tells the WebView about user-agent string.
+ * Sets the user-agent string using an integer code.
+ * <ul>
+ * <li>0 means the WebView should use an Android user-agent string</li>
+ * <li>1 means the WebView should use a desktop user-agent string</li>
+ * </ul>
+ * Other values are ignored. The default is an Android user-agent string,
+ * i.e. code value 0.
*
- * @param ua 0 if the WebView should use an Android user-agent string,
- * 1 if the WebView should use a desktop user-agent string
- * @deprecated Please use setUserAgentString instead.
+ * @param ua the integer code for the user-agent string
+ * @deprecated Please use {@link #setUserAgentString} instead.
*/
@Deprecated
public synchronized void setUserAgent(int ua) {
@@ -486,12 +508,17 @@ public abstract class WebSettings {
}
/**
- * Gets the user-agent as an int.
+ * Gets the user-agent as an integer code.
+ * <ul>
+ * <li>-1 means the WebView is using a custom user-agent string set with
+ * {@link #setUserAgentString}</li>
+ * <li>0 means the WebView should use an Android user-agent string</li>
+ * <li>1 means the WebView should use a desktop user-agent string</li>
+ * </ul>
*
- * @return 0 if the WebView is using an Android user-agent string,
- * 1 if the WebView is using a desktop user-agent string,
- * -1 if the WebView is using user defined user-agent string
- * @deprecated Please use getUserAgentString instead.
+ * @return the integer code for the user-agent string
+ * @see #setUserAgent
+ * @deprecated Please use {@link #getUserAgentString} instead.
*/
@Deprecated
public synchronized int getUserAgent() {
@@ -499,7 +526,9 @@ public abstract class WebSettings {
}
/**
- * Tells the WebView to use the wide viewport.
+ * Tells the WebView to use a wide viewport. The default is false.
+ *
+ * @param use whether to use a wide viewport
*/
public synchronized void setUseWideViewPort(boolean use) {
throw new MustOverrideException();
@@ -509,26 +538,28 @@ public abstract class WebSettings {
* Gets whether the WebView is using a wide viewport.
*
* @return true if the WebView is using a wide viewport
+ * @see #setUseWideViewPort
*/
public synchronized boolean getUseWideViewPort() {
throw new MustOverrideException();
}
/**
- * Tells the WebView whether it supports multiple windows. TRUE means
- * that {@link WebChromeClient#onCreateWindow(WebView, boolean,
- * boolean, Message)} is implemented by the host application.
+ * Sets whether the WebView whether supports multiple windows. If set to
+ * true, {@link WebChromeClient#onCreateWindow} must be implemented by the
+ * host application. The default is false.
+ *
+ * @param support whether to suport multiple windows
*/
public synchronized void setSupportMultipleWindows(boolean support) {
throw new MustOverrideException();
}
/**
- * Gets whether the WebView is supporting multiple windows.
+ * Gets whether the WebView supports multiple windows.
*
- * @return true if the WebView is supporting multiple windows. This means
- * that {@link WebChromeClient#onCreateWindow(WebView, boolean,
- * boolean, Message)} is implemented by the host application.
+ * @return true if the WebView supports multiple windows
+ * @see #setSupportMultipleWindows
*/
public synchronized boolean supportMultipleWindows() {
throw new MustOverrideException();
@@ -536,10 +567,9 @@ public abstract class WebSettings {
/**
* Sets the underlying layout algorithm. This will cause a relayout of the
- * WebView. The default is NARROW_COLUMNS.
+ * WebView. The default is {@link LayoutAlgorithm#NARROW_COLUMNS}.
*
- * @param l a LayoutAlgorithm enum specifying the algorithm to use
- * @see WebSettings.LayoutAlgorithm
+ * @param l the layout algorithm to use, as a {@link LayoutAlgorithm} value
*/
public synchronized void setLayoutAlgorithm(LayoutAlgorithm l) {
throw new MustOverrideException();
@@ -548,10 +578,8 @@ public abstract class WebSettings {
/**
* Gets the current layout algorithm.
*
- * @return a LayoutAlgorithm enum value describing the layout algorithm
- * being used
+ * @return the layout algorithm in use, as a {@link LayoutAlgorithm} value
* @see #setLayoutAlgorithm
- * @see WebSettings.LayoutAlgorithm
*/
public synchronized LayoutAlgorithm getLayoutAlgorithm() {
throw new MustOverrideException();
@@ -596,7 +624,7 @@ public abstract class WebSettings {
}
/**
- * Sets the sans-serif font family name.
+ * Sets the sans-serif font family name. The default is "sans-serif".
*
* @param font a font family name
*/
@@ -608,6 +636,7 @@ public abstract class WebSettings {
* Gets the sans-serif font family name.
*
* @return the sans-serif font family name as a string
+ * @see #setSansSerifFontFamily
*/
public synchronized String getSansSerifFontFamily() {
throw new MustOverrideException();
@@ -883,9 +912,9 @@ public abstract class WebSettings {
public abstract void setAllowFileAccessFromFileURLs(boolean flag);
/**
- * Tells the WebView to enable plugins.
+ * Sets whether the WebView should enable plugins. The default is false.
*
- * @param flag true if the WebView should load plugins
+ * @param flag true if plugins should be enabled
* @deprecated This method has been deprecated in favor of
* {@link #setPluginState}
*/
@@ -898,7 +927,8 @@ public abstract class WebSettings {
* Tells the WebView to enable, disable, or have plugins on demand. On
* demand mode means that if a plugin exists that can handle the embedded
* content, a placeholder icon will be shown instead of the plugin. When
- * the placeholder is clicked, the plugin will be enabled.
+ * the placeholder is clicked, the plugin will be enabled. The default is
+ * {@link PluginState#OFF}.
*
* @param state a PluginState value
*/
@@ -921,23 +951,27 @@ public abstract class WebSettings {
/**
* Sets the path to where database storage API databases should be saved.
- * Note that the WebCore Database Tracker only allows the path to be set once.
+ * In order for the database storage API to function correctly, this method
+ * must be called with a path to which the application can write. This
+ * method should only be called once: repeated calls are ignored.
*
- * @param databasePath a String path to the directory where databases should
- * be saved. May be the empty string but should never
- * be null.
+ * @param databasePath a path to the directory where databases should be
+ * saved.
*/
// This will update WebCore when the Sync runs in the C++ side.
+ // Note that the WebCore Database Tracker only allows the path to be set
+ // once.
public synchronized void setDatabasePath(String databasePath) {
throw new MustOverrideException();
}
/**
- * Sets the path where the Geolocation permissions database should be saved.
+ * Sets the path where the Geolocation databases should be saved. In order
+ * for Geolocation permissions and cached positions to be persisted, this
+ * method must be called with a path to which the application can write.
*
- * @param databasePath a String path to the directory where the Geolocation
- * permissions database should be saved. May be the
- * empty string but should never be null.
+ * @param databasePath a path to the directory where databases should be
+ * saved.
*/
// This will update WebCore when the Sync runs in the C++ side.
public synchronized void setGeolocationDatabasePath(String databasePath) {
@@ -945,7 +979,10 @@ public abstract class WebSettings {
}
/**
- * Tells the WebView to enable Application Caches API.
+ * Sets whether the Application Caches API should be enabled. The default
+ * is false. Note that in order for the Application Caches API to be
+ * enabled, a valid database path must also be supplied to
+ * {@link #setAppCachePath}.
*
* @param flag true if the WebView should enable Application Caches
*/
@@ -954,20 +991,22 @@ public abstract class WebSettings {
}
/**
- * Sets a custom path to the Application Caches files. The client
- * must ensure it exists before this call.
+ * Sets the path to the Application Caches files. In order for the
+ * Application Caches API to be enabled, this method must be called with a
+ * path to which the application can write. This method should only be
+ * called once: repeated calls are ignored.
*
* @param appCachePath a String path to the directory containing
- * Application Caches files. The appCache path can be
- * the empty string but should not be null. Passing
- * null for this parameter will result in a no-op.
+ * Application Caches files.
+ * @see setAppCacheEnabled
*/
public synchronized void setAppCachePath(String appCachePath) {
throw new MustOverrideException();
}
/**
- * Sets the maximum size for the Application Caches content.
+ * Sets the maximum size for the Application Caches content. The default is
+ * {@link Long#MAX_VALUE}.
*
* @param appCacheMaxSize the maximum size in bytes
*/
@@ -976,7 +1015,9 @@ public abstract class WebSettings {
}
/**
- * Sets whether the database storage API is enabled.
+ * Sets whether the database storage API is enabled. The default value is
+ * false. See also {@link #setDatabasePath} for how to correctly set up the
+ * database storage API.
*
* @param flag true if the WebView should use the database storage API
*/
@@ -985,7 +1026,7 @@ public abstract class WebSettings {
}
/**
- * Sets whether the DOM storage API is enabled.
+ * Sets whether the DOM storage API is enabled. The default value is false.
*
* @param flag true if the WebView should use the DOM storage API
*/
@@ -997,15 +1038,16 @@ public abstract class WebSettings {
* Gets whether the DOM Storage APIs are enabled.
*
* @return true if the DOM Storage APIs are enabled
+ * @see #setDomStorageEnabled
*/
public synchronized boolean getDomStorageEnabled() {
throw new MustOverrideException();
}
/**
- * Gets the path to where database storage API databases are saved for
- * the current WebView.
+ * Gets the path to where database storage API databases are saved.
*
* @return the String path to the database storage API databases
+ * @see #setDatabasePath
*/
public synchronized String getDatabasePath() {
throw new MustOverrideException();
@@ -1015,13 +1057,16 @@ public abstract class WebSettings {
* Gets whether the database storage API is enabled.
*
* @return true if the database storage API is enabled
+ * @see #setDatabaseEnabled
*/
public synchronized boolean getDatabaseEnabled() {
throw new MustOverrideException();
}
/**
- * Sets whether Geolocation is enabled.
+ * Sets whether Geolocation is enabled. The default is true. See also
+ * {@link #setGeolocationDatabasePath} for how to correctly set up
+ * Geolocation.
*
* @param flag whether Geolocation should be enabled
*/
@@ -1064,6 +1109,7 @@ public abstract class WebSettings {
* Gets whether plugins are enabled.
*
* @return true if plugins are enabled
+ * @see #setPluginsEnabled
* @deprecated This method has been replaced by {@link #getPluginState}
*/
@Deprecated
@@ -1072,9 +1118,10 @@ public abstract class WebSettings {
}
/**
- * Gets the current plugin state.
+ * Gets the current state regarding whether plugins are enabled.
*
- * @return a value corresponding to the enum PluginState
+ * @return the plugin state as a {@link PluginState} value
+ * @see #setPluginState
*/
public synchronized PluginState getPluginState() {
throw new MustOverrideException();
@@ -1135,8 +1182,8 @@ public abstract class WebSettings {
}
/**
- * Sets the WebView's user-agent string. If the string "ua" is null or empty,
- * it will use the system default user-agent string.
+ * Sets the WebView's user-agent string. If the string is null or empty,
+ * the system default value will be used.
*/
public synchronized void setUserAgentString(String ua) {
throw new MustOverrideException();
@@ -1144,6 +1191,9 @@ public abstract class WebSettings {
/**
* Gets the WebView's user-agent string.
+ *
+ * @return the WebView's user-agent string
+ * @see #setUserAgentString
*/
public synchronized String getUserAgentString() {
throw new MustOverrideException();
@@ -1151,7 +1201,8 @@ public abstract class WebSettings {
/**
* Tells the WebView whether it needs to set a node to have focus when
- * {@link WebView#requestFocus(int, android.graphics.Rect)} is called.
+ * {@link WebView#requestFocus(int, android.graphics.Rect)} is called. The
+ * default value is true.
*
* @param flag whether the WebView needs to set a node
*/
@@ -1161,9 +1212,10 @@ public abstract class WebSettings {
/**
* Sets the priority of the Render thread. Unlike the other settings, this
- * one only needs to be called once per process. The default is NORMAL.
+ * one only needs to be called once per process. The default value is
+ * {@link RenderPriority#NORMAL}.
*
- * @param priority a RenderPriority
+ * @param priority the priority
*/
public synchronized void setRenderPriority(RenderPriority priority) {
throw new MustOverrideException();
@@ -1171,20 +1223,25 @@ public abstract class WebSettings {
/**
* Overrides the way the cache is used. The way the cache is used is based
- * on the navigation option. For a normal page load, the cache is checked
+ * on the navigation type. For a normal page load, the cache is checked
* and content is re-validated as needed. When navigating back, content is
- * not revalidated, instead the content is just pulled from the cache.
- * This function allows the client to override this behavior.
+ * not revalidated, instead the content is just retrieved from the cache.
+ * This method allows the client to override this behavior by specifying
+ * one of {@link #LOAD_DEFAULT}, {@link #LOAD_NORMAL},
+ * {@link #LOAD_CACHE_ELSE_NETWORK}, {@link #LOAD_NO_CACHE} or
+ * {@link #LOAD_CACHE_ONLY}. The default value is {@link #LOAD_DEFAULT}.
*
- * @param mode one of the LOAD_ values
+ * @param mode the mode to use
*/
public void setCacheMode(int mode) {
throw new MustOverrideException();
}
/**
- * Gets the current setting for overriding the cache mode. For a full
- * description, see the {@link #setCacheMode(int)} function.
+ * Gets the current setting for overriding the cache mode.
+ *
+ * @return the current setting for overriding the cache mode
+ * @see #setCacheMode
*/
public int getCacheMode() {
throw new MustOverrideException();
diff --git a/core/java/android/webkit/WebSyncManager.java b/core/java/android/webkit/WebSyncManager.java
index 38b5e5c..d3ec603 100644
--- a/core/java/android/webkit/WebSyncManager.java
+++ b/core/java/android/webkit/WebSyncManager.java
@@ -37,9 +37,6 @@ abstract class WebSyncManager implements Runnable {
// handler of the sync thread
protected Handler mHandler;
// database for the persistent storage
- // Note that this remains uninitialised as it is unused. We cannot remove
- // the member as it leaked into the public API via CookieSyncManager.
- // TODO: hide this member, ditto for mHandler.
protected WebViewDatabase mDataBase;
// Ref count for calls to start/stop sync
private int mStartSyncRefCount;
@@ -65,6 +62,7 @@ abstract class WebSyncManager implements Runnable {
protected WebSyncManager(Context context, String name) {
mThreadName = name;
if (context != null) {
+ mDataBase = WebViewDatabase.getInstance(context);
mSyncThread = new Thread(this);
mSyncThread.setName(mThreadName);
mSyncThread.start();
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 119fcd3..2545cd8 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -35,8 +35,8 @@ import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewDebug;
import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -44,6 +44,7 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.widget.AbsoluteLayout;
+import java.io.BufferedWriter;
import java.io.File;
import java.util.Map;
@@ -263,7 +264,7 @@ import java.util.Map;
@Widget
public class WebView extends AbsoluteLayout
implements ViewTreeObserver.OnGlobalFocusChangeListener,
- ViewGroup.OnHierarchyChangeListener {
+ ViewGroup.OnHierarchyChangeListener, ViewDebug.HierarchyHandler {
private static final String LOGTAG = "webview_proxy";
@@ -1004,6 +1005,7 @@ public class WebView extends AbsoluteLayout
*
* @return the current scale
*/
+ @ViewDebug.ExportedProperty(category = "webview")
public float getScale() {
checkThread();
return mProvider.getScale();
@@ -1094,6 +1096,7 @@ public class WebView extends AbsoluteLayout
*
* @return the URL for the current page
*/
+ @ViewDebug.ExportedProperty(category = "webview")
public String getUrl() {
checkThread();
return mProvider.getUrl();
@@ -1108,6 +1111,7 @@ public class WebView extends AbsoluteLayout
*
* @return the URL that was originally requested for the current page
*/
+ @ViewDebug.ExportedProperty(category = "webview")
public String getOriginalUrl() {
checkThread();
return mProvider.getOriginalUrl();
@@ -1119,6 +1123,7 @@ public class WebView extends AbsoluteLayout
*
* @return the title for the current page
*/
+ @ViewDebug.ExportedProperty(category = "webview")
public String getTitle() {
checkThread();
return mProvider.getTitle();
@@ -1161,6 +1166,7 @@ public class WebView extends AbsoluteLayout
*
* @return the height of the HTML content
*/
+ @ViewDebug.ExportedProperty(category = "webview")
public int getContentHeight() {
checkThread();
return mProvider.getContentHeight();
@@ -1172,6 +1178,7 @@ public class WebView extends AbsoluteLayout
* @return the width of the HTML content
* @hide
*/
+ @ViewDebug.ExportedProperty(category = "webview")
public int getContentWidth() {
return mProvider.getContentWidth();
}
@@ -1652,6 +1659,24 @@ public class WebView extends AbsoluteLayout
mProvider.debugDump();
}
+ /**
+ * See {@link ViewDebug.HierarchyHandler#dumpViewHierarchyWithProperties(BufferedWriter, int)}
+ * @hide
+ */
+ @Override
+ public void dumpViewHierarchyWithProperties(BufferedWriter out, int level) {
+ mProvider.dumpViewHierarchyWithProperties(out, level);
+ }
+
+ /**
+ * See {@link ViewDebug.HierarchyHandler#findHierarchyView(String, int)}
+ * @hide
+ */
+ @Override
+ public View findHierarchyView(String className, int hashCode) {
+ return mProvider.findHierarchyView(className, hashCode);
+ }
+
//-------------------------------------------------------------------------
// Interface for WebView providers
//-------------------------------------------------------------------------
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 84a6129..5eefbe1 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -117,6 +117,8 @@ import android.widget.Toast;
import junit.framework.Assert;
+import java.io.BufferedWriter;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -132,6 +134,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
+import java.util.concurrent.CountDownLatch;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -679,6 +682,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
// after resize.
static private final int EDIT_RECT_BUFFER = 10;
+ static private final long SELECTION_HANDLE_ANIMATION_MS = 150;
+
// true means redraw the screen all-the-time. Only with AUTO_REDRAW_HACK
private boolean mAutoRedraw;
@@ -945,21 +950,20 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
private Drawable mSelectHandleLeft;
private Drawable mSelectHandleRight;
private Drawable mSelectHandleCenter;
- private Point mSelectHandleLeftOffset;
- private Point mSelectHandleRightOffset;
- private Point mSelectHandleCenterOffset;
- private Point mSelectCursorLeft = new Point();
- private int mSelectCursorLeftLayerId;
- private QuadF mSelectCursorLeftTextQuad = new QuadF();
- private Point mSelectCursorRight = new Point();
- private int mSelectCursorRightLayerId;
- private QuadF mSelectCursorRightTextQuad = new QuadF();
+ private Point mSelectOffset;
+ private Point mSelectCursorBase = new Point();
+ private Rect mSelectHandleBaseBounds = new Rect();
+ private int mSelectCursorBaseLayerId;
+ private QuadF mSelectCursorBaseTextQuad = new QuadF();
+ private Point mSelectCursorExtent = new Point();
+ private Rect mSelectHandleExtentBounds = new Rect();
+ private int mSelectCursorExtentLayerId;
+ private QuadF mSelectCursorExtentTextQuad = new QuadF();
private Point mSelectDraggingCursor;
- private Point mSelectDraggingOffset;
private QuadF mSelectDraggingTextQuad;
private boolean mIsCaretSelection;
- static final int HANDLE_ID_LEFT = 0;
- static final int HANDLE_ID_RIGHT = 1;
+ static final int HANDLE_ID_BASE = 0;
+ static final int HANDLE_ID_EXTENT = 1;
// the color used to highlight the touch rectangles
static final int HIGHLIGHT_COLOR = 0x6633b5e5;
@@ -1049,6 +1053,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
static final int EDIT_TEXT_SIZE_CHANGED = 150;
static final int SHOW_CARET_HANDLE = 151;
static final int UPDATE_CONTENT_BOUNDS = 152;
+ static final int SCROLL_HANDLE_INTO_VIEW = 153;
private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID;
private static final int LAST_PACKAGE_MSG_ID = HIT_TEST_RESULT;
@@ -2196,7 +2201,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
// We grab a copy of the back/forward list because a client of WebView
// may have invalidated the history list by calling clearHistory.
- WebBackForwardList list = copyBackForwardList();
+ WebBackForwardListClassic list = copyBackForwardList();
final int currentIndex = list.getCurrentIndex();
final int size = list.getSize();
// We should fail saving the state if the list is empty or the index is
@@ -2210,7 +2215,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
// arrays.
ArrayList<byte[]> history = new ArrayList<byte[]>(size);
for (int i = 0; i < size; i++) {
- WebHistoryItem item = list.getItemAtIndex(i);
+ WebHistoryItemClassic item = list.getItemAtIndex(i);
if (null == item) {
// FIXME: this shouldn't happen
// need to determine how item got set to null
@@ -2409,7 +2414,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
*/
@Override
public WebBackForwardList restoreState(Bundle inState) {
- WebBackForwardList returnList = null;
+ WebBackForwardListClassic returnList = null;
if (inState == null) {
return returnList;
}
@@ -2417,7 +2422,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
mCertificate = SslCertificate.restoreState(
inState.getBundle("certificate"));
- final WebBackForwardList list = mCallbackProxy.getBackForwardList();
+ final WebBackForwardListClassic list = mCallbackProxy.getBackForwardList();
final int index = inState.getInt("index");
// We can't use a clone of the list because we need to modify the
// shared copy, so synchronize instead to prevent concurrent
@@ -2438,7 +2443,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
// the item and thus our history list cannot be rebuilt.
return null;
}
- WebHistoryItem item = new WebHistoryItem(data);
+ WebHistoryItem item = new WebHistoryItemClassic(data);
list.addHistoryItem(item);
}
// Grab the most recent copy to return to the caller.
@@ -2611,7 +2616,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
*/
@Override
public boolean canGoBack() {
- WebBackForwardList l = mCallbackProxy.getBackForwardList();
+ WebBackForwardListClassic l = mCallbackProxy.getBackForwardList();
synchronized (l) {
if (l.getClearPending()) {
return false;
@@ -2634,7 +2639,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
*/
@Override
public boolean canGoForward() {
- WebBackForwardList l = mCallbackProxy.getBackForwardList();
+ WebBackForwardListClassic l = mCallbackProxy.getBackForwardList();
synchronized (l) {
if (l.getClearPending()) {
return false;
@@ -2657,7 +2662,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
*/
@Override
public boolean canGoBackOrForward(int steps) {
- WebBackForwardList l = mCallbackProxy.getBackForwardList();
+ WebBackForwardListClassic l = mCallbackProxy.getBackForwardList();
synchronized (l) {
if (l.getClearPending()) {
return false;
@@ -3305,6 +3310,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
scrollLayerTo(scrollX, scrollY);
+ animateHandles();
return;
}
mInOverScrollMode = false;
@@ -3325,6 +3331,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
mWebViewPrivate.super_scrollTo(scrollX, scrollY);
+ animateHandles();
+
if (mOverScrollGlow != null) {
mOverScrollGlow.pullGlow(getScrollX(), getScrollY(), oldX, oldY, maxX, maxY);
}
@@ -3371,7 +3379,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
*/
@Override
public String getTouchIconUrl() {
- WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
+ WebHistoryItemClassic h = mCallbackProxy.getBackForwardList().getCurrentItem();
return h != null ? h.getTouchIconUrl() : null;
}
@@ -3535,7 +3543,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
* See {@link WebView#copyBackForwardList()}
*/
@Override
- public WebBackForwardList copyBackForwardList() {
+ public WebBackForwardListClassic copyBackForwardList() {
return mCallbackProxy.getBackForwardList().clone();
}
@@ -3819,17 +3827,14 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
return;
}
if (mSelectingText) {
- if (mSelectCursorLeftLayerId == mCurrentScrollingLayerId) {
- mSelectCursorLeft.offset(dx, dy);
- mSelectCursorLeftTextQuad.offset(dx, dy);
+ if (mSelectCursorBaseLayerId == mCurrentScrollingLayerId) {
+ mSelectCursorBase.offset(dx, dy);
+ mSelectCursorBaseTextQuad.offset(dx, dy);
}
- if (mSelectCursorRightLayerId == mCurrentScrollingLayerId) {
- mSelectCursorRight.offset(dx, dy);
- mSelectCursorRightTextQuad.offset(dx, dy);
+ if (mSelectCursorExtentLayerId == mCurrentScrollingLayerId) {
+ mSelectCursorExtent.offset(dx, dy);
+ mSelectCursorExtentTextQuad.offset(dx, dy);
}
- } else if (mHandleAlpha.getAlpha() > 0) {
- // stop fading as we're not going to move with the layer.
- mHandleAlphaAnimator.end();
}
if (mAutoCompletePopup != null &&
mCurrentScrollingLayerId == mEditTextLayerId) {
@@ -4445,9 +4450,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
private void onZoomAnimationStart() {
- if (!mSelectingText && mHandleAlpha.getAlpha() > 0) {
- mHandleAlphaAnimator.end();
- }
}
private void onZoomAnimationEnd() {
@@ -4480,34 +4482,63 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
private class SelectionHandleAlpha {
private int mAlpha = 0;
+ private int mTargetAlpha = 0;
+
public void setAlpha(int alpha) {
mAlpha = alpha;
- if (mSelectHandleCenter != null) {
- mSelectHandleCenter.setAlpha(alpha);
- mSelectHandleLeft.setAlpha(alpha);
- mSelectHandleRight.setAlpha(alpha);
- // TODO: Use partial invalidate
- invalidate();
- }
+ // TODO: Use partial invalidate
+ invalidate();
}
public int getAlpha() {
return mAlpha;
}
+ public void setTargetAlpha(int alpha) {
+ mTargetAlpha = alpha;
+ }
+
+ public int getTargetAlpha() {
+ return mTargetAlpha;
+ }
+
}
private void startSelectingText() {
mSelectingText = true;
mShowTextSelectionExtra = true;
- mHandleAlphaAnimator.setIntValues(255);
- mHandleAlphaAnimator.start();
+ animateHandles();
+ }
+
+ private void animateHandle(boolean canShow, ObjectAnimator animator,
+ Point selectionPoint, int selectionLayerId,
+ SelectionHandleAlpha alpha) {
+ boolean isVisible = canShow && mSelectingText
+ && ((mSelectionStarted && mSelectDraggingCursor == selectionPoint)
+ || isHandleVisible(selectionPoint, selectionLayerId));
+ int targetValue = isVisible ? 255 : 0;
+ if (targetValue != alpha.getTargetAlpha()) {
+ alpha.setTargetAlpha(targetValue);
+ animator.setIntValues(targetValue);
+ animator.setDuration(SELECTION_HANDLE_ANIMATION_MS);
+ animator.start();
+ }
+ }
+
+ private void animateHandles() {
+ boolean canShowBase = mSelectingText;
+ boolean canShowExtent = mSelectingText && !mIsCaretSelection;
+ animateHandle(canShowBase, mBaseHandleAlphaAnimator, mSelectCursorBase,
+ mSelectCursorBaseLayerId, mBaseAlpha);
+ animateHandle(canShowExtent, mExtentHandleAlphaAnimator,
+ mSelectCursorExtent, mSelectCursorExtentLayerId,
+ mExtentAlpha);
}
+
private void endSelectingText() {
mSelectingText = false;
mShowTextSelectionExtra = false;
- mHandleAlphaAnimator.setIntValues(0);
- mHandleAlphaAnimator.start();
+ animateHandles();
}
private void ensureSelectionHandles() {
@@ -4518,66 +4549,87 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
com.android.internal.R.drawable.text_select_handle_left);
mSelectHandleRight = mContext.getResources().getDrawable(
com.android.internal.R.drawable.text_select_handle_right);
- mHandleAlpha.setAlpha(mHandleAlpha.getAlpha());
- mSelectHandleCenterOffset = new Point(0,
- -mSelectHandleCenter.getIntrinsicHeight());
- mSelectHandleLeftOffset = new Point(0,
+ // All handles have the same height, so we can save effort with
+ // this assumption.
+ mSelectOffset = new Point(0,
-mSelectHandleLeft.getIntrinsicHeight());
- mSelectHandleRightOffset = new Point(
- -mSelectHandleLeft.getIntrinsicWidth() / 2,
- -mSelectHandleRight.getIntrinsicHeight());
}
}
+ private void drawHandle(Point point, int handleId, Rect bounds,
+ int alpha, Canvas canvas) {
+ int offset;
+ int width;
+ int height;
+ Drawable drawable;
+ boolean isLeft = nativeIsHandleLeft(mNativeClass, handleId);
+ if (isLeft) {
+ drawable = mSelectHandleLeft;
+ width = mSelectHandleLeft.getIntrinsicWidth();
+ height = mSelectHandleLeft.getIntrinsicHeight();
+ // Magic formula copied from TextView
+ offset = (width * 3) / 4;
+ } else {
+ drawable = mSelectHandleRight;
+ width = mSelectHandleRight.getIntrinsicWidth();
+ height = mSelectHandleRight.getIntrinsicHeight();
+ // Magic formula copied from TextView
+ offset = width / 4;
+ }
+ int x = contentToViewDimension(point.x);
+ int y = contentToViewDimension(point.y);
+ bounds.set(x - offset, y, x - offset + width, y + height);
+ drawable.setBounds(bounds);
+ drawable.setAlpha(alpha);
+ drawable.draw(canvas);
+ }
+
private void drawTextSelectionHandles(Canvas canvas) {
- if (mHandleAlpha.getAlpha() == 0) {
+ if (mBaseAlpha.getAlpha() == 0 && mExtentAlpha.getAlpha() == 0) {
return;
}
ensureSelectionHandles();
- if (mSelectingText) {
- int[] handles = new int[4];
- getSelectionHandles(handles);
- int start_x = contentToViewDimension(handles[0]);
- int start_y = contentToViewDimension(handles[1]);
- int end_x = contentToViewDimension(handles[2]);
- int end_y = contentToViewDimension(handles[3]);
-
- if (mIsCaretSelection) {
- // Caret handle is centered
- start_x -= (mSelectHandleCenter.getIntrinsicWidth() / 2);
- mSelectHandleCenter.setBounds(start_x, start_y,
- start_x + mSelectHandleCenter.getIntrinsicWidth(),
- start_y + mSelectHandleCenter.getIntrinsicHeight());
- } else {
- // Magic formula copied from TextView
- start_x -= (mSelectHandleLeft.getIntrinsicWidth() * 3) / 4;
- mSelectHandleLeft.setBounds(start_x, start_y,
- start_x + mSelectHandleLeft.getIntrinsicWidth(),
- start_y + mSelectHandleLeft.getIntrinsicHeight());
- end_x -= mSelectHandleRight.getIntrinsicWidth() / 4;
- mSelectHandleRight.setBounds(end_x, end_y,
- end_x + mSelectHandleRight.getIntrinsicWidth(),
- end_y + mSelectHandleRight.getIntrinsicHeight());
- }
- }
-
if (mIsCaretSelection) {
+ // Caret handle is centered
+ int x = contentToViewDimension(mSelectCursorBase.x) -
+ (mSelectHandleCenter.getIntrinsicWidth() / 2);
+ int y = contentToViewDimension(mSelectCursorBase.y);
+ mSelectHandleBaseBounds.set(x, y,
+ x + mSelectHandleCenter.getIntrinsicWidth(),
+ y + mSelectHandleCenter.getIntrinsicHeight());
+ mSelectHandleCenter.setBounds(mSelectHandleBaseBounds);
+ mSelectHandleCenter.setAlpha(mBaseAlpha.getAlpha());
mSelectHandleCenter.draw(canvas);
} else {
- mSelectHandleLeft.draw(canvas);
- mSelectHandleRight.draw(canvas);
+ drawHandle(mSelectCursorBase, HANDLE_ID_BASE,
+ mSelectHandleBaseBounds, mBaseAlpha.getAlpha(), canvas);
+ drawHandle(mSelectCursorExtent, HANDLE_ID_EXTENT,
+ mSelectHandleExtentBounds, mExtentAlpha.getAlpha(), canvas);
}
}
+ private boolean isHandleVisible(Point selectionPoint, int layerId) {
+ boolean isVisible = true;
+ if (mIsEditingText) {
+ isVisible = mEditTextContentBounds.contains(selectionPoint.x,
+ selectionPoint.y);
+ }
+ if (isVisible) {
+ isVisible = nativeIsPointVisible(mNativeClass, layerId,
+ selectionPoint.x, selectionPoint.y);
+ }
+ return isVisible;
+ }
+
/**
* Takes an int[4] array as an output param with the values being
* startX, startY, endX, endY
*/
private void getSelectionHandles(int[] handles) {
- handles[0] = mSelectCursorLeft.x;
- handles[1] = mSelectCursorLeft.y;
- handles[2] = mSelectCursorRight.x;
- handles[3] = mSelectCursorRight.y;
+ handles[0] = mSelectCursorBase.x;
+ handles[1] = mSelectCursorBase.y;
+ handles[2] = mSelectCursorExtent.x;
+ handles[3] = mSelectCursorExtent.y;
}
// draw history
@@ -4812,6 +4864,43 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
/**
+ * Sets use of the Geolocation mock client. Also resets that client. Called
+ * by DRT on UI thread, need to proxy to WebCore thread.
+ *
+ * debug only
+ */
+ public void setUseMockGeolocation() {
+ mWebViewCore.sendMessage(EventHub.SET_USE_MOCK_GEOLOCATION);
+ }
+
+ /**
+ * Called by DRT on WebCore thread.
+ *
+ * debug only
+ */
+ public void setMockGeolocationPosition(double latitude, double longitude, double accuracy) {
+ mWebViewCore.setMockGeolocationPosition(latitude, longitude, accuracy);
+ }
+
+ /**
+ * Called by DRT on WebCore thread.
+ *
+ * debug only
+ */
+ public void setMockGeolocationError(int code, String message) {
+ mWebViewCore.setMockGeolocationError(code, message);
+ }
+
+ /**
+ * Called by DRT on WebCore thread.
+ *
+ * debug only
+ */
+ public void setMockGeolocationPermission(boolean allow) {
+ mWebViewCore.setMockGeolocationPermission(allow);
+ }
+
+ /**
* Called by DRT on WebCore thread.
*
* debug only
@@ -5044,8 +5133,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
ClipboardManager cm = (ClipboardManager)(mContext
.getSystemService(Context.CLIPBOARD_SERVICE));
if (cm.hasPrimaryClip()) {
- Point cursorPoint = new Point(contentToViewX(mSelectCursorLeft.x),
- contentToViewY(mSelectCursorLeft.y));
+ Point cursorPoint = new Point(contentToViewX(mSelectCursorBase.x),
+ contentToViewY(mSelectCursorBase.y));
Point cursorTop = calculateCaretTop();
cursorTop.set(contentToViewX(cursorTop.x),
contentToViewY(cursorTop.y));
@@ -5095,12 +5184,12 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
* calculates the top of a caret.
*/
private Point calculateCaretTop() {
- float scale = scaleAlongSegment(mSelectCursorLeft.x, mSelectCursorLeft.y,
- mSelectCursorLeftTextQuad.p4, mSelectCursorLeftTextQuad.p3);
+ float scale = scaleAlongSegment(mSelectCursorBase.x, mSelectCursorBase.y,
+ mSelectCursorBaseTextQuad.p4, mSelectCursorBaseTextQuad.p3);
int x = Math.round(scaleCoordinate(scale,
- mSelectCursorLeftTextQuad.p1.x, mSelectCursorLeftTextQuad.p2.x));
+ mSelectCursorBaseTextQuad.p1.x, mSelectCursorBaseTextQuad.p2.x));
int y = Math.round(scaleCoordinate(scale,
- mSelectCursorLeftTextQuad.p1.y, mSelectCursorLeftTextQuad.p2.y));
+ mSelectCursorBaseTextQuad.p1.y, mSelectCursorBaseTextQuad.p2.y));
return new Point(x, y);
}
@@ -5111,50 +5200,12 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
private void syncSelectionCursors() {
- mSelectCursorLeftLayerId =
- nativeGetHandleLayerId(mNativeClass, HANDLE_ID_LEFT,
- mSelectCursorLeft, mSelectCursorLeftTextQuad);
- mSelectCursorRightLayerId =
- nativeGetHandleLayerId(mNativeClass, HANDLE_ID_RIGHT,
- mSelectCursorRight, mSelectCursorRightTextQuad);
- }
-
- private void adjustSelectionCursors() {
- if (mIsCaretSelection) {
- syncSelectionCursors();
- return; // no need to swap left and right handles.
- }
-
- boolean wasDraggingLeft = (mSelectDraggingCursor == mSelectCursorLeft);
- int oldX = mSelectDraggingCursor.x;
- int oldY = mSelectDraggingCursor.y;
- int oldLeftX = mSelectCursorLeft.x;
- int oldLeftY = mSelectCursorLeft.y;
- int oldRightX = mSelectCursorRight.x;
- int oldRightY = mSelectCursorRight.y;
- syncSelectionCursors();
-
- boolean rightChanged = (oldRightX != mSelectCursorRight.x
- || oldRightY != mSelectCursorRight.y);
- boolean leftChanged = (oldLeftX != mSelectCursorLeft.x
- || oldLeftY != mSelectCursorLeft.y);
- if (leftChanged && rightChanged) {
- // Left and right switched places, so swap dragging cursor
- boolean draggingLeft = !wasDraggingLeft;
- mSelectDraggingCursor = (draggingLeft
- ? mSelectCursorLeft : mSelectCursorRight);
- mSelectDraggingTextQuad = (draggingLeft
- ? mSelectCursorLeftTextQuad : mSelectCursorRightTextQuad);
- mSelectDraggingOffset = (draggingLeft
- ? mSelectHandleLeftOffset : mSelectHandleRightOffset);
- }
- mSelectDraggingCursor.set(oldX, oldY);
- }
-
- private float distanceSquared(int x, int y, Point p) {
- float dx = p.x - x;
- float dy = p.y - y;
- return (dx * dx) + (dy * dy);
+ mSelectCursorBaseLayerId =
+ nativeGetHandleLayerId(mNativeClass, HANDLE_ID_BASE,
+ mSelectCursorBase, mSelectCursorBaseTextQuad);
+ mSelectCursorExtentLayerId =
+ nativeGetHandleLayerId(mNativeClass, HANDLE_ID_EXTENT,
+ mSelectCursorExtent, mSelectCursorExtentTextQuad);
}
private boolean setupWebkitSelect() {
@@ -5169,18 +5220,11 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
private void updateWebkitSelection() {
- int[] handles = null;
- if (mIsCaretSelection) {
- mSelectCursorRight.set(mSelectCursorLeft.x, mSelectCursorLeft.y);
- }
- if (mSelectingText) {
- handles = new int[4];
- getSelectionHandles(handles);
- } else {
- nativeSetTextSelection(mNativeClass, 0);
- }
+ int handleId = (mSelectDraggingCursor == mSelectCursorBase)
+ ? HANDLE_ID_BASE : HANDLE_ID_EXTENT;
mWebViewCore.removeMessages(EventHub.SELECT_TEXT);
- mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SELECT_TEXT, handles);
+ mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SELECT_TEXT,
+ mSelectDraggingCursor.x, mSelectDraggingCursor.y, (Integer)handleId);
}
private void resetCaretTimer() {
@@ -5543,21 +5587,21 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
Point caretTop = calculateCaretTop();
if (visibleRect.width() < mEditTextContentBounds.width()) {
// The whole edit won't fit in the width, so use the caret rect
- if (mSelectCursorLeft.x < caretTop.x) {
- showRect.left = Math.max(0, mSelectCursorLeft.x - buffer);
+ if (mSelectCursorBase.x < caretTop.x) {
+ showRect.left = Math.max(0, mSelectCursorBase.x - buffer);
showRect.right = caretTop.x + buffer;
} else {
showRect.left = Math.max(0, caretTop.x - buffer);
- showRect.right = mSelectCursorLeft.x + buffer;
+ showRect.right = mSelectCursorBase.x + buffer;
}
}
if (visibleRect.height() < mEditTextContentBounds.height()) {
// The whole edit won't fit in the height, so use the caret rect
- if (mSelectCursorLeft.y > caretTop.y) {
+ if (mSelectCursorBase.y > caretTop.y) {
showRect.top = Math.max(0, caretTop.y - buffer);
- showRect.bottom = mSelectCursorLeft.y + buffer;
+ showRect.bottom = mSelectCursorBase.y + buffer;
} else {
- showRect.top = Math.max(0, mSelectCursorLeft.y - buffer);
+ showRect.top = Math.max(0, mSelectCursorBase.y - buffer);
showRect.bottom = caretTop.y + buffer;
}
}
@@ -5801,28 +5845,19 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
ensureSelectionHandles();
int shiftedY = y - getTitleHeight() + getScrollY();
int shiftedX = x + getScrollX();
- if (mSelectHandleCenter != null && mSelectHandleCenter.getBounds()
- .contains(shiftedX, shiftedY)) {
+ if (mSelectHandleBaseBounds.contains(shiftedX, shiftedY)) {
mSelectionStarted = true;
- mSelectDraggingCursor = mSelectCursorLeft;
- mSelectDraggingOffset = mSelectHandleCenterOffset;
- mSelectDraggingTextQuad = mSelectCursorLeftTextQuad;
- mPrivateHandler.removeMessages(CLEAR_CARET_HANDLE);
- hidePasteButton();
- } else if (mSelectHandleLeft != null
- && mSelectHandleLeft.getBounds()
- .contains(shiftedX, shiftedY)) {
- mSelectionStarted = true;
- mSelectDraggingOffset = mSelectHandleLeftOffset;
- mSelectDraggingCursor = mSelectCursorLeft;
- mSelectDraggingTextQuad = mSelectCursorLeftTextQuad;
- } else if (mSelectHandleRight != null
- && mSelectHandleRight.getBounds()
+ mSelectDraggingCursor = mSelectCursorBase;
+ mSelectDraggingTextQuad = mSelectCursorBaseTextQuad;
+ if (mIsCaretSelection) {
+ mPrivateHandler.removeMessages(CLEAR_CARET_HANDLE);
+ hidePasteButton();
+ }
+ } else if (mSelectHandleExtentBounds
.contains(shiftedX, shiftedY)) {
mSelectionStarted = true;
- mSelectDraggingOffset = mSelectHandleRightOffset;
- mSelectDraggingCursor = mSelectCursorRight;
- mSelectDraggingTextQuad = mSelectCursorRightTextQuad;
+ mSelectDraggingCursor = mSelectCursorExtent;
+ mSelectDraggingTextQuad = mSelectCursorExtentTextQuad;
} else if (mIsCaretSelection) {
selectionDone();
}
@@ -5867,9 +5902,9 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
if (deltaX != 0 || deltaY != 0) {
int handleX = contentX +
- viewToContentDimension(mSelectDraggingOffset.x);
+ viewToContentDimension(mSelectOffset.x);
int handleY = contentY +
- viewToContentDimension(mSelectDraggingOffset.y);
+ viewToContentDimension(mSelectOffset.y);
mSelectDraggingCursor.set(handleX, handleY);
boolean inCursorText =
mSelectDraggingTextQuad.containsPoint(handleX, handleY);
@@ -6006,12 +6041,15 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
break;
}
case MotionEvent.ACTION_UP: {
- endScrollEdit();
- if (!mConfirmMove && mIsEditingText && mSelectionStarted &&
- mIsCaretSelection) {
- showPasteWindow();
- stopTouch();
- break;
+ if (mIsEditingText && mSelectionStarted) {
+ endScrollEdit();
+ mPrivateHandler.sendEmptyMessageDelayed(SCROLL_HANDLE_INTO_VIEW,
+ TEXT_SCROLL_FIRST_SCROLL_MS);
+ if (!mConfirmMove && mIsCaretSelection) {
+ showPasteWindow();
+ stopTouch();
+ break;
+ }
}
mLastTouchUpTime = eventTime;
if (mSentAutoScrollMessage) {
@@ -6118,6 +6156,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
}
+ private static int getSelectionCoordinate(int coordinate, int min, int max) {
+ return Math.max(Math.min(coordinate, max), min);
+ }
+
private void beginScrollEdit() {
if (mLastEditScroll == 0) {
mLastEditScroll = SystemClock.uptimeMillis() -
@@ -6126,10 +6168,37 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
}
+ private void scrollDraggedSelectionHandleIntoView() {
+ if (mSelectDraggingCursor == null) {
+ return;
+ }
+ int x = mSelectDraggingCursor.x;
+ int y = mSelectDraggingCursor.y;
+ if (!mEditTextContentBounds.contains(x,y)) {
+ int left = Math.min(0, x - mEditTextContentBounds.left - EDIT_RECT_BUFFER);
+ int right = Math.max(0, x - mEditTextContentBounds.right + EDIT_RECT_BUFFER);
+ int deltaX = left + right;
+ int above = Math.min(0, y - mEditTextContentBounds.top - EDIT_RECT_BUFFER);
+ int below = Math.max(0, y - mEditTextContentBounds.bottom + EDIT_RECT_BUFFER);
+ int deltaY = above + below;
+ if (deltaX != 0 || deltaY != 0) {
+ int scrollX = getTextScrollX() + deltaX;
+ int scrollY = getTextScrollY() + deltaY;
+ scrollX = clampBetween(scrollX, 0, getMaxTextScrollX());
+ scrollY = clampBetween(scrollY, 0, getMaxTextScrollY());
+ scrollEditText(scrollX, scrollY);
+ }
+ }
+ }
+
private void endScrollEdit() {
mLastEditScroll = 0;
}
+ private static int clampBetween(int value, int min, int max) {
+ return Math.max(min, Math.min(value, max));
+ }
+
private static int getTextScrollDelta(float speed, long deltaT) {
float distance = speed * deltaT;
int intDistance = (int)Math.floor(distance);
@@ -6145,10 +6214,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
*/
private void scrollEditWithCursor() {
if (mLastEditScroll != 0) {
- int x = viewToContentX(mLastTouchX + getScrollX() + mSelectDraggingOffset.x);
+ int x = viewToContentX(mLastTouchX + getScrollX() + mSelectOffset.x);
float scrollSpeedX = getTextScrollSpeed(x, mEditTextContentBounds.left,
mEditTextContentBounds.right);
- int y = viewToContentY(mLastTouchY + getScrollY() + mSelectDraggingOffset.y);
+ int y = viewToContentY(mLastTouchY + getScrollY() + mSelectOffset.y);
float scrollSpeedY = getTextScrollSpeed(y, mEditTextContentBounds.top,
mEditTextContentBounds.bottom);
if (scrollSpeedX == 0.0f && scrollSpeedY == 0.0f) {
@@ -6158,24 +6227,27 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
long timeSinceLastUpdate = currentTime - mLastEditScroll;
int deltaX = getTextScrollDelta(scrollSpeedX, timeSinceLastUpdate);
int deltaY = getTextScrollDelta(scrollSpeedY, timeSinceLastUpdate);
+ int scrollX = getTextScrollX() + deltaX;
+ scrollX = clampBetween(scrollX, 0, getMaxTextScrollX());
+ int scrollY = getTextScrollY() + deltaY;
+ scrollY = clampBetween(scrollY, 0, getMaxTextScrollY());
+
mLastEditScroll = currentTime;
- if (deltaX == 0 && deltaY == 0) {
+ if (scrollX == getTextScrollX() && scrollY == getTextScrollY()) {
// By probability no text scroll this time. Try again later.
mPrivateHandler.sendEmptyMessageDelayed(SCROLL_EDIT_TEXT,
TEXT_SCROLL_FIRST_SCROLL_MS);
} else {
- int scrollX = getTextScrollX() + deltaX;
- scrollX = Math.min(getMaxTextScrollX(), scrollX);
- scrollX = Math.max(0, scrollX);
- int scrollY = getTextScrollY() + deltaY;
- scrollY = Math.min(getMaxTextScrollY(), scrollY);
- scrollY = Math.max(0, scrollY);
- scrollEditText(scrollX, scrollY);
- int cursorX = mSelectDraggingCursor.x;
- int cursorY = mSelectDraggingCursor.y;
- mSelectDraggingCursor.set(x - deltaX, y - deltaY);
+ int selectionX = getSelectionCoordinate(x,
+ mEditTextContentBounds.left, mEditTextContentBounds.right);
+ int selectionY = getSelectionCoordinate(y,
+ mEditTextContentBounds.top, mEditTextContentBounds.bottom);
+ int oldX = mSelectDraggingCursor.x;
+ int oldY = mSelectDraggingCursor.y;
+ mSelectDraggingCursor.set(selectionX, selectionY);
updateWebkitSelection();
- mSelectDraggingCursor.set(cursorX, cursorY);
+ scrollEditText(scrollX, scrollY);
+ mSelectDraggingCursor.set(oldX, oldY);
}
}
}
@@ -6231,10 +6303,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
// scrolling. The rectangle is in document coordinates.
final int maxX = mScrollingLayerRect.right;
final int maxY = mScrollingLayerRect.bottom;
- final int resultX = Math.max(0,
- Math.min(mScrollingLayerRect.left + contentX, maxX));
- final int resultY = Math.max(0,
- Math.min(mScrollingLayerRect.top + contentY, maxY));
+ final int resultX = clampBetween(maxX, 0,
+ mScrollingLayerRect.left + contentX);
+ final int resultY = clampBetween(maxY, 0,
+ mScrollingLayerRect.top + contentY);
if (resultX != mScrollingLayerRect.left
|| resultY != mScrollingLayerRect.top
@@ -6335,10 +6407,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
int x = Math.round(newX);
int y = Math.round(newY);
if (mIsEditingText) {
- x = Math.max(mEditTextContentBounds.left,
- Math.min(mEditTextContentBounds.right, x));
- y = Math.max(mEditTextContentBounds.top,
- Math.min(mEditTextContentBounds.bottom, y));
+ x = clampBetween(x, mEditTextContentBounds.left,
+ mEditTextContentBounds.right);
+ y = clampBetween(y, mEditTextContentBounds.top,
+ mEditTextContentBounds.bottom);
}
mSelectDraggingCursor.set(x, y);
}
@@ -6401,9 +6473,12 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
private long mTrackballUpTime = 0;
private long mLastCursorTime = 0;
private Rect mLastCursorBounds;
- private SelectionHandleAlpha mHandleAlpha = new SelectionHandleAlpha();
- private ObjectAnimator mHandleAlphaAnimator =
- ObjectAnimator.ofInt(mHandleAlpha, "alpha", 0);
+ private SelectionHandleAlpha mBaseAlpha = new SelectionHandleAlpha();
+ private SelectionHandleAlpha mExtentAlpha = new SelectionHandleAlpha();
+ private ObjectAnimator mBaseHandleAlphaAnimator =
+ ObjectAnimator.ofInt(mBaseAlpha, "alpha", 0);
+ private ObjectAnimator mExtentHandleAlphaAnimator =
+ ObjectAnimator.ofInt(mExtentAlpha, "alpha", 0);
// Set by default; BrowserActivity clears to interpret trackball data
// directly for movement. Currently, the framework only passes
@@ -7437,7 +7512,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
mEditTextLayerId = initData.mNodeLayerId;
nativeMapLayerRect(mNativeClass, mEditTextLayerId,
mEditTextContentBounds);
- mEditTextContent.set(initData.mContentRect);
+ mEditTextContent.set(initData.mClientRect);
relocateAutoCompletePopup();
}
break;
@@ -7518,6 +7593,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
scrollEditWithCursor();
break;
+ case SCROLL_HANDLE_INTO_VIEW:
+ scrollDraggedSelectionHandleIntoView();
+ break;
+
default:
super.handleMessage(msg);
break;
@@ -7553,8 +7632,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
.contains(x, y);
} else {
isPressingHandle =
- mSelectHandleLeft.getBounds().contains(x, y)
- || mSelectHandleRight.getBounds().contains(x, y);
+ mSelectHandleBaseBounds.contains(x, y)
+ || mSelectHandleExtentBounds.contains(x, y);
}
return isPressingHandle;
}
@@ -7901,8 +7980,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
if (data.mSelectTextPtr != 0 &&
(data.mStart != data.mEnd ||
- (mFieldPointer == nodePointer && mFieldPointer != 0))) {
- mIsCaretSelection = (data.mStart == data.mEnd);
+ (mFieldPointer == nodePointer && mFieldPointer != 0) ||
+ (nodePointer == 0 && data.mStart == 0 && data.mEnd == 0))) {
+ mIsEditingText = (mFieldPointer == nodePointer) && nodePointer != 0;
+ mIsCaretSelection = (data.mStart == data.mEnd && nodePointer != 0);
if (mIsCaretSelection &&
(mInputConnection == null ||
mInputConnection.getEditable().length() == 0)) {
@@ -7911,11 +7992,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
} else {
if (!mSelectingText) {
setupWebkitSelect();
- } else if (!mSelectionStarted) {
- syncSelectionCursors();
} else {
- adjustSelectionCursors();
+ syncSelectionCursors();
}
+ animateHandles();
if (mIsCaretSelection) {
resetCaretTimer();
}
@@ -7931,8 +8011,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
float maxScrollX = getMaxTextScrollX();
float scrollPercentX = ((float)scrollX)/maxScrollX;
mEditTextContent.offsetTo(-scrollX, -scrollY);
- mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SCROLL_TEXT_INPUT, 0,
+ mWebViewCore.removeMessages(EventHub.SCROLL_TEXT_INPUT);
+ mWebViewCore.sendMessage(EventHub.SCROLL_TEXT_INPUT, 0,
scrollY, (Float)scrollPercentX);
+ animateHandles();
}
private void beginTextBatch() {
@@ -8518,6 +8600,54 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
WebViewCore.setShouldMonitorWebCoreThread();
}
+ @Override
+ public void dumpViewHierarchyWithProperties(BufferedWriter out, int level) {
+ int layer = getBaseLayer();
+ if (layer != 0) {
+ try {
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ ViewStateSerializer.dumpLayerHierarchy(layer, stream, level);
+ stream.close();
+ byte[] buf = stream.toByteArray();
+ out.write(new String(buf, "ascii"));
+ } catch (IOException e) {}
+ }
+ }
+
+ @Override
+ public View findHierarchyView(String className, int hashCode) {
+ if (mNativeClass == 0) return null;
+ Picture pic = new Picture();
+ if (!nativeDumpLayerContentToPicture(mNativeClass, className, hashCode, pic)) {
+ return null;
+ }
+ return new PictureWrapperView(getContext(), pic, mWebView);
+ }
+
+ private static class PictureWrapperView extends View {
+ Picture mPicture;
+ WebView mWebView;
+
+ public PictureWrapperView(Context context, Picture picture, WebView parent) {
+ super(context);
+ mPicture = picture;
+ mWebView = parent;
+ setWillNotDraw(false);
+ setRight(mPicture.getWidth());
+ setBottom(mPicture.getHeight());
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ canvas.drawPicture(mPicture);
+ }
+
+ @Override
+ public boolean post(Runnable action) {
+ return mWebView.post(action);
+ }
+ }
+
private native void nativeCreate(int ptr, String drawableDir, boolean isHighEndGfx);
private native void nativeDebugDump();
private static native void nativeDestroy(int ptr);
@@ -8538,6 +8668,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
int scrollingLayer);
private native int nativeGetBaseLayer(int nativeInstance);
private native void nativeCopyBaseContentToPicture(Picture pict);
+ private native boolean nativeDumpLayerContentToPicture(int nativeInstance,
+ String className, int layerId, Picture pict);
private native boolean nativeHasContent();
private native void nativeStopGL(int ptr);
private native void nativeDiscardAllTextures();
@@ -8581,4 +8713,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
private static native int nativeSetHwAccelerated(int instance, boolean hwAccelerated);
private static native void nativeFindMaxVisibleRect(int instance, int layerId,
Rect visibleContentRect);
+ private static native boolean nativeIsHandleLeft(int instance, int handleId);
+ private static native boolean nativeIsPointVisible(int instance,
+ int layerId, int contentX, int contentY);
}
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 6aff10a..64a5918 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -204,35 +204,6 @@ public class WebViewClient {
}
/**
- * Notify the host application that an SSL error occurred while loading a
- * resource, but the WebView chose to proceed anyway based on a
- * decision retained from a previous response to onReceivedSslError().
- * @hide
- */
- public void onProceededAfterSslError(WebView view, SslError error) {
- }
-
- /**
- * Notify the host application to handle a SSL client certificate
- * request (display the request to the user and ask whether to
- * proceed with a client certificate or not). The host application
- * has to call either handler.cancel() or handler.proceed() as the
- * connection is suspended and waiting for the response. The
- * default behavior is to cancel, returning no client certificate.
- *
- * @param view The WebView that is initiating the callback.
- * @param handler A ClientCertRequestHandler object that will
- * handle the user's response.
- * @param host_and_port The host and port of the requesting server.
- *
- * @hide
- */
- public void onReceivedClientCertRequest(WebView view,
- ClientCertRequestHandler handler, String host_and_port) {
- handler.cancel();
- }
-
- /**
* Notify the host application to handle an authentication request. The
* default behavior is to cancel the request.
*
diff --git a/core/java/android/webkit/WebViewClientClassicExt.java b/core/java/android/webkit/WebViewClientClassicExt.java
new file mode 100644
index 0000000..a873585
--- /dev/null
+++ b/core/java/android/webkit/WebViewClientClassicExt.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.net.http.SslError;
+
+/**
+ * Adds WebViewClassic specific extension methods to the WebViewClient callback class.
+ * These are not part of the public WebView API, so the class is hidden.
+ * @hide
+ */
+public class WebViewClientClassicExt extends WebViewClient {
+
+ /**
+ * Notify the host application that an SSL error occurred while loading a
+ * resource, but the WebView chose to proceed anyway based on a
+ * decision retained from a previous response to onReceivedSslError().
+ */
+ public void onProceededAfterSslError(WebView view, SslError error) {
+ }
+
+ /**
+ * Notify the host application to handle a SSL client certificate
+ * request (display the request to the user and ask whether to
+ * proceed with a client certificate or not). The host application
+ * has to call either handler.cancel() or handler.proceed() as the
+ * connection is suspended and waiting for the response. The
+ * default behavior is to cancel, returning no client certificate.
+ *
+ * @param view The WebView that is initiating the callback.
+ * @param handler A ClientCertRequestHandler object that will
+ * handle the user's response.
+ * @param host_and_port The host and port of the requesting server.
+ */
+ public void onReceivedClientCertRequest(WebView view,
+ ClientCertRequestHandler handler, String host_and_port) {
+ handler.cancel();
+ }
+}
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 728ddbf..905647d 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -132,6 +132,8 @@ public final class WebViewCore {
private int mRestoredX = 0;
private int mRestoredY = 0;
+ private MockGeolocation mMockGeolocation = new MockGeolocation(this);
+
private DeviceMotionAndOrientationManager mDeviceMotionAndOrientationManager =
new DeviceMotionAndOrientationManager(this);
private DeviceMotionService mDeviceMotionService;
@@ -560,13 +562,6 @@ public final class WebViewCore {
}
/**
- * Notify the webview that this is an installable web app.
- */
- protected void setInstallableWebApp() {
- mCallbackProxy.setInstallableWebApp();
- }
-
- /**
* Notify the webview that we want to display the video layer fullscreen.
*/
protected void enterFullscreenForVideoLayer(int layerId, String url) {
@@ -619,8 +614,6 @@ public final class WebViewCore {
*/
private native void nativeNotifyAnimationStarted(int nativeClass);
- private native boolean nativeFocusBoundsChanged(int nativeClass);
-
private native boolean nativeKey(int nativeClass, int keyCode,
int unichar, int repeatCount, boolean isShift, boolean isAlt,
boolean isSym, boolean isDown);
@@ -960,7 +953,7 @@ public final class WebViewCore {
public int mMaxLength;
public Rect mContentBounds;
public int mNodeLayerId;
- public Rect mContentRect;
+ public Rect mClientRect;
}
// mAction of TouchEventData can be MotionEvent.getAction() which uses the
@@ -1199,6 +1192,7 @@ public final class WebViewCore {
static final int SET_INITIAL_FOCUS = 224;
static final int SAVE_VIEW_STATE = 225;
+ static final int SET_USE_MOCK_GEOLOCATION = 226;
// Private handler for WebCore messages.
private Handler mHandler;
@@ -1306,13 +1300,8 @@ public final class WebViewCore {
} else {
xPercent = ((Float) msg.obj).floatValue();
}
- Rect contentBounds = new Rect();
nativeScrollFocusedTextInput(mNativeClass, xPercent,
- msg.arg2, contentBounds);
- Message.obtain(
- mWebViewClassic.mPrivateHandler,
- WebViewClassic.UPDATE_CONTENT_BOUNDS,
- contentBounds).sendToTarget();
+ msg.arg2);
break;
case LOAD_URL: {
@@ -1660,6 +1649,10 @@ public final class WebViewCore {
(Set<String>) msg.obj);
break;
+ case SET_USE_MOCK_GEOLOCATION:
+ setUseMockGeolocation();
+ break;
+
case SET_USE_MOCK_DEVICE_ORIENTATION:
setUseMockDeviceOrientation();
break;
@@ -1708,13 +1701,9 @@ public final class WebViewCore {
nativeInsertText(mNativeClass, (String) msg.obj);
break;
case SELECT_TEXT: {
- int[] args = (int[]) msg.obj;
- if (args == null) {
- nativeClearTextSelection(mNativeClass);
- } else {
- nativeSelectText(mNativeClass, args[0],
- args[1], args[2], args[3]);
- }
+ int handleId = (Integer) msg.obj;
+ nativeSelectText(mNativeClass, handleId,
+ msg.arg1, msg.arg2);
break;
}
case SELECT_WORD_AT: {
@@ -2192,7 +2181,6 @@ public final class WebViewCore {
// only non-null if it is for the first picture set after the first layout
ViewState mViewState;
boolean mFirstLayoutForNonStandardLoad;
- boolean mFocusSizeChanged;
}
DrawData mLastDrawData = null;
@@ -2247,7 +2235,6 @@ public final class WebViewCore {
private void webkitDraw(DrawData draw) {
if (mWebViewClassic != null) {
- draw.mFocusSizeChanged = nativeFocusBoundsChanged(mNativeClass);
draw.mViewSize = new Point(mCurrentViewWidth, mCurrentViewHeight);
if (mSettings.getUseWideViewPort()) {
draw.mMinPrefWidth = Math.max(
@@ -2330,7 +2317,6 @@ public final class WebViewCore {
Log.w(LOGTAG, "Cannot pauseUpdatePicture, core destroyed or not initialized!");
return;
}
- core.nativeSetIsPaused(core.mNativeClass, true);
core.mDrawIsPaused = true;
}
}
@@ -2348,7 +2334,6 @@ public final class WebViewCore {
Log.w(LOGTAG, "Cannot resumeUpdatePicture, core destroyed!");
return;
}
- core.nativeSetIsPaused(core.mNativeClass, false);
core.mDrawIsPaused = false;
// always redraw on resume to reenable gif animations
core.mDrawIsScheduled = false;
@@ -2363,13 +2348,13 @@ public final class WebViewCore {
//////////////////////////////////////////////////////////////////////////
private void restoreState(int index) {
- WebBackForwardList list = mCallbackProxy.getBackForwardList();
+ WebBackForwardListClassic list = mCallbackProxy.getBackForwardList();
int size = list.getSize();
for (int i = 0; i < size; i++) {
list.getItemAtIndex(i).inflate(mBrowserFrame.mNativeFrame);
}
mBrowserFrame.mLoadInitFromJava = true;
- list.restoreIndex(mBrowserFrame.mNativeFrame, index);
+ WebBackForwardListClassic.restoreIndex(mBrowserFrame.mNativeFrame, index);
mBrowserFrame.mLoadInitFromJava = false;
}
@@ -2787,14 +2772,11 @@ public final class WebViewCore {
}
// called by JNI
- private void updateTextfield(int ptr, boolean changeToPassword,
- String text, int textGeneration) {
+ private void updateTextfield(int ptr, String text, int textGeneration) {
if (mWebViewClassic != null) {
- Message msg = Message.obtain(mWebViewClassic.mPrivateHandler,
+ Message.obtain(mWebViewClassic.mPrivateHandler,
WebViewClassic.UPDATE_TEXTFIELD_TEXT_MSG_ID, ptr,
- textGeneration, text);
- msg.getData().putBoolean("password", changeToPassword);
- msg.sendToTarget();
+ textGeneration, text).sendToTarget();
}
}
@@ -2855,7 +2837,7 @@ public final class WebViewCore {
* Scroll the focused textfield to (xPercent, y) in document space
*/
private native void nativeScrollFocusedTextInput(int nativeClass,
- float xPercent, int y, Rect contentBounds);
+ float xPercent, int y);
// these must be in document space (i.e. not scaled/zoomed).
private native void nativeSetScrollOffset(int nativeClass,
@@ -3063,6 +3045,22 @@ public final class WebViewCore {
mDeviceMotionAndOrientationManager.setUseMock();
}
+ private void setUseMockGeolocation() {
+ mMockGeolocation.setUseMock();
+ }
+
+ public void setMockGeolocationPosition(double latitude, double longitude, double accuracy) {
+ mMockGeolocation.setPosition(latitude, longitude, accuracy);
+ }
+
+ public void setMockGeolocationError(int code, String message) {
+ mMockGeolocation.setError(code, message);
+ }
+
+ public void setMockGeolocationPermission(boolean allow) {
+ mMockGeolocation.setPermission(allow);
+ }
+
public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma) {
mDeviceMotionAndOrientationManager.setMockOrientation(canProvideAlpha, alpha,
@@ -3089,7 +3087,6 @@ public final class WebViewCore {
sShouldMonitorWebCoreThread = true;
}
- private native void nativeSetIsPaused(int nativeClass, boolean isPaused);
private native void nativePause(int nativeClass);
private native void nativeResume(int nativeClass);
private native void nativeFreeMemory(int nativeClass);
@@ -3135,7 +3132,7 @@ public final class WebViewCore {
private native String nativeGetText(int nativeClass,
int startX, int startY, int endX, int endY);
private native void nativeSelectText(int nativeClass,
- int startX, int startY, int endX, int endY);
+ int handleId, int x, int y);
private native void nativeClearTextSelection(int nativeClass);
private native boolean nativeSelectWordAt(int nativeClass, int x, int y);
private native void nativeSelectAll(int nativeClass);
diff --git a/core/java/android/webkit/WebViewDatabaseClassic.java b/core/java/android/webkit/WebViewDatabaseClassic.java
index 9b1d4cb..c804b90 100644
--- a/core/java/android/webkit/WebViewDatabaseClassic.java
+++ b/core/java/android/webkit/WebViewDatabaseClassic.java
@@ -100,6 +100,7 @@ final class WebViewDatabaseClassic extends WebViewDatabase {
private boolean mInitialized = false;
WebViewDatabaseClassic(final Context context) {
+ JniUtil.setContext(context);
new Thread() {
@Override
public void run() {
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 867ee54..ad28b17 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -37,6 +37,7 @@ import android.view.inputmethod.InputConnection;
import android.webkit.WebView.HitTestResult;
import android.webkit.WebView.PictureListener;
+import java.io.BufferedWriter;
import java.io.File;
import java.util.Map;
@@ -238,6 +239,10 @@ public interface WebViewProvider {
public void debugDump();
+ public void dumpViewHierarchyWithProperties(BufferedWriter out, int level);
+
+ public View findHierarchyView(String className, int hashCode);
+
//-------------------------------------------------------------------------
// Provider glue methods
//-------------------------------------------------------------------------
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 0a71c5a..421a324 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -225,26 +225,53 @@ public abstract class CompoundButton extends Button implements Checkable {
}
@Override
+ public int getCompoundPaddingLeft() {
+ int padding = super.getCompoundPaddingLeft();
+ if (!isLayoutRtl()) {
+ final Drawable buttonDrawable = mButtonDrawable;
+ if (buttonDrawable != null) {
+ padding += buttonDrawable.getIntrinsicWidth();
+ }
+ }
+ return padding;
+ }
+
+ @Override
+ public int getCompoundPaddingRight() {
+ int padding = super.getCompoundPaddingRight();
+ if (isLayoutRtl()) {
+ final Drawable buttonDrawable = mButtonDrawable;
+ if (buttonDrawable != null) {
+ padding += buttonDrawable.getIntrinsicWidth();
+ }
+ }
+ return padding;
+ }
+
+ @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
final Drawable buttonDrawable = mButtonDrawable;
if (buttonDrawable != null) {
final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
- final int height = buttonDrawable.getIntrinsicHeight();
-
- int y = 0;
+ final int drawableHeight = buttonDrawable.getIntrinsicHeight();
+ final int drawableWidth = buttonDrawable.getIntrinsicWidth();
+ int top = 0;
switch (verticalGravity) {
case Gravity.BOTTOM:
- y = getHeight() - height;
+ top = getHeight() - drawableHeight;
break;
case Gravity.CENTER_VERTICAL:
- y = (getHeight() - height) / 2;
+ top = (getHeight() - drawableHeight) / 2;
break;
}
+ int bottom = top + drawableHeight;
+ int left = isLayoutRtl() ? getWidth() - drawableWidth : 0;
+ int right = isLayoutRtl() ? getWidth() : drawableWidth;
- buttonDrawable.setBounds(0, y, buttonDrawable.getIntrinsicWidth(), y + height);
+ buttonDrawable.setBounds(left, top, right, bottom);
buttonDrawable.draw(canvas);
}
}
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index d019d8c..1893620 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -603,6 +603,12 @@ public class FrameLayout extends ViewGroup {
*/
public int gravity = -1;
+ @Override
+ protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
+ width = a.getLayoutDimension(widthAttr, MATCH_PARENT);
+ height = a.getLayoutDimension(heightAttr, MATCH_PARENT);
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index ada7dd1..f23e1aa 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -94,7 +94,7 @@ public class GridView extends AbsListView {
private View mReferenceView = null;
private View mReferenceViewInSelectedRow = null;
- private int mGravity = Gravity.LEFT;
+ private int mGravity = Gravity.START;
private final Rect mTempRect = new Rect();
@@ -300,9 +300,18 @@ public class GridView extends AbsListView {
final int columnWidth = mColumnWidth;
final int horizontalSpacing = mHorizontalSpacing;
+ final boolean isLayoutRtl = isLayoutRtl();
+
int last;
- int nextLeft = mListPadding.left +
- ((mStretchMode == STRETCH_SPACING_UNIFORM) ? horizontalSpacing : 0);
+ int nextLeft;
+
+ if (isLayoutRtl) {
+ nextLeft = getWidth() - mListPadding.right - columnWidth -
+ ((mStretchMode == STRETCH_SPACING_UNIFORM) ? horizontalSpacing : 0);
+ } else {
+ nextLeft = mListPadding.left +
+ ((mStretchMode == STRETCH_SPACING_UNIFORM) ? horizontalSpacing : 0);
+ }
if (!mStackFromBottom) {
last = Math.min(startPos + mNumColumns, mItemCount);
@@ -311,7 +320,8 @@ public class GridView extends AbsListView {
startPos = Math.max(0, startPos - mNumColumns + 1);
if (last - startPos < mNumColumns) {
- nextLeft += (mNumColumns - (last - startPos)) * (columnWidth + horizontalSpacing);
+ final int deltaLeft = (mNumColumns - (last - startPos)) * (columnWidth + horizontalSpacing);
+ nextLeft += (isLayoutRtl ? -1 : +1) * deltaLeft;
}
}
@@ -330,7 +340,7 @@ public class GridView extends AbsListView {
final int where = flow ? -1 : pos - startPos;
child = makeAndAddView(pos, y, flow, nextLeft, selected, where);
- nextLeft += columnWidth;
+ nextLeft += (isLayoutRtl ? -1 : +1) * columnWidth;
if (pos < last - 1) {
nextLeft += horizontalSpacing;
}
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index cf28da4..f259597 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -193,15 +193,6 @@ public class ImageView extends View {
}
}
- /**
- * @hide
- */
- @Override
- public int getResolvedLayoutDirection(Drawable dr) {
- return (dr == mDrawable) ?
- getResolvedLayoutDirection() : super.getResolvedLayoutDirection(dr);
- }
-
@Override
public boolean hasOverlappingRendering() {
return (getBackground() != null);
@@ -675,6 +666,7 @@ public class ImageView extends View {
d.setState(getDrawableState());
}
d.setLevel(mLevel);
+ d.setLayoutDirection(getLayoutDirection());
mDrawableWidth = d.getIntrinsicWidth();
mDrawableHeight = d.getIntrinsicHeight();
applyColorMod();
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index f3f18d5..1c6a406 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -478,6 +478,9 @@ public class ProgressBar extends View {
d.setCallback(this);
}
mIndeterminateDrawable = d;
+ if (mIndeterminateDrawable != null) {
+ mIndeterminateDrawable.setLayoutDirection(getLayoutDirection());
+ }
if (mIndeterminate) {
mCurrentDrawable = d;
postInvalidate();
@@ -517,6 +520,7 @@ public class ProgressBar extends View {
if (d != null) {
d.setCallback(this);
+ d.setLayoutDirection(getLayoutDirection());
// Make sure the ProgressBar is always tall enough
int drawableHeight = d.getMinimumHeight();
@@ -975,15 +979,6 @@ public class ProgressBar extends View {
}
}
- /**
- * @hide
- */
- @Override
- public int getResolvedLayoutDirection(Drawable who) {
- return (who == mProgressDrawable || who == mIndeterminateDrawable) ?
- getResolvedLayoutDirection() : super.getResolvedLayoutDirection(who);
- }
-
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
updateDrawableBounds(w, h);
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index f217c9c..338b8d6 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -297,33 +297,6 @@ public class RadioGroup extends LinearLayout {
public LayoutParams(MarginLayoutParams source) {
super(source);
}
-
- /**
- * <p>Fixes the child's width to
- * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and the child's
- * height to {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}
- * when not specified in the XML file.</p>
- *
- * @param a the styled attributes set
- * @param widthAttr the width attribute to fetch
- * @param heightAttr the height attribute to fetch
- */
- @Override
- protected void setBaseAttributes(TypedArray a,
- int widthAttr, int heightAttr) {
-
- if (a.hasValue(widthAttr)) {
- width = a.getLayoutDimension(widthAttr, "layout_width");
- } else {
- width = WRAP_CONTENT;
- }
-
- if (a.hasValue(heightAttr)) {
- height = a.getLayoutDimension(heightAttr, "layout_height");
- } else {
- height = WRAP_CONTENT;
- }
- }
}
/**
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index beb87cd..62063a1 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1656,12 +1656,19 @@ public class RemoteViews implements Parcelable, Filter {
}
/**
+ * Equivalent to calling {@link
+ * TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int, int)}.
+ *
* @param viewId The id of the view whose text should change
- * @param start The id of a drawable to place before the text (relative to the
+ * @param start The id of a drawable to place before the text (relative to the
* layout direction), or 0
* @param top The id of a drawable to place above the text, or 0
* @param end The id of a drawable to place after the text, or 0
+<<<<<<< HEAD
+ * @param bottom The id of a drawable to place below the text, or 0
+=======
* @param bottom The id of a drawable to place below the text, or 0
+>>>>>>> 0a43f67e
*/
public void setTextViewCompoundDrawablesRelative(int viewId, int start, int top, int end, int bottom) {
addAction(new TextViewDrawableAction(viewId, true, start, top, end, bottom));
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 36d1ee0..510a794 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -349,7 +349,7 @@ public class Spinner extends AbsSpinner implements OnClickListener {
public void setGravity(int gravity) {
if (mGravity != gravity) {
if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
- gravity |= Gravity.LEFT;
+ gravity |= Gravity.START;
}
mGravity = gravity;
requestLayout();
@@ -453,7 +453,7 @@ public class Spinner extends AbsSpinner implements OnClickListener {
/**
* Creates and positions all views for this Spinner.
*
- * @param delta Change in the selected position. +1 moves selection is moving to the right,
+ * @param delta Change in the selected position. +1 means selection is moving to the right,
* so views are scrolling to the left. -1 means selection is moving to the left.
*/
@Override
@@ -485,7 +485,9 @@ public class Spinner extends AbsSpinner implements OnClickListener {
View sel = makeAndAddView(mSelectedPosition);
int width = sel.getMeasuredWidth();
int selectedOffset = childrenLeft;
- switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+ final int layoutDirection = getResolvedLayoutDirection();
+ final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
+ switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.CENTER_HORIZONTAL:
selectedOffset = childrenLeft + (childrenWidth / 2) - (width / 2);
break;
@@ -932,19 +934,18 @@ public class Spinner extends AbsSpinner implements OnClickListener {
@Override
public void show() {
final Drawable background = getBackground();
- int bgOffset = 0;
+ int hOffset = 0;
if (background != null) {
background.getPadding(mTempRect);
- bgOffset = -mTempRect.left;
+ hOffset = isLayoutRtl() ? mTempRect.right : -mTempRect.left;
} else {
mTempRect.left = mTempRect.right = 0;
}
final int spinnerPaddingLeft = Spinner.this.getPaddingLeft();
+ final int spinnerPaddingRight = Spinner.this.getPaddingRight();
+ final int spinnerWidth = Spinner.this.getWidth();
if (mDropDownWidth == WRAP_CONTENT) {
- final int spinnerWidth = Spinner.this.getWidth();
- final int spinnerPaddingRight = Spinner.this.getPaddingRight();
-
int contentWidth = measureContentWidth(
(SpinnerAdapter) mAdapter, getBackground());
final int contentWidthLimit = mContext.getResources()
@@ -952,17 +953,20 @@ public class Spinner extends AbsSpinner implements OnClickListener {
if (contentWidth > contentWidthLimit) {
contentWidth = contentWidthLimit;
}
-
setContentWidth(Math.max(
contentWidth, spinnerWidth - spinnerPaddingLeft - spinnerPaddingRight));
} else if (mDropDownWidth == MATCH_PARENT) {
- final int spinnerWidth = Spinner.this.getWidth();
- final int spinnerPaddingRight = Spinner.this.getPaddingRight();
setContentWidth(spinnerWidth - spinnerPaddingLeft - spinnerPaddingRight);
} else {
setContentWidth(mDropDownWidth);
}
- setHorizontalOffset(bgOffset + spinnerPaddingLeft);
+
+ if (isLayoutRtl()) {
+ hOffset += spinnerWidth - spinnerPaddingRight - getWidth();
+ } else {
+ hOffset += spinnerPaddingLeft;
+ }
+ setHorizontalOffset(hOffset);
setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
super.show();
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 471f259..8f5dc2c 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -469,12 +469,6 @@ public class Switch extends CompoundButton {
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
-
if (mOnLayout == null) {
mOnLayout = makeLayout(mTextOn);
}
@@ -490,34 +484,6 @@ public class Switch extends CompoundButton {
mThumbWidth = maxTextWidth + mThumbTextPadding * 2;
- switch (widthMode) {
- case MeasureSpec.AT_MOST:
- widthSize = Math.min(widthSize, switchWidth);
- break;
-
- case MeasureSpec.UNSPECIFIED:
- widthSize = switchWidth;
- break;
-
- case MeasureSpec.EXACTLY:
- // Just use what we were given
- break;
- }
-
- switch (heightMode) {
- case MeasureSpec.AT_MOST:
- heightSize = Math.min(heightSize, switchHeight);
- break;
-
- case MeasureSpec.UNSPECIFIED:
- heightSize = switchHeight;
- break;
-
- case MeasureSpec.EXACTLY:
- // Just use what we were given
- break;
- }
-
mSwitchWidth = switchWidth;
mSwitchHeight = switchHeight;
@@ -651,7 +617,7 @@ public class Switch extends CompoundButton {
mVelocityTracker.computeCurrentVelocity(1000);
float xvel = mVelocityTracker.getXVelocity();
if (Math.abs(xvel) > mMinFlingVelocity) {
- newState = xvel > 0;
+ newState = isLayoutRtl() ? (xvel < 0) : (xvel > 0);
} else {
newState = getTargetCheckedState();
}
@@ -669,13 +635,25 @@ public class Switch extends CompoundButton {
}
private boolean getTargetCheckedState() {
- return mThumbPosition >= getThumbScrollRange() / 2;
+ if (isLayoutRtl()) {
+ return mThumbPosition <= getThumbScrollRange() / 2;
+ } else {
+ return mThumbPosition >= getThumbScrollRange() / 2;
+ }
+ }
+
+ private void setThumbPosition(boolean checked) {
+ if (isLayoutRtl()) {
+ mThumbPosition = checked ? 0 : getThumbScrollRange();
+ } else {
+ mThumbPosition = checked ? getThumbScrollRange() : 0;
+ }
}
@Override
public void setChecked(boolean checked) {
super.setChecked(checked);
- mThumbPosition = checked ? getThumbScrollRange() : 0;
+ setThumbPosition(checked);
invalidate();
}
@@ -683,10 +661,19 @@ public class Switch extends CompoundButton {
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- mThumbPosition = isChecked() ? getThumbScrollRange() : 0;
+ setThumbPosition(isChecked());
+
+ int switchRight;
+ int switchLeft;
+
+ if (isLayoutRtl()) {
+ switchLeft = getPaddingLeft();
+ switchRight = switchLeft + mSwitchWidth;
+ } else {
+ switchRight = getWidth() - getPaddingRight();
+ switchLeft = switchRight - mSwitchWidth;
+ }
- int switchRight = getWidth() - getPaddingRight();
- int switchLeft = switchRight - mSwitchWidth;
int switchTop = 0;
int switchBottom = 0;
switch (getGravity() & Gravity.VERTICAL_GRAVITY_MASK) {
@@ -761,7 +748,22 @@ public class Switch extends CompoundButton {
}
@Override
+ public int getCompoundPaddingLeft() {
+ if (!isLayoutRtl()) {
+ return super.getCompoundPaddingLeft();
+ }
+ int padding = super.getCompoundPaddingLeft() + mSwitchWidth;
+ if (!TextUtils.isEmpty(getText())) {
+ padding += mSwitchPadding;
+ }
+ return padding;
+ }
+
+ @Override
public int getCompoundPaddingRight() {
+ if (isLayoutRtl()) {
+ return super.getCompoundPaddingRight();
+ }
int padding = super.getCompoundPaddingRight() + mSwitchWidth;
if (!TextUtils.isEmpty(getText())) {
padding += mSwitchPadding;
diff --git a/core/java/android/widget/TableLayout.java b/core/java/android/widget/TableLayout.java
index 6331b6d..513f180 100644
--- a/core/java/android/widget/TableLayout.java
+++ b/core/java/android/widget/TableLayout.java
@@ -741,11 +741,7 @@ public class TableLayout extends LinearLayout {
@Override
protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
this.width = MATCH_PARENT;
- if (a.hasValue(heightAttr)) {
- this.height = a.getLayoutDimension(heightAttr, "layout_height");
- } else {
- this.height = WRAP_CONTENT;
- }
+ this.height = a.getLayoutDimension(heightAttr, WRAP_CONTENT);
}
}
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
index 01c4c2c..fb548df 100644
--- a/core/java/android/widget/TableRow.java
+++ b/core/java/android/widget/TableRow.java
@@ -502,19 +502,8 @@ public class TableRow extends LinearLayout {
@Override
protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
- // We don't want to force users to specify a layout_width
- if (a.hasValue(widthAttr)) {
- width = a.getLayoutDimension(widthAttr, "layout_width");
- } else {
- width = MATCH_PARENT;
- }
-
- // We don't want to force users to specify a layout_height
- if (a.hasValue(heightAttr)) {
- height = a.getLayoutDimension(heightAttr, "layout_height");
- } else {
- height = WRAP_CONTENT;
- }
+ width = a.getLayoutDimension(widthAttr, MATCH_PARENT);
+ height = a.getLayoutDimension(heightAttr, WRAP_CONTENT);
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 01617da..25f0131 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1542,7 +1542,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
/**
* Returns the start padding of the view, plus space for the start
* Drawable if any.
- * @hide
*/
public int getCompoundPaddingStart() {
resolveDrawables();
@@ -1558,7 +1557,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
/**
* Returns the end padding of the view, plus space for the end
* Drawable if any.
- * @hide
*/
public int getCompoundPaddingEnd() {
resolveDrawables();
@@ -1656,7 +1654,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
/**
* Returns the total start padding of the view, including the start
* Drawable if any.
- * @hide
*/
public int getTotalPaddingStart() {
return getCompoundPaddingStart();
@@ -1665,7 +1662,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
/**
* Returns the total end padding of the view, including the end
* Drawable if any.
- * @hide
*/
public int getTotalPaddingEnd() {
return getCompoundPaddingEnd();
@@ -1868,7 +1864,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @attr ref android.R.styleable#TextView_drawableTop
* @attr ref android.R.styleable#TextView_drawableEnd
* @attr ref android.R.styleable#TextView_drawableBottom
- * @hide
*/
public void setCompoundDrawablesRelative(Drawable start, Drawable top,
Drawable end, Drawable bottom) {
@@ -1990,7 +1985,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @attr ref android.R.styleable#TextView_drawableTop
* @attr ref android.R.styleable#TextView_drawableEnd
* @attr ref android.R.styleable#TextView_drawableBottom
- * @hide
*/
@android.view.RemotableViewMethod
public void setCompoundDrawablesRelativeWithIntrinsicBounds(int start, int top, int end,
@@ -2014,7 +2008,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @attr ref android.R.styleable#TextView_drawableTop
* @attr ref android.R.styleable#TextView_drawableEnd
* @attr ref android.R.styleable#TextView_drawableBottom
- * @hide
*/
public void setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top,
Drawable end, Drawable bottom) {
@@ -2061,7 +2054,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @attr ref android.R.styleable#TextView_drawableTop
* @attr ref android.R.styleable#TextView_drawableEnd
* @attr ref android.R.styleable#TextView_drawableBottom
- * @hide
*/
public Drawable[] getCompoundDrawablesRelative() {
final Drawables dr = mDrawables;
@@ -4586,23 +4578,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
- /**
- * @hide
- */
- @Override
- public int getResolvedLayoutDirection(Drawable who) {
- if (who == null) return View.LAYOUT_DIRECTION_LTR;
- if (mDrawables != null) {
- final Drawables drawables = mDrawables;
- if (who == drawables.mDrawableLeft || who == drawables.mDrawableRight ||
- who == drawables.mDrawableTop || who == drawables.mDrawableBottom ||
- who == drawables.mDrawableStart || who == drawables.mDrawableEnd) {
- return getResolvedLayoutDirection();
- }
- }
- return super.getResolvedLayoutDirection(who);
- }
-
@Override
public boolean hasOverlappingRendering() {
return (getBackground() != null || mText instanceof Spannable || hasSelection());
@@ -5634,7 +5609,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
physicalWidth, false);
}
- /** @hide */
@Override
public void onResolvedLayoutDirectionReset() {
if (mLayoutAlignment != null) {
@@ -8180,7 +8154,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return mEditor.mInBatchEditControllers;
}
- /** @hide */
@Override
public void onResolvedTextDirectionChanged() {
if (hasPasswordTransformationMethod()) {
@@ -8216,13 +8189,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
- /**
- * Subclasses will need to override this method to implement their own way of resolving
- * drawables depending on the layout direction.
- *
- * A call to the super method will be required from the subclasses implementation.
- */
- protected void resolveDrawables() {
+ @Override
+ public void onResolveDrawables(int layoutDirection) {
// No need to resolve twice
if (mResolvedDrawables) {
return;
@@ -8238,7 +8206,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
Drawables dr = mDrawables;
- switch(getResolvedLayoutDirection()) {
+ switch(layoutDirection) {
case LAYOUT_DIRECTION_RTL:
if (dr.mDrawableStart != null) {
dr.mDrawableRight = dr.mDrawableStart;
@@ -8270,9 +8238,25 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
break;
}
+ updateDrawablesLayoutDirection(dr, layoutDirection);
mResolvedDrawables = true;
}
+ private void updateDrawablesLayoutDirection(Drawables dr, int layoutDirection) {
+ if (dr.mDrawableLeft != null) {
+ dr.mDrawableLeft.setLayoutDirection(layoutDirection);
+ }
+ if (dr.mDrawableRight != null) {
+ dr.mDrawableRight.setLayoutDirection(layoutDirection);
+ }
+ if (dr.mDrawableTop != null) {
+ dr.mDrawableTop.setLayoutDirection(layoutDirection);
+ }
+ if (dr.mDrawableBottom != null) {
+ dr.mDrawableBottom.setLayoutDirection(layoutDirection);
+ }
+ }
+
protected void resetResolvedDrawables() {
mResolvedDrawables = false;
}
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index fafc113..6fc0773 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -24,6 +24,7 @@ import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.util.LocaleUtil;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -33,6 +34,8 @@ import android.view.WindowManagerImpl;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
+import java.util.Locale;
+
/**
* A toast is a view containing a quick little message for the user. The toast class
* helps you create and show those.
@@ -371,7 +374,11 @@ public class Toast {
handleHide();
mView = mNextView;
mWM = WindowManagerImpl.getDefault();
- final int gravity = mGravity;
+ // We can resolve the Gravity here by using the Locale for getting
+ // the layout direction
+ final int layoutDirection = LocaleUtil.getLayoutDirectionFromLocale(
+ Locale.getDefault());
+ final int gravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
mParams.gravity = gravity;
if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
mParams.horizontalWeight = 1.0f;
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 6a0cd36..1a76461f 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -58,14 +58,14 @@ interface IBatteryStats {
void noteBluetoothOff();
void noteFullWifiLockAcquired(int uid);
void noteFullWifiLockReleased(int uid);
- void noteScanWifiLockAcquired(int uid);
- void noteScanWifiLockReleased(int uid);
+ void noteWifiScanStarted(int uid);
+ void noteWifiScanStopped(int uid);
void noteWifiMulticastEnabled(int uid);
void noteWifiMulticastDisabled(int uid);
void noteFullWifiLockAcquiredFromSource(in WorkSource ws);
void noteFullWifiLockReleasedFromSource(in WorkSource ws);
- void noteScanWifiLockAcquiredFromSource(in WorkSource ws);
- void noteScanWifiLockReleasedFromSource(in WorkSource ws);
+ void noteWifiScanStartedFromSource(in WorkSource ws);
+ void noteWifiScanStoppedFromSource(in WorkSource ws);
void noteWifiMulticastEnabledFromSource(in WorkSource ws);
void noteWifiMulticastDisabledFromSource(in WorkSource ws);
void noteNetworkInterfaceType(String iface, int type);
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl b/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl
index 216d985..78b4466 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl
@@ -24,6 +24,7 @@ import android.widget.RemoteViews;
oneway interface IAppWidgetHost {
void updateAppWidget(int appWidgetId, in RemoteViews views);
void providerChanged(int appWidgetId, in AppWidgetProviderInfo info);
+ void providersChanged();
void viewDataChanged(int appWidgetId, int viewId);
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 5157385..42bc14d 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -159,8 +159,8 @@ public final class BatteryStatsImpl extends BatteryStats {
= new SparseArray<ArrayList<StopwatchTimer>>();
final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<StopwatchTimer>();
final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<StopwatchTimer>();
- final ArrayList<StopwatchTimer> mScanWifiLockTimers = new ArrayList<StopwatchTimer>();
final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<StopwatchTimer>();
+ final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<StopwatchTimer>();
// Last partial timers we use for distributing CPU usage.
final ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<StopwatchTimer>();
@@ -320,6 +320,18 @@ public final class BatteryStatsImpl extends BatteryStats {
Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 5: totalTime
};
+ private static final int[] WAKEUP_SOURCES_FORMAT = new int[] {
+ Process.PROC_TAB_TERM|Process.PROC_OUT_STRING, // 0: name
+ Process.PROC_TAB_TERM|Process.PROC_COMBINE|
+ Process.PROC_OUT_LONG, // 1: count
+ Process.PROC_TAB_TERM|Process.PROC_COMBINE,
+ Process.PROC_TAB_TERM|Process.PROC_COMBINE,
+ Process.PROC_TAB_TERM|Process.PROC_COMBINE,
+ Process.PROC_TAB_TERM|Process.PROC_COMBINE,
+ Process.PROC_TAB_TERM|Process.PROC_COMBINE
+ |Process.PROC_OUT_LONG, // 6: totalTime
+ };
+
private final String[] mProcWakelocksName = new String[3];
private final long[] mProcWakelocksData = new long[3];
@@ -1028,34 +1040,44 @@ public final class BatteryStatsImpl extends BatteryStats {
private final Map<String, KernelWakelockStats> readKernelWakelockStats() {
+ FileInputStream is;
byte[] buffer = new byte[8192];
int len;
+ boolean wakeup_sources = false;
try {
- FileInputStream is = new FileInputStream("/proc/wakelocks");
+ try {
+ is = new FileInputStream("/proc/wakelocks");
+ } catch (java.io.FileNotFoundException e) {
+ try {
+ is = new FileInputStream("/d/wakeup_sources");
+ wakeup_sources = true;
+ } catch (java.io.FileNotFoundException e2) {
+ return null;
+ }
+ }
+
len = is.read(buffer);
is.close();
+ } catch (java.io.IOException e) {
+ return null;
+ }
- if (len > 0) {
- int i;
- for (i=0; i<len; i++) {
- if (buffer[i] == '\0') {
- len = i;
- break;
- }
+ if (len > 0) {
+ int i;
+ for (i=0; i<len; i++) {
+ if (buffer[i] == '\0') {
+ len = i;
+ break;
}
}
- } catch (java.io.FileNotFoundException e) {
- return null;
- } catch (java.io.IOException e) {
- return null;
}
- return parseProcWakelocks(buffer, len);
+ return parseProcWakelocks(buffer, len, wakeup_sources);
}
private final Map<String, KernelWakelockStats> parseProcWakelocks(
- byte[] wlBuffer, int len) {
+ byte[] wlBuffer, int len, boolean wakeup_sources) {
String name;
int count;
long totalTime;
@@ -1092,12 +1114,20 @@ public final class BatteryStatsImpl extends BatteryStats {
if ((wlBuffer[j] & 0x80) != 0) wlBuffer[j] = (byte) '?';
}
boolean parsed = Process.parseProcLine(wlBuffer, startIndex, endIndex,
- PROC_WAKELOCKS_FORMAT, nameStringArray, wlData, null);
+ wakeup_sources ? WAKEUP_SOURCES_FORMAT :
+ PROC_WAKELOCKS_FORMAT,
+ nameStringArray, wlData, null);
name = nameStringArray[0];
count = (int) wlData[1];
- // convert nanoseconds to microseconds with rounding.
- totalTime = (wlData[2] + 500) / 1000;
+
+ if (wakeup_sources) {
+ // convert milliseconds to microseconds
+ totalTime = wlData[2] * 1000;
+ } else {
+ // convert nanoseconds to microseconds with rounding.
+ totalTime = (wlData[2] + 500) / 1000;
+ }
if (parsed && name.length() > 0) {
if (!m.containsKey(name)) {
@@ -2174,28 +2204,28 @@ public final class BatteryStatsImpl extends BatteryStats {
getUidStatsLocked(uid).noteFullWifiLockReleasedLocked();
}
- int mWifiScanLockNesting = 0;
+ int mWifiScanNesting = 0;
- public void noteScanWifiLockAcquiredLocked(int uid) {
- if (mWifiScanLockNesting == 0) {
- mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_LOCK_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan lock on to: "
+ public void noteWifiScanStartedLocked(int uid) {
+ if (mWifiScanNesting == 0) {
+ mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
+ Integer.toHexString(mHistoryCur.states));
addHistoryRecordLocked(SystemClock.elapsedRealtime());
}
- mWifiScanLockNesting++;
- getUidStatsLocked(uid).noteScanWifiLockAcquiredLocked();
+ mWifiScanNesting++;
+ getUidStatsLocked(uid).noteWifiScanStartedLocked();
}
- public void noteScanWifiLockReleasedLocked(int uid) {
- mWifiScanLockNesting--;
- if (mWifiScanLockNesting == 0) {
- mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_LOCK_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan lock off to: "
+ public void noteWifiScanStoppedLocked(int uid) {
+ mWifiScanNesting--;
+ if (mWifiScanNesting == 0) {
+ mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
+ Integer.toHexString(mHistoryCur.states));
addHistoryRecordLocked(SystemClock.elapsedRealtime());
}
- getUidStatsLocked(uid).noteScanWifiLockReleasedLocked();
+ getUidStatsLocked(uid).noteWifiScanStoppedLocked();
}
int mWifiMulticastNesting = 0;
@@ -2236,17 +2266,17 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
- public void noteScanWifiLockAcquiredFromSourceLocked(WorkSource ws) {
+ public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
int N = ws.size();
for (int i=0; i<N; i++) {
- noteScanWifiLockAcquiredLocked(ws.get(i));
+ noteWifiScanStartedLocked(ws.get(i));
}
}
- public void noteScanWifiLockReleasedFromSourceLocked(WorkSource ws) {
+ public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
int N = ws.size();
for (int i=0; i<N; i++) {
- noteScanWifiLockReleasedLocked(ws.get(i));
+ noteWifiScanStoppedLocked(ws.get(i));
}
}
@@ -2360,8 +2390,8 @@ public final class BatteryStatsImpl extends BatteryStats {
boolean mFullWifiLockOut;
StopwatchTimer mFullWifiLockTimer;
- boolean mScanWifiLockOut;
- StopwatchTimer mScanWifiLockTimer;
+ boolean mWifiScanStarted;
+ StopwatchTimer mWifiScanTimer;
boolean mWifiMulticastEnabled;
StopwatchTimer mWifiMulticastTimer;
@@ -2405,8 +2435,8 @@ public final class BatteryStatsImpl extends BatteryStats {
mWifiRunningTimers, mUnpluggables);
mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
mFullWifiLockTimers, mUnpluggables);
- mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
- mScanWifiLockTimers, mUnpluggables);
+ mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
+ mWifiScanTimers, mUnpluggables);
mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
mWifiMulticastTimers, mUnpluggables);
mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
@@ -2518,22 +2548,22 @@ public final class BatteryStatsImpl extends BatteryStats {
}
@Override
- public void noteScanWifiLockAcquiredLocked() {
- if (!mScanWifiLockOut) {
- mScanWifiLockOut = true;
- if (mScanWifiLockTimer == null) {
- mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
- mScanWifiLockTimers, mUnpluggables);
+ public void noteWifiScanStartedLocked() {
+ if (!mWifiScanStarted) {
+ mWifiScanStarted = true;
+ if (mWifiScanTimer == null) {
+ mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
+ mWifiScanTimers, mUnpluggables);
}
- mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
+ mWifiScanTimer.startRunningLocked(BatteryStatsImpl.this);
}
}
@Override
- public void noteScanWifiLockReleasedLocked() {
- if (mScanWifiLockOut) {
- mScanWifiLockOut = false;
- mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this);
+ public void noteWifiScanStoppedLocked() {
+ if (mWifiScanStarted) {
+ mWifiScanStarted = false;
+ mWifiScanTimer.stopRunningLocked(BatteryStatsImpl.this);
}
}
@@ -2614,11 +2644,11 @@ public final class BatteryStatsImpl extends BatteryStats {
}
@Override
- public long getScanWifiLockTime(long batteryRealtime, int which) {
- if (mScanWifiLockTimer == null) {
+ public long getWifiScanTime(long batteryRealtime, int which) {
+ if (mWifiScanTimer == null) {
return 0;
}
- return mScanWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
+ return mWifiScanTimer.getTotalTimeLocked(batteryRealtime, which);
}
@Override
@@ -2698,9 +2728,9 @@ public final class BatteryStatsImpl extends BatteryStats {
active |= !mFullWifiLockTimer.reset(BatteryStatsImpl.this, false);
active |= mFullWifiLockOut;
}
- if (mScanWifiLockTimer != null) {
- active |= !mScanWifiLockTimer.reset(BatteryStatsImpl.this, false);
- active |= mScanWifiLockOut;
+ if (mWifiScanTimer != null) {
+ active |= !mWifiScanTimer.reset(BatteryStatsImpl.this, false);
+ active |= mWifiScanStarted;
}
if (mWifiMulticastTimer != null) {
active |= !mWifiMulticastTimer.reset(BatteryStatsImpl.this, false);
@@ -2791,8 +2821,8 @@ public final class BatteryStatsImpl extends BatteryStats {
if (mFullWifiLockTimer != null) {
mFullWifiLockTimer.detach();
}
- if (mScanWifiLockTimer != null) {
- mScanWifiLockTimer.detach();
+ if (mWifiScanTimer != null) {
+ mWifiScanTimer.detach();
}
if (mWifiMulticastTimer != null) {
mWifiMulticastTimer.detach();
@@ -2860,9 +2890,9 @@ public final class BatteryStatsImpl extends BatteryStats {
} else {
out.writeInt(0);
}
- if (mScanWifiLockTimer != null) {
+ if (mWifiScanTimer != null) {
out.writeInt(1);
- mScanWifiLockTimer.writeToParcel(out, batteryRealtime);
+ mWifiScanTimer.writeToParcel(out, batteryRealtime);
} else {
out.writeInt(0);
}
@@ -2954,12 +2984,12 @@ public final class BatteryStatsImpl extends BatteryStats {
} else {
mFullWifiLockTimer = null;
}
- mScanWifiLockOut = false;
+ mWifiScanStarted = false;
if (in.readInt() != 0) {
- mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
- mScanWifiLockTimers, mUnpluggables, in);
+ mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
+ mWifiScanTimers, mUnpluggables, in);
} else {
- mScanWifiLockTimer = null;
+ mWifiScanTimer = null;
}
mWifiMulticastEnabled = false;
if (in.readInt() != 0) {
@@ -5118,9 +5148,9 @@ public final class BatteryStatsImpl extends BatteryStats {
if (in.readInt() != 0) {
u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
}
- u.mScanWifiLockOut = false;
+ u.mWifiScanStarted = false;
if (in.readInt() != 0) {
- u.mScanWifiLockTimer.readSummaryFromParcelLocked(in);
+ u.mWifiScanTimer.readSummaryFromParcelLocked(in);
}
u.mWifiMulticastEnabled = false;
if (in.readInt() != 0) {
@@ -5310,9 +5340,9 @@ public final class BatteryStatsImpl extends BatteryStats {
} else {
out.writeInt(0);
}
- if (u.mScanWifiLockTimer != null) {
+ if (u.mWifiScanTimer != null) {
out.writeInt(1);
- u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+ u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL);
} else {
out.writeInt(0);
}
@@ -5537,7 +5567,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mWindowTimers.clear();
mWifiRunningTimers.clear();
mFullWifiLockTimers.clear();
- mScanWifiLockTimers.clear();
+ mWifiScanTimers.clear();
mWifiMulticastTimers.clear();
sNumSpeedSteps = in.readInt();
diff --git a/core/java/com/android/internal/util/AsyncChannel.java b/core/java/com/android/internal/util/AsyncChannel.java
index d1c2d2e..5093b4d 100644
--- a/core/java/com/android/internal/util/AsyncChannel.java
+++ b/core/java/com/android/internal/util/AsyncChannel.java
@@ -444,6 +444,16 @@ public class AsyncChannel {
if ((mConnection != null) && (mSrcContext != null)) {
mSrcContext.unbindService(mConnection);
}
+ try {
+ // Send the DISCONNECTED, although it may not be received
+ // but its the best we can do.
+ Message msg = Message.obtain();
+ msg.what = CMD_CHANNEL_DISCONNECTED;
+ msg.replyTo = mSrcMessenger;
+ mDstMessenger.send(msg);
+ } catch(Exception e) {
+ }
+ // Tell source we're disconnected.
if (mSrcHandler != null) {
replyDisconnected(STATUS_SUCCESSFUL);
}
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index 1391ac3..0ea7b83 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -80,9 +80,9 @@ import java.util.Vector;
* and invoke <code>halting</code>. Any message subsequently received by the state
* machine will cause <code>haltedProcessMessage</code> to be invoked.</p>
*
- * <p>If it is desirable to completely stop the state machine call <code>quit</code>. This
- * will exit the current state and its parent and then exit from the controlling thread
- * and no further messages will be processed.</p>
+ * <p>If it is desirable to completely stop the state machine call <code>quit</code> or
+ * <code>abort</code>. These will call <code>exit</code> of the current state and its parents, call
+ * <code>onQuiting</code> and then exit Thread/Loopers.</p>
*
* <p>In addition to <code>processMessage</code> each <code>State</code> has
* an <code>enter</code> method and <code>exit</exit> method which may be overridden.</p>
@@ -362,7 +362,7 @@ class Hsm1 extends StateMachine {
}
&#64;Override
- void halting() {
+ void onHalting() {
Log.d(TAG, "halting");
synchronized (this) {
this.notifyAll();
@@ -423,10 +423,10 @@ public class StateMachine {
private String mName;
/** Message.what value when quitting */
- public static final int SM_QUIT_CMD = -1;
+ private static final int SM_QUIT_CMD = -1;
/** Message.what value when initializing */
- public static final int SM_INIT_CMD = -2;
+ private static final int SM_INIT_CMD = -2;
/**
* Convenience constant that maybe returned by processMessage
@@ -443,11 +443,10 @@ public class StateMachine {
public static final boolean NOT_HANDLED = false;
/**
+ * StateMachine logging record.
* {@hide}
- *
- * The information maintained for a processed message.
*/
- public static class ProcessedMessageInfo {
+ public static class LogRec {
private long mTime;
private int mWhat;
private String mInfo;
@@ -456,12 +455,13 @@ public class StateMachine {
/**
* Constructor
- * @param message
+ *
+ * @param msg
* @param state that handled the message
* @param orgState is the first state the received the message but
* did not processes the message.
*/
- ProcessedMessageInfo(Message msg, String info, State state, State orgState) {
+ LogRec(Message msg, String info, State state, State orgState) {
update(msg, info, state, orgState);
}
@@ -473,7 +473,7 @@ public class StateMachine {
*/
public void update(Message msg, String info, State state, State orgState) {
mTime = System.currentTimeMillis();
- mWhat = msg.what;
+ mWhat = (msg != null) ? msg.what : 0;
mInfo = info;
mState = state;
mOrgState = orgState;
@@ -517,8 +517,7 @@ public class StateMachine {
/**
* @return as string
*/
- @Override
- public String toString() {
+ public String toString(StateMachine sm) {
StringBuilder sb = new StringBuilder();
sb.append("time=");
Calendar c = Calendar.getInstance();
@@ -529,10 +528,15 @@ public class StateMachine {
sb.append(" orgState=");
sb.append(mOrgState == null ? "<null>" : mOrgState.getName());
sb.append(" what=");
- sb.append(mWhat);
- sb.append("(0x");
- sb.append(Integer.toHexString(mWhat));
- sb.append(")");
+ String what = sm.getWhatToString(mWhat);
+ if (TextUtils.isEmpty(what)) {
+ sb.append(mWhat);
+ sb.append("(0x");
+ sb.append(Integer.toHexString(mWhat));
+ sb.append(")");
+ } else {
+ sb.append(what);
+ }
if ( ! TextUtils.isEmpty(mInfo)) {
sb.append(" ");
sb.append(mInfo);
@@ -542,21 +546,21 @@ public class StateMachine {
}
/**
- * A list of messages recently processed by the state machine.
+ * A list of log records including messages recently processed by the state machine.
*
- * The class maintains a list of messages that have been most
+ * The class maintains a list of log records including messages
* recently processed. The list is finite and may be set in the
* constructor or by calling setSize. The public interface also
- * includes size which returns the number of recent messages,
- * count which is the number of message processed since the
- * the last setSize, get which returns a processed message and
- * add which adds a processed messaged.
+ * includes size which returns the number of recent records,
+ * count which is the number of records processed since the
+ * the last setSize, get which returns a record and
+ * add which adds a record.
*/
- private static class ProcessedMessages {
+ private static class LogRecords {
private static final int DEFAULT_SIZE = 20;
- private Vector<ProcessedMessageInfo> mMessages = new Vector<ProcessedMessageInfo>();
+ private Vector<LogRec> mLogRecords = new Vector<LogRec>();
private int mMaxSize = DEFAULT_SIZE;
private int mOldestIndex = 0;
private int mCount = 0;
@@ -564,39 +568,39 @@ public class StateMachine {
/**
* private constructor use add
*/
- private ProcessedMessages() {
+ private LogRecords() {
}
/**
- * Set size of messages to maintain and clears all current messages.
+ * Set size of messages to maintain and clears all current records.
*
- * @param maxSize number of messages to maintain at anyone time.
+ * @param maxSize number of records to maintain at anyone time.
*/
- void setSize(int maxSize) {
+ synchronized void setSize(int maxSize) {
mMaxSize = maxSize;
mCount = 0;
- mMessages.clear();
+ mLogRecords.clear();
}
/**
- * @return the number of recent messages.
+ * @return the number of recent records.
*/
- int size() {
- return mMessages.size();
+ synchronized int size() {
+ return mLogRecords.size();
}
/**
- * @return the total number of messages processed since size was set.
+ * @return the total number of records processed since size was set.
*/
- int count() {
+ synchronized int count() {
return mCount;
}
/**
- * Clear the list of Processed Message Info.
+ * Clear the list of records.
*/
- void cleanup() {
- mMessages.clear();
+ synchronized void cleanup() {
+ mLogRecords.clear();
}
/**
@@ -604,7 +608,7 @@ public class StateMachine {
* record and size()-1 is the newest record. If the index is to
* large null is returned.
*/
- ProcessedMessageInfo get(int index) {
+ synchronized LogRec get(int index) {
int nextIndex = mOldestIndex + index;
if (nextIndex >= mMaxSize) {
nextIndex -= mMaxSize;
@@ -612,7 +616,7 @@ public class StateMachine {
if (nextIndex >= size()) {
return null;
} else {
- return mMessages.get(nextIndex);
+ return mLogRecords.get(nextIndex);
}
}
@@ -625,12 +629,12 @@ public class StateMachine {
* @param orgState is the first state the received the message but
* did not processes the message.
*/
- void add(Message msg, String messageInfo, State state, State orgState) {
+ synchronized void add(Message msg, String messageInfo, State state, State orgState) {
mCount += 1;
- if (mMessages.size() < mMaxSize) {
- mMessages.add(new ProcessedMessageInfo(msg, messageInfo, state, orgState));
+ if (mLogRecords.size() < mMaxSize) {
+ mLogRecords.add(new LogRec(msg, messageInfo, state, orgState));
} else {
- ProcessedMessageInfo pmi = mMessages.get(mOldestIndex);
+ LogRec pmi = mLogRecords.get(mOldestIndex);
mOldestIndex += 1;
if (mOldestIndex >= mMaxSize) {
mOldestIndex = 0;
@@ -652,8 +656,8 @@ public class StateMachine {
/** The current message */
private Message mMsg;
- /** A list of messages that this state machine has processed */
- private ProcessedMessages mProcessedMessages = new ProcessedMessages();
+ /** A list of log records including messages this state machine has processed */
+ private LogRecords mLogRecords = new LogRecords();
/** true if construction of the state machine has not been completed */
private boolean mIsConstructionCompleted;
@@ -814,15 +818,18 @@ public class StateMachine {
*/
if (destState != null) {
if (destState == mQuittingState) {
+ /**
+ * Call onQuitting to let subclasses cleanup.
+ */
+ mSm.onQuitting();
cleanupAfterQuitting();
-
} else if (destState == mHaltingState) {
/**
- * Call halting() if we've transitioned to the halting
+ * Call onHalting() if we've transitioned to the halting
* state. All subsequent messages will be processed in
* in the halting state which invokes haltedProcessMessage(msg);
*/
- mSm.halting();
+ mSm.onHalting();
}
}
}
@@ -831,7 +838,6 @@ public class StateMachine {
* Cleanup all the static variables and the looper after the SM has been quit.
*/
private final void cleanupAfterQuitting() {
- mSm.quitting();
if (mSm.mSmThread != null) {
// If we made the thread then quit looper which stops the thread.
getLooper().quit();
@@ -841,7 +847,7 @@ public class StateMachine {
mSm.mSmHandler = null;
mSm = null;
mMsg = null;
- mProcessedMessages.cleanup();
+ mLogRecords.cleanup();
mStateStack = null;
mTempStateStack = null;
mStateInfo.clear();
@@ -892,36 +898,38 @@ public class StateMachine {
if (mDbg) {
Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
}
- while (!curStateInfo.state.processMessage(msg)) {
- /**
- * Not processed
- */
- curStateInfo = curStateInfo.parentStateInfo;
- if (curStateInfo == null) {
+
+ if (isQuit(msg)) {
+ transitionTo(mQuittingState);
+ } else {
+ while (!curStateInfo.state.processMessage(msg)) {
/**
- * No parents left so it's not handled
+ * Not processed
*/
- mSm.unhandledMessage(msg);
- if (isQuit(msg)) {
- transitionTo(mQuittingState);
+ curStateInfo = curStateInfo.parentStateInfo;
+ if (curStateInfo == null) {
+ /**
+ * No parents left so it's not handled
+ */
+ mSm.unhandledMessage(msg);
+ break;
+ }
+ if (mDbg) {
+ Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
}
- break;
- }
- if (mDbg) {
- Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
}
- }
- /**
- * Record that we processed the message
- */
- if (mSm.recordProcessedMessage(msg)) {
- if (curStateInfo != null) {
- State orgState = mStateStack[mStateStackTopIndex].state;
- mProcessedMessages.add(msg, mSm.getMessageInfo(msg), curStateInfo.state,
- orgState);
- } else {
- mProcessedMessages.add(msg, mSm.getMessageInfo(msg), null, null);
+ /**
+ * Record that we processed the message
+ */
+ if (mSm.recordLogRec(msg)) {
+ if (curStateInfo != null) {
+ State orgState = mStateStack[mStateStackTopIndex].state;
+ mLogRecords.add(msg, mSm.getLogRecString(msg), curStateInfo.state,
+ orgState);
+ } else {
+ mLogRecords.add(msg, mSm.getLogRecString(msg), null, null);
+ }
}
}
}
@@ -1141,13 +1149,19 @@ public class StateMachine {
mDeferredMessages.add(newMsg);
}
- /** @see StateMachine#deferMessage(Message) */
+ /** @see StateMachine#quit() */
private final void quit() {
if (mDbg) Log.d(TAG, "quit:");
sendMessage(obtainMessage(SM_QUIT_CMD, mSmHandlerObj));
}
- /** @see StateMachine#isQuit(Message) */
+ /** @see StateMachine#quitNow() */
+ private final void quitNow() {
+ if (mDbg) Log.d(TAG, "abort:");
+ sendMessageAtFrontOfQueue(obtainMessage(SM_QUIT_CMD, mSmHandlerObj));
+ }
+
+ /** Validate that the message was sent by quit or abort. */
private final boolean isQuit(Message msg) {
return (msg.what == SM_QUIT_CMD) && (msg.obj == mSmHandlerObj);
}
@@ -1162,26 +1176,6 @@ public class StateMachine {
mDbg = dbg;
}
- /** @see StateMachine#setProcessedMessagesSize(int) */
- private final void setProcessedMessagesSize(int maxSize) {
- mProcessedMessages.setSize(maxSize);
- }
-
- /** @see StateMachine#getProcessedMessagesSize() */
- private final int getProcessedMessagesSize() {
- return mProcessedMessages.size();
- }
-
- /** @see StateMachine#getProcessedMessagesCount() */
- private final int getProcessedMessagesCount() {
- return mProcessedMessages.count();
- }
-
- /** @see StateMachine#getProcessedMessageInfo(int) */
- private final ProcessedMessageInfo getProcessedMessageInfo(int index) {
- return mProcessedMessages.get(index);
- }
-
}
private SmHandler mSmHandler;
@@ -1282,8 +1276,8 @@ public class StateMachine {
/**
* transition to halt state. Upon returning
* from processMessage we will exit all current
- * states, execute the halting() method and then
- * all subsequent messages haltedProcessMesage
+ * states, execute the onHalting() method and then
+ * for all subsequent messages haltedProcessMessage
* will be called.
*/
protected final void transitionToHaltingState() {
@@ -1303,7 +1297,6 @@ public class StateMachine {
mSmHandler.deferMessage(msg);
}
-
/**
* Called when message wasn't handled
*
@@ -1325,7 +1318,7 @@ public class StateMachine {
* transitionToHalting. All subsequent messages will invoke
* {@link StateMachine#haltedProcessMessage(Message)}
*/
- protected void halting() {
+ protected void onHalting() {
}
/**
@@ -1334,7 +1327,7 @@ public class StateMachine {
* ignored. In addition, if this StateMachine created the thread, the thread will
* be stopped after this method returns.
*/
- protected void quitting() {
+ protected void onQuitting() {
}
/**
@@ -1345,33 +1338,77 @@ public class StateMachine {
}
/**
- * Set size of messages to maintain and clears all current messages.
+ * Set number of log records to maintain and clears all current records.
*
* @param maxSize number of messages to maintain at anyone time.
*/
- public final void setProcessedMessagesSize(int maxSize) {
- mSmHandler.setProcessedMessagesSize(maxSize);
+ public final void setLogRecSize(int maxSize) {
+ mSmHandler.mLogRecords.setSize(maxSize);
+ }
+
+ /**
+ * @return number of log records
+ */
+ public final int getLogRecSize() {
+ return mSmHandler.mLogRecords.size();
+ }
+
+ /**
+ * @return the total number of records processed
+ */
+ public final int getLogRecCount() {
+ return mSmHandler.mLogRecords.count();
+ }
+
+ /**
+ * @return a log record
+ */
+ public final LogRec getLogRec(int index) {
+ return mSmHandler.mLogRecords.get(index);
+ }
+
+ /**
+ * Add the string to LogRecords.
+ *
+ * @param string
+ */
+ protected void addLogRec(String string) {
+ mSmHandler.mLogRecords.add(null, string, null, null);
}
/**
- * @return number of messages processed
+ * Add the string and state to LogRecords
+ *
+ * @param string
+ * @param state current state
*/
- public final int getProcessedMessagesSize() {
- return mSmHandler.getProcessedMessagesSize();
+ protected void addLogRec(String string, State state) {
+ mSmHandler.mLogRecords.add(null, string, state, null);
}
/**
- * @return the total number of messages processed
+ * @return true if msg should be saved in the log, default is true.
*/
- public final int getProcessedMessagesCount() {
- return mSmHandler.getProcessedMessagesCount();
+ protected boolean recordLogRec(Message msg) {
+ return true;
}
/**
- * @return a processed message information
+ * Return a string to be logged by LogRec, default
+ * is an empty string. Override if additional information is desired.
+ *
+ * @param msg that was processed
+ * @return information to be logged as a String
*/
- public final ProcessedMessageInfo getProcessedMessageInfo(int index) {
- return mSmHandler.getProcessedMessageInfo(index);
+ protected String getLogRecString(Message msg) {
+ return "";
+ }
+
+ /**
+ * @return the string for msg.what
+ */
+ protected String getWhatToString(int what) {
+ return null;
}
/**
@@ -1548,43 +1585,23 @@ public class StateMachine {
}
/**
- * Conditionally quit the looper and stop execution.
- *
- * This sends the SM_QUIT_MSG to the state machine and
- * if not handled by any state's processMessage then the
- * state machine will be stopped and no further messages
- * will be processed.
+ * Quit the state machine after all currently queued up messages are processed.
*/
- public final void quit() {
- // mSmHandler can be null if the state machine has quit.
+ protected final void quit() {
+ // mSmHandler can be null if the state machine is already stopped.
if (mSmHandler == null) return;
mSmHandler.quit();
}
/**
- * @return ture if msg is quit
+ * Quit the state machine immediately all currently queued messages will be discarded.
*/
- protected final boolean isQuit(Message msg) {
- return mSmHandler.isQuit(msg);
- }
-
- /**
- * @return true if msg should be saved in ProcessedMessage, default is true.
- */
- protected boolean recordProcessedMessage(Message msg) {
- return true;
- }
+ protected final void quitNow() {
+ // mSmHandler can be null if the state machine is already stopped.
+ if (mSmHandler == null) return;
- /**
- * Return message info to be logged by ProcessedMessageInfo, default
- * is an empty string. Override if additional information is desired.
- *
- * @param msg that was processed
- * @return information to be logged as a String
- */
- protected String getMessageInfo(Message msg) {
- return "";
+ mSmHandler.quitNow();
}
/**
@@ -1629,9 +1646,9 @@ public class StateMachine {
*/
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(getName() + ":");
- pw.println(" total messages=" + getProcessedMessagesCount());
- for (int i=0; i < getProcessedMessagesSize(); i++) {
- pw.printf(" msg[%d]: %s\n", i, getProcessedMessageInfo(i));
+ pw.println(" total records=" + getLogRecCount());
+ for (int i=0; i < getLogRecSize(); i++) {
+ pw.printf(" rec[%d]: %s\n", i, getLogRec(i).toString(this));
pw.flush();
}
pw.println("curState=" + getCurrentState().getName());
diff --git a/core/java/com/android/internal/widget/LockSettingsService.java b/core/java/com/android/internal/widget/LockSettingsService.java
index 24c7161..2fb81ac 100644
--- a/core/java/com/android/internal/widget/LockSettingsService.java
+++ b/core/java/com/android/internal/widget/LockSettingsService.java
@@ -24,6 +24,7 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Binder;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.os.UserId;
import android.provider.Settings;
import android.provider.Settings.Secure;
@@ -303,12 +304,15 @@ public class LockSettingsService extends ILockSettings.Stub {
}
private void writeToDb(String key, String value, int userId) {
+ writeToDb(mOpenHelper.getWritableDatabase(), key, value, userId);
+ }
+
+ private void writeToDb(SQLiteDatabase db, String key, String value, int userId) {
ContentValues cv = new ContentValues();
cv.put(COLUMN_KEY, key);
cv.put(COLUMN_USERID, userId);
cv.put(COLUMN_VALUE, value);
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
db.beginTransaction();
try {
db.delete(TABLE, COLUMN_KEY + "=? AND " + COLUMN_USERID + "=?",
@@ -359,6 +363,16 @@ public class LockSettingsService extends ILockSettings.Stub {
@Override
public void onCreate(SQLiteDatabase db) {
createTable(db);
+ initializeDefaults(db);
+ }
+
+ private void initializeDefaults(SQLiteDatabase db) {
+ // Get the lockscreen default from a system property, if available
+ boolean lockScreenDisable = SystemProperties.getBoolean("ro.lockscreen.disable.default",
+ false);
+ if (lockScreenDisable) {
+ writeToDb(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
+ }
}
@Override