diff options
Diffstat (limited to 'core/java')
50 files changed, 1314 insertions, 1076 deletions
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 9ba5305..d8777fb 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -1912,7 +1912,7 @@ final class FragmentManagerImpl extends FragmentManager { if (mActive != 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/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/Intent.java b/core/java/android/content/Intent.java index edd509b..352f996 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -570,7 +570,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} @@ -1285,6 +1287,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/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/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/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/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 816b631..672ff02 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; @@ -1787,28 +1791,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; @@ -1873,7 +1873,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; @@ -1881,7 +1880,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; @@ -1889,31 +1887,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; @@ -1971,7 +1964,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; @@ -1980,7 +1972,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; @@ -1988,7 +1979,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; @@ -1996,7 +1986,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; @@ -2004,7 +1993,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; @@ -2013,7 +2001,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; @@ -2022,13 +2009,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; @@ -3867,6 +3852,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(); } @@ -5663,9 +5657,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"), @@ -5687,7 +5679,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) { @@ -5707,7 +5698,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"), @@ -5727,7 +5717,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() { @@ -11470,7 +11459,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 @@ -11515,14 +11503,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 @@ -11582,7 +11568,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) { } @@ -11591,7 +11576,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()) { @@ -11605,7 +11589,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 @@ -11622,7 +11605,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() { } @@ -11632,7 +11614,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)); @@ -13938,13 +13919,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) { } /** @@ -14213,8 +14210,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; @@ -14377,13 +14375,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; @@ -14437,7 +14441,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) ? @@ -14461,7 +14464,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) ? @@ -14470,10 +14472,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; @@ -16272,7 +16275,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"), @@ -16297,7 +16299,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) { @@ -16327,7 +16328,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 @@ -16340,7 +16340,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 @@ -16401,7 +16400,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() { } @@ -16410,7 +16408,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()) { @@ -16425,7 +16422,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); @@ -16436,7 +16432,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() { } @@ -16454,7 +16449,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"), @@ -16483,7 +16477,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()) { @@ -16513,7 +16506,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"), @@ -16535,7 +16527,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 @@ -16600,7 +16591,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()) { @@ -16616,7 +16606,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() { } @@ -16625,7 +16614,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 @@ -16637,7 +16625,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/ViewGroup.java b/core/java/android/view/ViewGroup.java index e7b0e78..a6ba0ec 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/VolumePanel.java b/core/java/android/view/VolumePanel.java index 5ffc2c3..30d87c4 100644 --- a/core/java/android/view/VolumePanel.java +++ b/core/java/android/view/VolumePanel.java @@ -103,6 +103,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 */ @@ -275,6 +278,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(); } @@ -662,7 +672,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/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..36665ee 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. @@ -188,7 +188,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 +249,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 +403,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")); } @@ -1081,7 +1082,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 +1093,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 +1302,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 +1317,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); } 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/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..d90f031 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; } 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/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/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java index 611742b..5314e47 100644 --- a/core/java/android/webkit/WebViewClassic.java +++ b/core/java/android/webkit/WebViewClassic.java @@ -945,21 +945,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 +1048,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 +2196,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 +2210,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 +2409,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 +2417,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 +2438,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 +2611,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 +2634,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 +2657,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; @@ -3371,7 +3371,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 +3535,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,13 +3819,13 @@ 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. @@ -4519,54 +4519,63 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc 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, + 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.draw(canvas); + } + private void drawTextSelectionHandles(Canvas canvas) { if (mHandleAlpha.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()); + 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.draw(canvas); } 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()); + drawHandle(mSelectCursorBase, HANDLE_ID_BASE, + mSelectHandleBaseBounds, canvas); + drawHandle(mSelectCursorExtent, HANDLE_ID_EXTENT, + mSelectHandleExtentBounds, canvas); } } - - if (mIsCaretSelection) { - mSelectHandleCenter.draw(canvas); - } else { - mSelectHandleLeft.draw(canvas); - mSelectHandleRight.draw(canvas); - } } /** @@ -4574,10 +4583,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc * 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 +4821,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 +5090,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 +5141,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 +5157,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 +5177,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 +5544,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; } } @@ -5800,28 +5801,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)) { - mSelectionStarted = true; - mSelectDraggingCursor = mSelectCursorLeft; - mSelectDraggingOffset = mSelectHandleCenterOffset; - mSelectDraggingTextQuad = mSelectCursorLeftTextQuad; - mPrivateHandler.removeMessages(CLEAR_CARET_HANDLE); - hidePasteButton(); - } else if (mSelectHandleLeft != null - && mSelectHandleLeft.getBounds() - .contains(shiftedX, shiftedY)) { + if (mSelectHandleBaseBounds.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(); } @@ -5866,9 +5858,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); @@ -6005,12 +5997,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) { @@ -6117,6 +6112,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() - @@ -6125,10 +6124,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); @@ -6144,10 +6170,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) { @@ -6157,24 +6183,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); } } } @@ -6230,10 +6259,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 @@ -6334,10 +6363,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); } @@ -7436,7 +7465,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; @@ -7517,6 +7546,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc scrollEditWithCursor(); break; + case SCROLL_HANDLE_INTO_VIEW: + scrollDraggedSelectionHandleIntoView(); + break; + default: super.handleMessage(msg); break; @@ -7552,8 +7585,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; } @@ -7910,10 +7943,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc } else { if (!mSelectingText) { setupWebkitSelect(); - } else if (!mSelectionStarted) { - syncSelectionCursors(); } else { - adjustSelectionCursors(); + syncSelectionCursors(); } if (mIsCaretSelection) { resetCaretTimer(); @@ -7930,7 +7961,8 @@ 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); } @@ -8580,4 +8612,5 @@ 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); } 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..eaaaf77 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; @@ -960,7 +962,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 +1201,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 +1309,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 +1658,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 +1710,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: { @@ -2330,7 +2328,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 +2345,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 +2359,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; } @@ -2855,7 +2851,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 +3059,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 +3101,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 +3146,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/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 8975109..71ad148 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 ad4d742..331d208 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -1657,13 +1657,15 @@ 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 - * @param bottom The id of a drawable to place below the text, or 0 - * @hide + * @param bottom The id of a drawable to place below the text, or 0 */ 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/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 { } @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 |
