summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/SearchDialog.java9
-rw-r--r--core/java/android/bluetooth/BluetoothA2dp.java66
-rw-r--r--core/java/android/bluetooth/BluetoothHeadset.java109
-rw-r--r--core/java/android/bluetooth/IBluetoothA2dp.aidl2
-rw-r--r--core/java/android/bluetooth/IBluetoothHeadset.aidl18
-rw-r--r--core/java/android/content/Context.java9
-rw-r--r--core/java/android/gadget/GadgetHost.java72
-rw-r--r--core/java/android/gadget/GadgetHostView.java102
-rw-r--r--core/java/android/gadget/GadgetInfo.aidl (renamed from core/java/android/bluetooth/IBluetoothHeadsetCallback.aidl)28
-rw-r--r--core/java/android/gadget/GadgetInfo.java126
-rw-r--r--core/java/android/gadget/GadgetManager.java170
-rw-r--r--core/java/android/gadget/package.html4
-rw-r--r--core/java/android/hardware/Camera.java27
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java198
-rw-r--r--core/java/android/provider/Settings.java38
-rw-r--r--core/java/android/provider/UserDictionary.java127
-rw-r--r--core/java/android/server/BluetoothA2dpService.java52
-rw-r--r--core/java/android/speech/srec/Recognizer.java40
-rw-r--r--core/java/android/speech/srec/WaveHeader.java7
-rw-r--r--core/java/android/view/ViewRoot.java30
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java5
-rw-r--r--core/java/android/webkit/CallbackProxy.java136
-rw-r--r--core/java/android/webkit/TextDialog.java49
-rw-r--r--core/java/android/webkit/WebView.java13
-rw-r--r--core/java/android/widget/AutoCompleteTextView.java2
-rw-r--r--core/java/android/widget/MediaController.java6
-rw-r--r--core/java/android/widget/VideoView.java7
-rw-r--r--core/java/com/android/internal/gadget/IGadgetService.aidl28
-rw-r--r--core/java/com/android/internal/gadget/package.html3
-rw-r--r--core/java/com/android/internal/os/HandlerCaller.java2
-rw-r--r--core/java/com/android/internal/view/menu/IconMenuItemView.java4
-rw-r--r--core/java/com/android/internal/view/menu/ListMenuItemView.java8
-rw-r--r--core/java/com/android/internal/view/menu/MenuBuilder.java13
-rw-r--r--core/java/com/android/internal/widget/NumberPicker.java1
34 files changed, 1344 insertions, 167 deletions
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 495156e..5af08f7 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -1129,6 +1129,15 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
}
/**
+ * We never allow ACTV to automatically replace the text, since we use "jamSuggestionQuery"
+ * to do that. There's no point in letting ACTV do this here, because in the search UI,
+ * as soon as we click a suggestion, we're going to start shutting things down.
+ */
+ @Override
+ public void replaceText(CharSequence text) {
+ }
+
+ /**
* We always return true, so that the effective threshold is "zero". This allows us
* to provide "null" suggestions such as "just show me some recent entries".
*/
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 022a87c..b0b0154 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -72,6 +72,12 @@ public class BluetoothA2dp {
/** Playing implies connected */
public static final int STATE_PLAYING = 4;
+ /** Default priority for a2dp devices that should allow incoming
+ * connections */
+ public static final int PRIORITY_AUTO = 100;
+ /** Default priority for a2dp devices that should not allow incoming
+ * connections */
+ public static final int PRIORITY_OFF = 0;
private final IBluetoothA2dp mService;
private final Context mContext;
@@ -158,6 +164,66 @@ public class BluetoothA2dp {
}
}
+ /**
+ * Set priority of a2dp sink.
+ * Priority is a non-negative integer. By default paired sinks will have
+ * a priority of PRIORITY_AUTO, and unpaired headset PRIORITY_NONE (0).
+ * Sinks with priority greater than zero will accept incoming connections
+ * (if no sink is currently connected).
+ * Priority for unpaired sink must be PRIORITY_NONE.
+ * @param address Paired sink
+ * @param priority Integer priority, for example PRIORITY_AUTO or
+ * PRIORITY_NONE
+ * @return Result code, negative indicates an error
+ */
+ public int setSinkPriority(String address, int priority) {
+ try {
+ return mService.setSinkPriority(address, priority);
+ } catch (RemoteException e) {
+ Log.w(TAG, "", e);
+ return BluetoothError.ERROR_IPC;
+ }
+ }
+
+ /**
+ * Get priority of a2dp sink.
+ * @param address Sink
+ * @return non-negative priority, or negative error code on error.
+ */
+ public int getSinkPriority(String address) {
+ try {
+ return mService.getSinkPriority(address);
+ } catch (RemoteException e) {
+ Log.w(TAG, "", e);
+ return BluetoothError.ERROR_IPC;
+ }
+ }
+
+ /**
+ * Check class bits for possible A2DP Sink support.
+ * This is a simple heuristic that tries to guess if a device with the
+ * given class bits might be a A2DP Sink. It is not accurate for all
+ * devices. It tries to err on the side of false positives.
+ * @return True if this device might be a A2DP sink
+ */
+ public static boolean doesClassMatchSink(int btClass) {
+ if (BluetoothClass.Service.hasService(btClass, BluetoothClass.Service.RENDER)) {
+ return true;
+ }
+ // By the A2DP spec, sinks must indicate the RENDER service.
+ // However we found some that do not (Chordette). So lets also
+ // match on some other class bits.
+ switch (BluetoothClass.Device.getDevice(btClass)) {
+ case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO:
+ case BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES:
+ case BluetoothClass.Device.AUDIO_VIDEO_LOUDSPEAKER:
+ case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
+ return true;
+ default:
+ return false;
+ }
+ }
+
/** Helper for converting a state to a string.
* For debug use only - strings are not internationalized.
* @hide
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 905173e..c315271 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -57,7 +57,6 @@ public class BluetoothHeadset {
private IBluetoothHeadset mService;
private final Context mContext;
private final ServiceListener mServiceListener;
- private ConnectHeadsetCallback mConnectHeadsetCallback;
/** There was an error trying to obtain the state */
public static final int STATE_ERROR = -1;
@@ -73,6 +72,11 @@ public class BluetoothHeadset {
/** Connection cancelled before completetion. */
public static final int RESULT_CANCELLED = 2;
+ /** Default priority for headsets that should be auto-connected */
+ public static final int PRIORITY_AUTO = 100;
+ /** Default priority for headsets that should not be auto-connected */
+ public static final int PRIORITY_OFF = 0;
+
/**
* An interface for notifying BluetoothHeadset IPC clients when they have
* been connected to the BluetoothHeadset service.
@@ -97,14 +101,6 @@ public class BluetoothHeadset {
}
/**
- * Interface for connectHeadset() callback.
- * This callback can occur in the Binder thread.
- */
- public interface ConnectHeadsetCallback {
- public void onConnectHeadsetResult(String address, int resultCode);
- }
-
- /**
* Create a BluetoothHeadset proxy object.
*/
public BluetoothHeadset(Context context, ServiceListener l) {
@@ -175,24 +171,18 @@ public class BluetoothHeadset {
* Request to initiate a connection to a headset.
* This call does not block. Fails if a headset is already connecting
* or connected.
- * Will connect to the last connected headset if address is null.
- * onConnectHeadsetResult() of your ConnectHeadsetCallback will be called
- * on completition.
- * @param address The Bluetooth Address to connect to, or null to connect
- * to the last connected headset.
- * @param callback Callback on result. Not called if false is returned. Can
- * be null.
- * to the last connected headset.
+ * Initiates auto-connection if address is null. Tries to connect to all
+ * devices with priority greater than PRIORITY_AUTO in descending order.
+ * @param address The Bluetooth Address to connect to, or null to
+ * auto-connect to the last connected headset.
* @return False if there was a problem initiating the connection
- * procedure, and your callback will not be used. True if
- * the connection procedure was initiated, in which case
- * your callback is guarenteed to be called.
+ * procedure, and no further HEADSET_STATE_CHANGED intents
+ * will be expected.
*/
- public boolean connectHeadset(String address, ConnectHeadsetCallback callback) {
+ public boolean connectHeadset(String address) {
if (mService != null) {
try {
- if (mService.connectHeadset(address, mHeadsetCallback)) {
- mConnectHeadsetCallback = callback;
+ if (mService.connectHeadset(address)) {
return true;
}
} catch (RemoteException e) {Log.e(TAG, e.toString());}
@@ -273,6 +263,71 @@ public class BluetoothHeadset {
return false;
}
+ /**
+ * Set priority of headset.
+ * Priority is a non-negative integer. By default paired headsets will have
+ * a priority of PRIORITY_AUTO, and unpaired headset PRIORITY_NONE (0).
+ * Headsets with priority greater than zero will be auto-connected, and
+ * incoming connections will be accepted (if no other headset is
+ * connected).
+ * Auto-connection occurs at the following events: boot, incoming phone
+ * call, outgoing phone call.
+ * Headsets with priority equal to zero, or that are unpaired, are not
+ * auto-connected.
+ * Incoming connections are ignored regardless of priority if there is
+ * already a headset connected.
+ * @param address Paired headset
+ * @param priority Integer priority, for example PRIORITY_AUTO or
+ * PRIORITY_NONE
+ * @return True if successful, false if there was some error.
+ */
+ public boolean setPriority(String address, int priority) {
+ if (mService != null) {
+ try {
+ return mService.setPriority(address, priority);
+ } catch (RemoteException e) {Log.e(TAG, e.toString());}
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ return false;
+ }
+
+ /**
+ * Get priority of headset.
+ * @param address Headset
+ * @return non-negative priority, or negative error code on error.
+ */
+ public int getPriority(String address) {
+ if (mService != null) {
+ try {
+ return mService.getPriority(address);
+ } catch (RemoteException e) {Log.e(TAG, e.toString());}
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ return -1;
+ }
+
+ /**
+ * Check class bits for possible HSP or HFP support.
+ * This is a simple heuristic that tries to guess if a device with the
+ * given class bits might support HSP or HFP. It is not accurate for all
+ * devices. It tries to err on the side of false positives.
+ * @return True if this device might support HSP or HFP.
+ */
+ public static boolean doesClassMatch(int btClass) {
+ switch (BluetoothClass.Device.getDevice(btClass)) {
+ case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
+ case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
+ case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
+ return true;
+ default:
+ return false;
+ }
+ }
+
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
@@ -289,12 +344,4 @@ public class BluetoothHeadset {
}
}
};
-
- private IBluetoothHeadsetCallback mHeadsetCallback = new IBluetoothHeadsetCallback.Stub() {
- public void onConnectHeadsetResult(String address, int resultCode) {
- if (mConnectHeadsetCallback != null) {
- mConnectHeadsetCallback.onConnectHeadsetResult(address, resultCode);
- }
- }
- };
}
diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl
index 7e0226d..55ff27f 100644
--- a/core/java/android/bluetooth/IBluetoothA2dp.aidl
+++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl
@@ -26,4 +26,6 @@ interface IBluetoothA2dp {
int disconnectSink(in String address);
List<String> listConnectedSinks();
int getSinkState(in String address);
+ int setSinkPriority(in String address, int priority);
+ int getSinkPriority(in String address);
}
diff --git a/core/java/android/bluetooth/IBluetoothHeadset.aidl b/core/java/android/bluetooth/IBluetoothHeadset.aidl
index 564861f..582d4e3 100644
--- a/core/java/android/bluetooth/IBluetoothHeadset.aidl
+++ b/core/java/android/bluetooth/IBluetoothHeadset.aidl
@@ -16,8 +16,6 @@
package android.bluetooth;
-import android.bluetooth.IBluetoothHeadsetCallback;
-
/**
* System private API for Bluetooth Headset service
*
@@ -25,22 +23,12 @@ import android.bluetooth.IBluetoothHeadsetCallback;
*/
interface IBluetoothHeadset {
int getState();
-
String getHeadsetAddress();
-
- // Request that the given headset be connected
- // Assumes the given headset is already bonded
- // Will disconnect any currently connected headset
- // returns false if cannot start a connection (for example, there is
- // already a pending connect). callback will always be called iff this
- // returns true
- boolean connectHeadset(in String address, in IBluetoothHeadsetCallback callback);
-
+ boolean connectHeadset(in String address);
void disconnectHeadset();
-
boolean isConnected(in String address);
-
boolean startVoiceRecognition();
-
boolean stopVoiceRecognition();
+ boolean setPriority(in String address, int priority);
+ int getPriority(in String address);
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 6da00df..3908aa1 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1249,6 +1249,15 @@ public abstract class Context {
public static final String INPUT_METHOD_SERVICE = "input_method";
/**
+ * Use with {@link #getSystemService} to retrieve a
+ * {@blink android.gadget.GadgetManager} for accessing wallpapers.
+ *
+ * @hide
+ * @see #getSystemService
+ */
+ public static final String GADGET_SERVICE = "gadget";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/gadget/GadgetHost.java b/core/java/android/gadget/GadgetHost.java
new file mode 100644
index 0000000..418f2aa
--- /dev/null
+++ b/core/java/android/gadget/GadgetHost.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2006 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.gadget;
+
+import android.content.Context;
+import android.widget.RemoteViews;
+
+/**
+ * GadgetHost provides the interaction with the Gadget Service for apps,
+ * like the home screen, that want to embed gadgets in their UI.
+ */
+public class GadgetHost {
+ public GadgetHost(Context context, int hostId) {
+ }
+
+ /**
+ * Start receiving onGadgetChanged calls for your gadgets. Call this when your activity
+ * becomes visible, i.e. from onStart() in your Activity.
+ */
+ public void startListening() {
+ }
+
+ /**
+ * Stop receiving onGadgetChanged calls for your gadgets. Call this when your activity is
+ * no longer visible, i.e. from onStop() in your Activity.
+ */
+ public void stopListening() {
+ }
+
+ /**
+ * Stop listening to changes for this gadget.
+ */
+ public void gadgetRemoved(int gadgetId) {
+ }
+
+ /**
+ * Remove all records about gadget instances from the gadget manager. Call this when
+ * initializing your database, as it might be because of a data wipe.
+ */
+ public void clearGadgets() {
+ }
+
+ public final GadgetHostView createView(Context context, int gadgetId, GadgetInfo gadget) {
+ GadgetHostView view = onCreateView(context, gadgetId, gadget);
+ view.setGadget(gadgetId, gadget);
+ view.updateGadget(null);
+ return view;
+ }
+
+ /**
+ * Called to create the GadgetHostView. Override to return a custom subclass if you
+ * need it. {@more}
+ */
+ protected GadgetHostView onCreateView(Context context, int gadgetId, GadgetInfo gadget) {
+ return new GadgetHostView(context);
+ }
+}
+
diff --git a/core/java/android/gadget/GadgetHostView.java b/core/java/android/gadget/GadgetHostView.java
new file mode 100644
index 0000000..e2bef8c
--- /dev/null
+++ b/core/java/android/gadget/GadgetHostView.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2008 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.gadget;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.gadget.GadgetInfo;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.RemoteViews;
+import android.widget.TextView;
+
+public class GadgetHostView extends FrameLayout {
+ static final String TAG = "GadgetHostView";
+
+ // When we're inflating the initialLayout for a gadget, we only allow
+ // views that are allowed in RemoteViews.
+ static final LayoutInflater.Filter sInflaterFilter = new LayoutInflater.Filter() {
+ public boolean onLoadClass(Class clazz) {
+ return clazz.isAnnotationPresent(RemoteViews.RemoteView.class);
+ }
+ };
+
+ int mGadgetId;
+ GadgetInfo mInfo;
+ View mContentView;
+
+ public GadgetHostView(Context context) {
+ super(context);
+ }
+
+ public void setGadget(int gadgetId, GadgetInfo info) {
+ if (mInfo != null) {
+ // TODO: remove the old view, or whatever
+ }
+ mGadgetId = gadgetId;
+ mInfo = info;
+ }
+
+ public void updateGadget(RemoteViews remoteViews) {
+ Context context = getContext();
+
+ View contentView = null;
+ Exception exception = null;
+ try {
+ if (remoteViews == null) {
+ // there is no remoteViews (yet), so use the initial layout
+ Context theirContext = context.createPackageContext(mInfo.provider.getPackageName(),
+ 0);
+ LayoutInflater inflater = (LayoutInflater)theirContext.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ inflater = inflater.cloneInContext(theirContext);
+ inflater.setFilter(sInflaterFilter);
+ contentView = inflater.inflate(mInfo.initialLayout, this, false);
+ } else {
+ // use the RemoteViews
+ contentView = remoteViews.apply(mContext, this);
+ }
+ }
+ catch (PackageManager.NameNotFoundException e) {
+ exception = e;
+ }
+ catch (RuntimeException e) {
+ exception = e;
+ }
+ if (contentView == null) {
+ Log.w(TAG, "Error inflating gadget " + mInfo, exception);
+ // TODO: Should we throw an exception here for the host activity to catch?
+ // Maybe we should show a generic error widget.
+ TextView tv = new TextView(context);
+ tv.setText("Error inflating gadget");
+ contentView = tv;
+ }
+
+ FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.WRAP_CONTENT,
+ FrameLayout.LayoutParams.WRAP_CONTENT);
+
+ mContentView = contentView;
+ this.addView(contentView, lp);
+
+ // TODO: do an animation (maybe even one provided by the gadget).
+ }
+}
+
diff --git a/core/java/android/bluetooth/IBluetoothHeadsetCallback.aidl b/core/java/android/gadget/GadgetInfo.aidl
index 03e884b..7231545 100644
--- a/core/java/android/bluetooth/IBluetoothHeadsetCallback.aidl
+++ b/core/java/android/gadget/GadgetInfo.aidl
@@ -1,25 +1,19 @@
/*
- * Copyright (C) 2008, The Android Open Source Project
+ * Copyright (c) 2007, 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
+ * 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
+ * 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
+ * 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.bluetooth;
+package android.gadget;
-/**
- * {@hide}
- */
-oneway interface IBluetoothHeadsetCallback
-{
- void onConnectHeadsetResult(in String address, int resultCode);
-}
+parcelable GadgetInfo;
diff --git a/core/java/android/gadget/GadgetInfo.java b/core/java/android/gadget/GadgetInfo.java
new file mode 100644
index 0000000..1a7a9a0
--- /dev/null
+++ b/core/java/android/gadget/GadgetInfo.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2006 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.gadget;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.content.ComponentName;
+
+/**
+ * Describes the meta data for an installed gadget.
+ */
+public class GadgetInfo implements Parcelable {
+ /**
+ * Identity of this gadget component. This component should be a {@link
+ * android.content.BroadcastReceiver}, and it will be sent the Gadget intents
+ * {@link android.gadget as described in the gadget package documentation}.
+ */
+ public ComponentName provider;
+
+ /**
+ * Minimum width of the gadget, in dp.
+ */
+ public int minWidth;
+
+ /**
+ * Minimum height of the gadget, in dp.
+ */
+ public int minHeight;
+
+ /**
+ * How often, in milliseconds, that this gadget wants to be updated.
+ * The gadget manager may place a limit on how often a gadget is updated.
+ */
+ public int updatePeriodMillis;
+
+ /**
+ * The resource id of the initial layout for this gadget. This should be
+ * displayed until the RemoteViews for the gadget is available.
+ */
+ public int initialLayout;
+
+ /**
+ * The activity to launch that will configure the gadget.
+ */
+ public ComponentName configure;
+
+ public GadgetInfo() {
+ }
+
+ /**
+ * Unflatten the GadgetInfo from a parcel.
+ */
+ public GadgetInfo(Parcel in) {
+ if (0 != in.readInt()) {
+ this.provider = new ComponentName(in);
+ }
+ this.minWidth = in.readInt();
+ this.minHeight = in.readInt();
+ this.updatePeriodMillis = in.readInt();
+ this.initialLayout = in.readInt();
+ if (0 != in.readInt()) {
+ this.configure = new ComponentName(in);
+ }
+ }
+
+
+ public void writeToParcel(android.os.Parcel out, int flags) {
+ if (this.provider != null) {
+ out.writeInt(1);
+ this.provider.writeToParcel(out, flags);
+ } else {
+ out.writeInt(0);
+ }
+ out.writeInt(this.minWidth);
+ out.writeInt(this.minHeight);
+ out.writeInt(this.updatePeriodMillis);
+ out.writeInt(this.initialLayout);
+ if (this.configure != null) {
+ out.writeInt(1);
+ this.configure.writeToParcel(out, flags);
+ } else {
+ out.writeInt(0);
+ }
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Parcelable.Creator that instantiates GadgetInfo objects
+ */
+ public static final Parcelable.Creator<GadgetInfo> CREATOR
+ = new Parcelable.Creator<GadgetInfo>()
+ {
+ public GadgetInfo createFromParcel(Parcel parcel)
+ {
+ return new GadgetInfo(parcel);
+ }
+
+ public GadgetInfo[] newArray(int size)
+ {
+ return new GadgetInfo[size];
+ }
+ };
+
+ public String toString() {
+ return "GadgetInfo(provider=" + this.provider + ")";
+ }
+}
+
+
diff --git a/core/java/android/gadget/GadgetManager.java b/core/java/android/gadget/GadgetManager.java
new file mode 100644
index 0000000..49c706e
--- /dev/null
+++ b/core/java/android/gadget/GadgetManager.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2006 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.gadget;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.widget.RemoteViews;
+
+import com.android.internal.gadget.IGadgetService;
+
+import java.lang.ref.WeakReference;
+import java.util.List;
+import java.util.WeakHashMap;
+
+public class GadgetManager {
+ static final String TAG = "GadgetManager";
+
+ /**
+ * Send this when you want to pick a gadget to display.
+ *
+ * <p>
+ * The system will respond with an onActivityResult call with the following extras in
+ * the intent:
+ * <ul>
+ * <li><b>gadgetId</b></li>
+ * <li><b>gadgetId</b></li>
+ * <li><b>gadgetId</b></li>
+ * </ul>
+ * TODO: Add constants for these.
+ * TODO: Where does this go?
+ */
+ public static final String GADGET_PICK_ACTION = "android.gadget.action.PICK_GADGET";
+
+ public static final String EXTRA_GADGET_ID = "gadgetId";
+
+ /**
+ * Sent when it is time to update your gadget.
+ */
+ public static final String GADGET_UPDATE_ACTION = "android.gadget.GADGET_UPDATE";
+
+ /**
+ * Sent when the gadget is added to a host for the first time. TODO: Maybe we don't want this.
+ */
+ public static final String GADGET_ENABLE_ACTION = "android.gadget.GADGET_ENABLE";
+
+ /**
+ * Sent when the gadget is removed from the last host. TODO: Maybe we don't want this.
+ */
+ public static final String GADGET_DISABLE_ACTION = "android.gadget.GADGET_DISABLE";
+
+ static WeakHashMap<Context, WeakReference<GadgetManager>> sManagerCache = new WeakHashMap();
+ static IGadgetService sService;
+
+ Context mContext;
+
+ public static GadgetManager getInstance(Context context) {
+ synchronized (sManagerCache) {
+ if (sService == null) {
+ IBinder b = ServiceManager.getService(Context.GADGET_SERVICE);
+ sService = IGadgetService.Stub.asInterface(b);
+ }
+
+ WeakReference<GadgetManager> ref = sManagerCache.get(context);
+ GadgetManager result = null;
+ if (ref != null) {
+ result = ref.get();
+ }
+ if (result == null) {
+ result = new GadgetManager(context);
+ sManagerCache.put(context, new WeakReference(result));
+ }
+ return result;
+ }
+ }
+
+ private GadgetManager(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Call this with the new RemoteViews for your gadget whenever you need to.
+ *
+ * <p>
+ * This method will only work when called from the uid that owns the gadget provider.
+ *
+ * @param gadgetId The gadget instance for which to set the RemoteViews.
+ * @param views The RemoteViews object to show.
+ */
+ public void updateGadget(int gadgetId, RemoteViews views) {
+ }
+
+ /**
+ * Return a list of the gadgets that are currently installed.
+ */
+ public List<GadgetInfo> getAvailableGadgets() {
+ return null;
+ }
+
+ /**
+ * Get the available info about the gadget. If the gadgetId has not been bound yet,
+ * this method will return null.
+ *
+ * TODO: throws GadgetNotFoundException ??? if not valid
+ */
+ public GadgetInfo getGadgetInfo(int gadgetId) {
+ try {
+ return sService.getGadgetInfo(gadgetId);
+ }
+ catch (RemoteException e) {
+ throw new RuntimeException("system server dead?", e);
+ }
+ }
+
+ /**
+ * Get a gadgetId for a host in the calling process.
+ *
+ * @return a gadgetId
+ */
+ public int allocateGadgetId(String hostPackage) {
+ try {
+ return sService.allocateGadgetId(hostPackage);
+ }
+ catch (RemoteException e) {
+ throw new RuntimeException("system server dead?", e);
+ }
+ }
+
+ /**
+ * Delete the gadgetId. Same as removeGadget on GadgetHost.
+ */
+ public void deleteGadgetId(int gadgetId) {
+ try {
+ sService.deleteGadgetId(gadgetId);
+ }
+ catch (RemoteException e) {
+ throw new RuntimeException("system server dead?", e);
+ }
+ }
+
+ /**
+ * Set the component for a given gadgetId. You need the GADGET_LIST permission.
+ */
+ public void bindGadgetId(int gadgetId, ComponentName provider) {
+ try {
+ sService.bindGadgetId(gadgetId, provider);
+ }
+ catch (RemoteException e) {
+ throw new RuntimeException("system server dead?", e);
+ }
+ }
+}
+
diff --git a/core/java/android/gadget/package.html b/core/java/android/gadget/package.html
new file mode 100644
index 0000000..280ccfb
--- /dev/null
+++ b/core/java/android/gadget/package.html
@@ -0,0 +1,4 @@
+<body>
+@hide
+</body>
+
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index e2d7097..c09567c 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -55,6 +55,7 @@ public class Camera {
private PreviewCallback mPreviewCallback;
private AutoFocusCallback mAutoFocusCallback;
private ErrorCallback mErrorCallback;
+ private boolean mOneShot;
/**
* Returns a new Camera object.
@@ -198,9 +199,25 @@ public class Camera {
*/
public final void setPreviewCallback(PreviewCallback cb) {
mPreviewCallback = cb;
- setHasPreviewCallback(cb != null);
+ mOneShot = false;
+ setHasPreviewCallback(cb != null, false);
}
- private native final void setHasPreviewCallback(boolean installed);
+
+ /**
+ * Installs a callback to retrieve a single preview frame, after which the
+ * callback is cleared.
+ *
+ * @param cb A callback object that receives a copy of the preview frame.
+ */
+ public final void setOneShotPreviewCallback(PreviewCallback cb) {
+ if (cb != null) {
+ mPreviewCallback = cb;
+ mOneShot = true;
+ setHasPreviewCallback(true, true);
+ }
+ }
+
+ private native final void setHasPreviewCallback(boolean installed, boolean oneshot);
private class EventHandler extends Handler
{
@@ -230,8 +247,12 @@ public class Camera {
return;
case PREVIEW_CALLBACK:
- if (mPreviewCallback != null)
+ if (mPreviewCallback != null) {
mPreviewCallback.onPreviewFrame((byte[])msg.obj, mCamera);
+ if (mOneShot) {
+ mPreviewCallback = null;
+ }
+ }
return;
case AUTOFOCUS_CALLBACK:
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 21bb38e..1a7547d 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -33,6 +33,8 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.view.Window;
+import android.view.WindowManager;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
@@ -197,6 +199,7 @@ public class InputMethodService extends AbstractInputMethodService {
EditorInfo mInputEditorInfo;
boolean mShowInputRequested;
+ boolean mLastShowInputRequested;
boolean mShowCandidatesRequested;
boolean mFullscreenApplied;
@@ -257,6 +260,8 @@ public class InputMethodService extends AbstractInputMethodService {
public void bindInput(InputBinding binding) {
mInputBinding = binding;
mInputConnection = binding.getConnection();
+ if (DEBUG) Log.v(TAG, "bindInput(): binding=" + binding
+ + " ic=" + mInputConnection);
onBindInput();
}
@@ -264,17 +269,22 @@ public class InputMethodService extends AbstractInputMethodService {
* Clear the current input binding.
*/
public void unbindInput() {
+ if (DEBUG) Log.v(TAG, "unbindInput(): binding=" + mInputBinding
+ + " ic=" + mInputConnection);
+ onUnbindInput();
mInputStarted = false;
mInputBinding = null;
mInputConnection = null;
}
public void startInput(EditorInfo attribute) {
+ if (DEBUG) Log.v(TAG, "startInput(): editor=" + attribute);
doStartInput(attribute, false);
}
public void restartInput(EditorInfo attribute) {
- doStartInput(attribute, false);
+ if (DEBUG) Log.v(TAG, "restartInput(): editor=" + attribute);
+ doStartInput(attribute, true);
}
/**
@@ -305,6 +315,7 @@ public class InputMethodService extends AbstractInputMethodService {
if (!isEnabled()) {
return;
}
+ if (DEBUG) Log.v(TAG, "finishInput() in " + this);
onFinishInput();
mInputStarted = false;
}
@@ -455,7 +466,7 @@ public class InputMethodService extends AbstractInputMethodService {
mIsInputViewShown = false;
mExtractFrame.setVisibility(View.GONE);
- mCandidatesFrame.setVisibility(View.GONE);
+ mCandidatesFrame.setVisibility(View.INVISIBLE);
mInputFrame.setVisibility(View.GONE);
}
@@ -469,6 +480,29 @@ public class InputMethodService extends AbstractInputMethodService {
}
/**
+ * Take care of handling configuration changes. Subclasses of
+ * InputMethodService generally don't need to deal directly with
+ * this on their own; the standard implementation here takes care of
+ * regenerating the input method UI as a result of the configuration
+ * change, so you can rely on your {@link #onCreateInputView} and
+ * other methods being called as appropriate due to a configuration change.
+ */
+ @Override public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ boolean visible = mWindowVisible;
+ boolean showingInput = mShowInputRequested;
+ boolean showingCandidates = mShowCandidatesRequested;
+ initViews();
+ if (visible) {
+ if (showingCandidates) {
+ setCandidatesViewShown(true);
+ }
+ showWindow(showingInput);
+ }
+ }
+
+ /**
* Implement to return our standard {@link InputMethodImpl}. Subclasses
* can override to provide their own customized version.
*/
@@ -493,6 +527,27 @@ public class InputMethodService extends AbstractInputMethodService {
}
/**
+ * Return the maximum width, in pixels, available the input method.
+ * Input methods are positioned at the bottom of the screen and, unless
+ * running in fullscreen, will generally want to be as short as possible
+ * so should compute their height based on their contents. However, they
+ * can stretch as much as needed horizontally. The function returns to
+ * you the maximum amount of space available horizontally, which you can
+ * use if needed for UI placement.
+ *
+ * <p>In many cases this is not needed, you can just rely on the normal
+ * view layout mechanisms to position your views within the full horizontal
+ * space given to the input method.
+ *
+ * <p>Note that this value can change dynamically, in particular when the
+ * screen orientation changes.
+ */
+ public int getMaxWidth() {
+ WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
+ return wm.getDefaultDisplay().getWidth();
+ }
+
+ /**
* Return the currently active InputBinding for the input method, or
* null if there is none.
*/
@@ -525,12 +580,19 @@ public class InputMethodService extends AbstractInputMethodService {
* is currently running in fullscreen mode.
*/
public void updateFullscreenMode() {
- boolean isFullscreen = onEvaluateFullscreenMode();
+ boolean isFullscreen = mShowInputRequested && onEvaluateFullscreenMode();
+ boolean changed = mLastShowInputRequested != mShowInputRequested;
if (mIsFullscreen != isFullscreen || !mFullscreenApplied) {
+ changed = true;
mIsFullscreen = isFullscreen;
mFullscreenApplied = true;
- mWindow.getWindow().setBackgroundDrawable(
- onCreateBackgroundDrawable());
+ Drawable bg = onCreateBackgroundDrawable();
+ if (bg == null) {
+ // We need to give the window a real drawable, so that it
+ // correctly sets its mode.
+ bg = getResources().getDrawable(android.R.color.transparent);
+ }
+ mWindow.getWindow().setBackgroundDrawable(bg);
mExtractFrame.setVisibility(isFullscreen ? View.VISIBLE : View.GONE);
if (isFullscreen) {
if (mExtractView == null) {
@@ -540,11 +602,39 @@ public class InputMethodService extends AbstractInputMethodService {
}
}
startExtractingText();
- mWindow.getWindow().setLayout(FILL_PARENT, FILL_PARENT);
- } else {
- mWindow.getWindow().setLayout(WRAP_CONTENT, WRAP_CONTENT);
}
}
+
+ if (changed) {
+ onConfigureWindow(mWindow.getWindow(), isFullscreen,
+ !mShowInputRequested);
+ mLastShowInputRequested = mShowInputRequested;
+ }
+ }
+
+ /**
+ * Update the given window's parameters for the given mode. This is called
+ * when the window is first displayed and each time the fullscreen or
+ * candidates only mode changes.
+ *
+ * <p>The default implementation makes the layout for the window
+ * FILL_PARENT x FILL_PARENT when in fullscreen mode, and
+ * FILL_PARENT x WRAP_CONTENT when in non-fullscreen mode.
+ *
+ * @param win The input method's window.
+ * @param isFullscreen If true, the window is running in fullscreen mode
+ * and intended to cover the entire application display.
+ * @param isCandidatesOnly If true, the window is only showing the
+ * candidates view and none of the rest of its UI. This is mutually
+ * exclusive with fullscreen mode.
+ */
+ public void onConfigureWindow(Window win, boolean isFullscreen,
+ boolean isCandidatesOnly) {
+ if (isFullscreen) {
+ mWindow.getWindow().setLayout(FILL_PARENT, FILL_PARENT);
+ } else {
+ mWindow.getWindow().setLayout(FILL_PARENT, WRAP_CONTENT);
+ }
}
/**
@@ -607,7 +697,7 @@ public class InputMethodService extends AbstractInputMethodService {
* is currently shown.
*/
public void updateInputViewShown() {
- boolean isShown = onEvaluateInputViewShown();
+ boolean isShown = mShowInputRequested && onEvaluateInputViewShown();
if (mIsInputViewShown != isShown && mWindowVisible) {
mIsInputViewShown = isShown;
mInputFrame.setVisibility(isShown ? View.VISIBLE : View.GONE);
@@ -650,18 +740,18 @@ public class InputMethodService extends AbstractInputMethodService {
public void setCandidatesViewShown(boolean shown) {
if (mShowCandidatesRequested != shown) {
mCandidatesFrame.setVisibility(shown ? View.VISIBLE : View.INVISIBLE);
- if (!mShowInputRequested) {
- // If we are being asked to show the candidates view while the app
- // has not asked for the input view to be shown, then we need
- // to update whether the window is shown.
- if (shown) {
- showWindow(false);
- } else {
- hideWindow();
- }
- }
mShowCandidatesRequested = shown;
}
+ if (!mShowInputRequested && mWindowVisible != shown) {
+ // If we are being asked to show the candidates view while the app
+ // has not asked for the input view to be shown, then we need
+ // to update whether the window is shown.
+ if (shown) {
+ showWindow(false);
+ } else {
+ hideWindow();
+ }
+ }
}
public void setStatusIcon(int iconResId) {
@@ -729,7 +819,7 @@ public class InputMethodService extends AbstractInputMethodService {
* Called by the framework to create a Drawable for the background of
* the input method window. May return null for no background. The default
* implementation returns a non-null standard background only when in
- * fullscreen mode.
+ * fullscreen mode. This is called each time the fullscreen mode changes.
*/
public Drawable onCreateBackgroundDrawable() {
if (isFullscreenMode()) {
@@ -789,22 +879,6 @@ public class InputMethodService extends AbstractInputMethodService {
public void onStartInputView(EditorInfo info, boolean restarting) {
}
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
-
- boolean visible = mWindowVisible;
- boolean showingInput = mShowInputRequested;
- boolean showingCandidates = mShowCandidatesRequested;
- initViews();
- if (visible) {
- if (showingCandidates) {
- setCandidatesViewShown(true);
- }
- showWindow(showingInput);
- }
- }
-
/**
* The system has decided that it may be time to show your input method.
* This is called due to a corresponding call to your
@@ -837,17 +911,17 @@ public class InputMethodService extends AbstractInputMethodService {
boolean wasVisible = mWindowVisible;
mWindowVisible = true;
if (!mShowInputRequested) {
- doShowInput = true;
- mShowInputRequested = true;
+ if (showInput) {
+ doShowInput = true;
+ mShowInputRequested = true;
+ }
} else {
showInput = true;
}
- if (doShowInput) {
- if (DEBUG) Log.v(TAG, "showWindow: updating UI");
- updateFullscreenMode();
- updateInputViewShown();
- }
+ if (DEBUG) Log.v(TAG, "showWindow: updating UI");
+ updateFullscreenMode();
+ updateInputViewShown();
if (!mWindowAdded || !mWindowCreated) {
mWindowAdded = true;
@@ -885,13 +959,44 @@ public class InputMethodService extends AbstractInputMethodService {
}
}
+ /**
+ * Called when a new client has bound to the input method. This
+ * may be followed by a series of {@link #onStartInput(EditorInfo, boolean)}
+ * and {@link #onFinishInput()} calls as the user navigates through its
+ * UI. Upon this call you know that {@link #getCurrentInputBinding}
+ * and {@link #getCurrentInputConnection} return valid objects.
+ */
public void onBindInput() {
}
+ /**
+ * Called when the previous bound client is no longer associated
+ * with the input method. After returning {@link #getCurrentInputBinding}
+ * and {@link #getCurrentInputConnection} will no longer return
+ * valid objects.
+ */
+ public void onUnbindInput() {
+ }
+
+ /**
+ * Called to inform the input method that text input has started in an
+ * editor. You should use this callback to initialize the state of your
+ * input to match the state of the editor given to it.
+ *
+ * @param attribute The attributes of the editor that input is starting
+ * in.
+ * @param restarting Set to true if input is restarting in the same
+ * editor such as because the application has changed the text in
+ * the editor. Otherwise will be false, indicating this is a new
+ * session with the editor.
+ */
public void onStartInput(EditorInfo attribute, boolean restarting) {
}
void doStartInput(EditorInfo attribute, boolean restarting) {
+ if (mInputStarted && !restarting) {
+ onFinishInput();
+ }
mInputStarted = true;
mInputEditorInfo = attribute;
onStartInput(attribute, restarting);
@@ -903,6 +1008,13 @@ public class InputMethodService extends AbstractInputMethodService {
}
}
+ /**
+ * Called to inform the input method that text input has finished in
+ * the last editor. At this point there may be a call to
+ * {@link #onStartInput(EditorInfo, boolean)} to perform input in a
+ * new editor, or the input method may be left idle. This method is
+ * <em>not</em> called when input restarts in the same editor.
+ */
public void onFinishInput() {
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 7b64405..a18f37c 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1740,12 +1740,12 @@ public final class Settings {
*/
public static final Uri CONTENT_URI =
Uri.parse("content://" + AUTHORITY + "/secure");
-
+
/**
* Whether ADB is enabled.
*/
public static final String ADB_ENABLED = "adb_enabled";
-
+
/**
* Setting to allow mock locations and location provider status to be injected into the
* LocationManager service for testing purposes during application development. These
@@ -1753,7 +1753,7 @@ public final class Settings {
* by network, gps, or other location providers.
*/
public static final String ALLOW_MOCK_LOCATION = "mock_location";
-
+
/**
* The Android ID (a unique 64-bit value) as a hex string.
* Identical to that obtained by calling
@@ -1761,24 +1761,40 @@ public final class Settings {
* so you can get it without binding to a service.
*/
public static final String ANDROID_ID = "android_id";
-
+
/**
* Whether bluetooth is enabled/disabled
* 0=disabled. 1=enabled.
*/
public static final String BLUETOOTH_ON = "bluetooth_on";
-
+
+ /**
+ * Get the key that retrieves a bluetooth headset's priority.
+ * @hide
+ */
+ public static final String getBluetoothHeadsetPriorityKey(String address) {
+ return ("bluetooth_headset_priority_" + address.toUpperCase());
+ }
+
+ /**
+ * Get the key that retrieves a bluetooth a2dp sink's priority.
+ * @hide
+ */
+ public static final String getBluetoothA2dpSinkPriorityKey(String address) {
+ return ("bluetooth_a2dp_sink_priority_" + address.toUpperCase());
+ }
+
/**
* Whether or not data roaming is enabled. (0 = false, 1 = true)
*/
public static final String DATA_ROAMING = "data_roaming";
-
+
/**
* Setting to record the input method used by default, holding the ID
* of the desired method.
*/
public static final String DEFAULT_INPUT_METHOD = "default_input_method";
-
+
/**
* Whether the device has been provisioned (0 = false, 1 = true)
*/
@@ -1953,7 +1969,13 @@ public final class Settings {
* Whether the Wi-Fi watchdog is enabled.
*/
public static final String WIFI_WATCHDOG_ON = "wifi_watchdog_on";
-
+
+ /**
+ * A comma-separated list of SSIDs for which the Wi-Fi watchdog should be enabled.
+ * @hide pending API council
+ */
+ public static final String WIFI_WATCHDOG_WATCH_LIST = "wifi_watchdog_watch_list";
+
/**
* The number of pings to test if an access point is a good connection.
*/
diff --git a/core/java/android/provider/UserDictionary.java b/core/java/android/provider/UserDictionary.java
new file mode 100644
index 0000000..58e5731
--- /dev/null
+++ b/core/java/android/provider/UserDictionary.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2008 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.provider;
+
+import java.util.Locale;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.net.Uri;
+import android.text.TextUtils;
+
+/**
+ *
+ * @hide Pending API council approval
+ */
+public class UserDictionary {
+ public static final String AUTHORITY = "user_dictionary";
+
+ /**
+ * The content:// style URL for this provider
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://" + AUTHORITY);
+
+ /**
+ * Contains the user defined words.
+ * @hide Pending API council approval
+ */
+ public static class Words implements BaseColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://" + AUTHORITY + "/words");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of words.
+ */
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.userword";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} sub-directory of a single word.
+ */
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.google.userword";
+
+ public static final String _ID = BaseColumns._ID;
+
+ /**
+ * The word column.
+ * <p>TYPE: TEXT</p>
+ */
+ public static final String WORD = "word";
+
+ /**
+ * The frequency column. A value between 1 and 255.
+ * <p>TYPE: INTEGER</p>
+ */
+ public static final String FREQUENCY = "frequency";
+
+ /**
+ * The locale that this word belongs to. Null if it pertains to all
+ * locales. Locale is a 5 letter string such as <pre>en_US</pre>.
+ * <p>TYPE: TEXT</p>
+ */
+ public static final String LOCALE = "locale";
+
+ /**
+ * The uid of the application that inserted the word.
+ * <p>TYPE: INTEGER</p>
+ */
+ public static final String APP_ID = "appid";
+
+ public static final int LOCALE_TYPE_ALL = 0;
+
+ public static final int LOCALE_TYPE_CURRENT = 1;
+
+ /**
+ * Sort by descending order of frequency.
+ */
+ public static final String DEFAULT_SORT_ORDER = FREQUENCY + " DESC";
+
+
+ public static void addWord(Context context, String word,
+ int frequency, int localeType) {
+ final ContentResolver resolver = context.getContentResolver();
+
+ if (TextUtils.isEmpty(word) || localeType < 0 || localeType > 1) {
+ return;
+ }
+
+ if (frequency < 0) frequency = 0;
+ if (frequency > 255) frequency = 255;
+
+ String locale = null;
+
+ // TODO: Verify if this is the best way to get the current locale
+ if (localeType == LOCALE_TYPE_CURRENT) {
+ locale = Locale.getDefault().toString();
+ }
+ ContentValues values = new ContentValues(4);
+
+ values.put(WORD, word);
+ values.put(FREQUENCY, frequency);
+ values.put(LOCALE, locale);
+ values.put(APP_ID, 0); // TODO: Get App UID
+
+ Uri result = resolver.insert(CONTENT_URI, values);
+ // It's ok if the insert doesn't succeed because the word
+ // already exists.
+ }
+ }
+}
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index 90ef8f6..be784ff 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -35,6 +35,7 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.os.Binder;
+import android.provider.Settings;
import android.util.Log;
import java.io.FileDescriptor;
@@ -83,6 +84,8 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
mIntentFilter = new IntentFilter(BluetoothIntent.ENABLED_ACTION);
mIntentFilter.addAction(BluetoothIntent.DISABLED_ACTION);
+ mIntentFilter.addAction(BluetoothIntent.BONDING_CREATED_ACTION);
+ mIntentFilter.addAction(BluetoothIntent.BONDING_REMOVED_ACTION);
mContext.registerReceiver(mReceiver, mIntentFilter);
if (device.isEnabled()) {
@@ -103,10 +106,15 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
+ String address = intent.getStringExtra(BluetoothIntent.ADDRESS);
if (action.equals(BluetoothIntent.ENABLED_ACTION)) {
onBluetoothEnable();
} else if (action.equals(BluetoothIntent.DISABLED_ACTION)) {
onBluetoothDisable();
+ } else if (action.equals(BluetoothIntent.BONDING_CREATED_ACTION)) {
+ setSinkPriority(address, BluetoothA2dp.PRIORITY_AUTO);
+ } else if (action.equals(BluetoothIntent.BONDING_REMOVED_ACTION)) {
+ setSinkPriority(address, BluetoothA2dp.PRIORITY_OFF);
}
}
};
@@ -145,7 +153,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
if (path == null) {
return BluetoothError.ERROR;
}
-
+
SinkState sink = mAudioDevices.get(path);
int state = BluetoothA2dp.STATE_DISCONNECTED;
if (sink != null) {
@@ -159,8 +167,8 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
case BluetoothA2dp.STATE_CONNECTING:
return BluetoothError.SUCCESS;
}
-
- // State is DISCONNECTED
+
+ // State is DISCONNECTED
if (!connectSinkNative(path)) {
return BluetoothError.ERROR;
}
@@ -189,7 +197,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
return BluetoothError.SUCCESS;
}
- // State is CONNECTING or CONNECTED or PLAYING
+ // State is CONNECTING or CONNECTED or PLAYING
if (!disconnectSinkNative(path)) {
return BluetoothError.ERROR;
} else {
@@ -229,16 +237,37 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
return BluetoothA2dp.STATE_DISCONNECTED;
}
- public synchronized void onHeadsetCreated(String path) {
+ public synchronized int getSinkPriority(String address) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ if (!BluetoothDevice.checkBluetoothAddress(address)) {
+ return BluetoothError.ERROR;
+ }
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.getBluetoothA2dpSinkPriorityKey(address),
+ BluetoothA2dp.PRIORITY_OFF);
+ }
+
+ public synchronized int setSinkPriority(String address, int priority) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ if (!BluetoothDevice.checkBluetoothAddress(address)) {
+ return BluetoothError.ERROR;
+ }
+ return Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.getBluetoothA2dpSinkPriorityKey(address), priority) ?
+ BluetoothError.SUCCESS : BluetoothError.ERROR;
+ }
+
+ private synchronized void onHeadsetCreated(String path) {
updateState(path, BluetoothA2dp.STATE_DISCONNECTED);
}
- public synchronized void onHeadsetRemoved(String path) {
+ private synchronized void onHeadsetRemoved(String path) {
if (mAudioDevices == null) return;
mAudioDevices.remove(path);
}
- public synchronized void onSinkConnected(String path) {
+ private synchronized void onSinkConnected(String path) {
if (mAudioDevices == null) return;
// bluez 3.36 quietly disconnects the previous sink when a new sink
// is connected, so we need to mark all previously connected sinks as
@@ -258,16 +287,16 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
updateState(path, BluetoothA2dp.STATE_CONNECTED);
}
- public synchronized void onSinkDisconnected(String path) {
+ private synchronized void onSinkDisconnected(String path) {
mAudioManager.setBluetoothA2dpOn(false);
updateState(path, BluetoothA2dp.STATE_DISCONNECTED);
}
- public synchronized void onSinkPlaying(String path) {
+ private synchronized void onSinkPlaying(String path) {
updateState(path, BluetoothA2dp.STATE_PLAYING);
}
- public synchronized void onSinkStopped(String path) {
+ private synchronized void onSinkStopped(String path) {
updateState(path, BluetoothA2dp.STATE_CONNECTED);
}
@@ -307,7 +336,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
if (state != prevState) {
if (DBG) log("state " + address + " (" + path + ") " + prevState + "->" + state);
-
+
Intent intent = new Intent(BluetoothA2dp.SINK_STATE_CHANGED_ACTION);
intent.putExtra(BluetoothIntent.ADDRESS, address);
intent.putExtra(BluetoothA2dp.SINK_PREVIOUS_STATE, prevState);
@@ -339,5 +368,4 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
private synchronized native boolean connectSinkNative(String path);
private synchronized native boolean disconnectSinkNative(String path);
private synchronized native boolean isSinkConnectedNative(String path);
-
}
diff --git a/core/java/android/speech/srec/Recognizer.java b/core/java/android/speech/srec/Recognizer.java
index 749c923..a03a36a 100644
--- a/core/java/android/speech/srec/Recognizer.java
+++ b/core/java/android/speech/srec/Recognizer.java
@@ -367,6 +367,35 @@ public final class Recognizer {
SR_RecognizerStop(mRecognizer);
SR_RecognizerDeactivateRule(mRecognizer, mActiveGrammar.mGrammar, "trash");
}
+
+ /**
+ * Reset the acoustic state vectorto it's default value.
+ *
+ * @hide
+ */
+ public void resetAcousticState() {
+ SR_AcousticStateReset(mRecognizer);
+ }
+
+ /**
+ * Set the acoustic state vector.
+ * @param state String containing the acoustic state vector.
+ *
+ * @hide
+ */
+ public void setAcousticState(String state) {
+ SR_AcousticStateSet(mRecognizer, state);
+ }
+
+ /**
+ * Get the acoustic state vector.
+ * @return String containing the acoustic state vector.
+ *
+ * @hide
+ */
+ public String getAcousticState() {
+ return SR_AcousticStateGet(mRecognizer);
+ }
/**
* Clean up resources.
@@ -572,6 +601,9 @@ public final class Recognizer {
return "EVENT_" + event;
}
+ //
+ // SR_Recognizer methods
+ //
private static native void SR_RecognizerStart(int recognizer);
private static native void SR_RecognizerStop(int recognizer);
private static native int SR_RecognizerCreate();
@@ -615,6 +647,14 @@ public final class Recognizer {
private static native boolean SR_RecognizerIsSignalTooFewSamples(int recognizer);
private static native boolean SR_RecognizerIsSignalTooManySamples(int recognizer);
// private static native void SR_Recognizer_Change_Sample_Rate (size_t new_sample_rate);
+
+
+ //
+ // SR_AcousticState native methods
+ //
+ private static native void SR_AcousticStateReset(int recognizer);
+ private static native void SR_AcousticStateSet(int recognizer, String state);
+ private static native String SR_AcousticStateGet(int recognizer);
//
diff --git a/core/java/android/speech/srec/WaveHeader.java b/core/java/android/speech/srec/WaveHeader.java
index 0aa3cc2..a99496d 100644
--- a/core/java/android/speech/srec/WaveHeader.java
+++ b/core/java/android/speech/srec/WaveHeader.java
@@ -263,5 +263,12 @@ public class WaveHeader {
out.write(val >> 0);
out.write(val >> 8);
}
+
+ @Override
+ public String toString() {
+ return String.format(
+ "WaveHeader format=%d numChannels=%d sampleRate=%d bitsPerSample=%d numBytes=%d",
+ mFormat, mNumChannels, mSampleRate, mBitsPerSample, mNumBytes);
+ }
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 9d7a124..9e0289a 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -117,6 +117,7 @@ public final class ViewRoot extends Handler implements ViewParent,
View mView;
View mFocusedView;
+ View mRealFocusedView; // this is not set to null in touch mode
int mViewVisibility;
boolean mAppVisible = true;
@@ -971,9 +972,19 @@ public final class ViewRoot extends Handler implements ViewParent,
if (mFirst) {
// handle first focus request
- if (mView != null && !mView.hasFocus()) {
- mView.requestFocus(View.FOCUS_FORWARD);
- mFocusedView = mView.findFocus();
+ if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: mView.hasFocus()="
+ + mView.hasFocus());
+ if (mView != null) {
+ if (!mView.hasFocus()) {
+ mView.requestFocus(View.FOCUS_FORWARD);
+ mFocusedView = mRealFocusedView = mView.findFocus();
+ if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: requested focused view="
+ + mFocusedView);
+ } else {
+ mRealFocusedView = mView.findFocus();
+ if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: existing focused view="
+ + mRealFocusedView);
+ }
}
}
@@ -1214,13 +1225,16 @@ public final class ViewRoot extends Handler implements ViewParent,
// requestChildRectangleOnScreen() call (in which case 'rectangle'
// is non-null and we just want to scroll to whatever that
// rectangle is).
- View focus = mFocusedView;
+ View focus = mRealFocusedView;
if (focus != mLastScrolledFocus) {
// If the focus has changed, then ignore any requests to scroll
// to a rectangle; first we want to make sure the entire focus
// view is visible.
rectangle = null;
}
+ if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Eval scroll: focus=" + focus
+ + " rectangle=" + rectangle + " ci=" + ci
+ + " vi=" + vi);
if (focus == mLastScrolledFocus && !mScrollMayChange
&& rectangle == null) {
// Optimization: if the focus hasn't changed since last
@@ -1234,6 +1248,7 @@ public final class ViewRoot extends Handler implements ViewParent,
// a pan so it can be seen.
mLastScrolledFocus = focus;
mScrollMayChange = false;
+ if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Need to scroll?");
// Try to find the rectangle from the focus view.
if (focus.getGlobalVisibleRect(mVisRect, null)) {
if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Root w="
@@ -1307,7 +1322,9 @@ public final class ViewRoot extends Handler implements ViewParent,
mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(mFocusedView, focused);
scheduleTraversals();
}
- mFocusedView = focused;
+ mFocusedView = mRealFocusedView = focused;
+ if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Request child focus: focus now "
+ + mFocusedView);
}
public void clearChildFocus(View child) {
@@ -1315,7 +1332,8 @@ public final class ViewRoot extends Handler implements ViewParent,
View oldFocus = mFocusedView;
- mFocusedView = null;
+ if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Clearing child focus");
+ mFocusedView = mRealFocusedView = null;
if (mView != null && !mView.hasFocus()) {
// If a view gets the focus, the listener will be invoked from requestChildFocus()
if (!mView.requestFocus(View.FOCUS_FORWARD)) {
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index a676234..ba40782 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -800,7 +800,7 @@ public final class InputMethodManager {
try {
if (DEBUG) Log.v(TAG, "START INPUT: " + view + " ic="
- + ic + " tba=" + tba);
+ + ic + " tba=" + tba + " initial=" + initial);
InputBindResult res = mService.startInput(mClient, tba, initial,
mCurMethod == null);
if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);
@@ -848,6 +848,9 @@ public final class InputMethodManager {
synchronized (mH) {
if (DEBUG) Log.v(TAG, "focusIn: " + view);
// Okay we have a new view that is being served.
+ if (mServedView != view) {
+ mCurrentTextBoxAttribute = null;
+ }
mServedView = view;
mCompletions = null;
mServedConnecting = true;
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index cae94c9..4f8e5e4 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -16,8 +16,10 @@
package android.webkit;
+import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
@@ -30,7 +32,14 @@ import android.os.SystemClock;
import android.util.Config;
import android.util.Log;
import android.view.KeyEvent;
-
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.TextView;
+import com.android.internal.R;
+
+import java.net.MalformedURLException;
+import java.net.URL;
import java.util.HashMap;
/**
@@ -376,12 +385,24 @@ class CallbackProxy extends Handler {
case JS_ALERT:
if (mWebChromeClient != null) {
- JsResult res = (JsResult) msg.obj;
+ final JsResult res = (JsResult) msg.obj;
String message = msg.getData().getString("message");
String url = msg.getData().getString("url");
if (!mWebChromeClient.onJsAlert(mWebView, url, message,
- res)) {
- res.handleDefault();
+ res)) {
+ new AlertDialog.Builder(mContext)
+ .setTitle(getJsDialogTitle(url))
+ .setMessage(message)
+ .setPositiveButton(R.string.ok,
+ new AlertDialog.OnClickListener() {
+ public void onClick(
+ DialogInterface dialog,
+ int which) {
+ res.confirm();
+ }
+ })
+ .setCancelable(false)
+ .show();
}
res.setReady();
}
@@ -389,12 +410,29 @@ class CallbackProxy extends Handler {
case JS_CONFIRM:
if (mWebChromeClient != null) {
- JsResult res = (JsResult) msg.obj;
+ final JsResult res = (JsResult) msg.obj;
String message = msg.getData().getString("message");
String url = msg.getData().getString("url");
if (!mWebChromeClient.onJsConfirm(mWebView, url, message,
- res)) {
- res.handleDefault();
+ res)) {
+ new AlertDialog.Builder(mContext)
+ .setTitle(getJsDialogTitle(url))
+ .setMessage(message)
+ .setPositiveButton(R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(
+ DialogInterface dialog,
+ int which) {
+ res.confirm();
+ }})
+ .setNegativeButton(R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(
+ DialogInterface dialog,
+ int which) {
+ res.cancel();
+ }})
+ .show();
}
// Tell the JsResult that it is ready for client
// interaction.
@@ -404,13 +442,49 @@ class CallbackProxy extends Handler {
case JS_PROMPT:
if (mWebChromeClient != null) {
- JsPromptResult res = (JsPromptResult) msg.obj;
+ final JsPromptResult res = (JsPromptResult) msg.obj;
String message = msg.getData().getString("message");
String defaultVal = msg.getData().getString("default");
String url = msg.getData().getString("url");
if (!mWebChromeClient.onJsPrompt(mWebView, url, message,
defaultVal, res)) {
- res.handleDefault();
+ final LayoutInflater factory = LayoutInflater
+ .from(mContext);
+ final View view = factory.inflate(R.layout.js_prompt,
+ null);
+ final EditText v = (EditText) view
+ .findViewById(R.id.value);
+ v.setText(defaultVal);
+ ((TextView) view.findViewById(R.id.message))
+ .setText(message);
+ new AlertDialog.Builder(mContext)
+ .setTitle(getJsDialogTitle(url))
+ .setView(view)
+ .setPositiveButton(R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(
+ DialogInterface dialog,
+ int whichButton) {
+ res.confirm(v.getText()
+ .toString());
+ }
+ })
+ .setNegativeButton(R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(
+ DialogInterface dialog,
+ int whichButton) {
+ res.cancel();
+ }
+ })
+ .setOnCancelListener(
+ new DialogInterface.OnCancelListener() {
+ public void onCancel(
+ DialogInterface dialog) {
+ res.cancel();
+ }
+ })
+ .show();
}
// Tell the JsResult that it is ready for client
// interaction.
@@ -420,12 +494,32 @@ class CallbackProxy extends Handler {
case JS_UNLOAD:
if (mWebChromeClient != null) {
- JsResult res = (JsResult) msg.obj;
+ final JsResult res = (JsResult) msg.obj;
String message = msg.getData().getString("message");
String url = msg.getData().getString("url");
if (!mWebChromeClient.onJsBeforeUnload(mWebView, url,
- message, res)) {
- res.handleDefault();
+ message, res)) {
+ final String m = mContext.getString(
+ R.string.js_dialog_before_unload, message);
+ new AlertDialog.Builder(mContext)
+ .setMessage(m)
+ .setPositiveButton(R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(
+ DialogInterface dialog,
+ int which) {
+ res.confirm();
+ }
+ })
+ .setNegativeButton(R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(
+ DialogInterface dialog,
+ int which) {
+ res.cancel();
+ }
+ })
+ .show();
}
res.setReady();
}
@@ -468,6 +562,24 @@ class CallbackProxy extends Handler {
sendMessage(obtainMessage(SWITCH_OUT_HISTORY));
}
+ private String getJsDialogTitle(String url) {
+ String title = url;
+ if (URLUtil.isDataUrl(url)) {
+ // For data: urls, we just display 'JavaScript' similar to Safari.
+ title = mContext.getString(R.string.js_dialog_title_default);
+ } else {
+ try {
+ URL aUrl = new URL(url);
+ // For example: "The page at 'http://www.mit.edu' says:"
+ title = mContext.getString(R.string.js_dialog_title,
+ aUrl.getProtocol() + "://" + aUrl.getHost());
+ } catch (MalformedURLException ex) {
+ // do nothing. just use the url as the title
+ }
+ }
+ return title;
+ }
+
//--------------------------------------------------------------------------
// WebViewClient functions.
// NOTE: shouldOverrideKeyEvent is never called from the WebCore thread so
diff --git a/core/java/android/webkit/TextDialog.java b/core/java/android/webkit/TextDialog.java
index 30b519a..b7b40b1 100644
--- a/core/java/android/webkit/TextDialog.java
+++ b/core/java/android/webkit/TextDialog.java
@@ -38,13 +38,20 @@ import android.text.method.MovementMethod;
import android.text.method.PasswordTransformationMethod;
import android.text.method.TextKeyListener;
import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
import android.view.View.MeasureSpec;
import android.view.ViewConfiguration;
import android.widget.AbsoluteLayout.LayoutParams;
+import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
/**
* TextDialog is a specialized version of EditText used by WebView
@@ -281,7 +288,7 @@ import android.widget.AutoCompleteTextView;
}
return false;
}
-
+
/**
* Determine whether this TextDialog currently represents the node
* represented by ptr.
@@ -406,6 +413,9 @@ import android.widget.AutoCompleteTextView;
* focus to the host.
*/
/* package */ void remove() {
+ // hide the soft keyboard when the edit text is out of focus
+ InputMethodManager.getInstance(mContext).hideSoftInputFromWindow(
+ getWindowToken(), 0);
mHandler.removeMessages(LONGPRESS);
mWebView.removeView(this);
mWebView.requestFocus();
@@ -427,6 +437,43 @@ import android.widget.AutoCompleteTextView;
mWebView.passToJavaScript(getText().toString(), event);
}
+ public void setAdapterCustom(AutoCompleteAdapter adapter) {
+ adapter.setTextView(this);
+ super.setAdapter(adapter);
+ }
+
+ /**
+ * This is a special version of ArrayAdapter which changes its text size
+ * to match the text size of its host TextView.
+ */
+ public static class AutoCompleteAdapter extends ArrayAdapter<String> {
+ private TextView mTextView;
+
+ public AutoCompleteAdapter(Context context, ArrayList<String> entries) {
+ super(context, com.android.internal.R.layout
+ .search_dropdown_item_1line, entries);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public View getView(int position, View convertView, ViewGroup parent) {
+ TextView tv =
+ (TextView) super.getView(position, convertView, parent);
+ if (tv != null && mTextView != null) {
+ tv.setTextSize(mTextView.getTextSize());
+ }
+ return tv;
+ }
+
+ /**
+ * Set the TextView so we can match its text size.
+ */
+ private void setTextView(TextView tv) {
+ mTextView = tv;
+ }
+ }
+
/**
* Determine whether to use the system-wide password disguising method,
* or to use none.
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index f00238d..9cfc622 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -57,6 +57,7 @@ import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.view.inputmethod.InputMethodManager;
+import android.webkit.TextDialog.AutoCompleteAdapter;
import android.webkit.WebViewCore.EventHub;
import android.widget.AbsoluteLayout;
import android.widget.AdapterView;
@@ -2819,10 +2820,8 @@ public class WebView extends AbsoluteLayout
public void run() {
ArrayList<String> pastEntries = mDatabase.getFormData(mUrl, mName);
if (pastEntries.size() > 0) {
- ArrayAdapter<String> adapter = new ArrayAdapter<String>(
- mContext, com.android.internal.R.layout
- .search_dropdown_item_1line,
- pastEntries);
+ AutoCompleteAdapter adapter = new
+ AutoCompleteAdapter(mContext, pastEntries);
((HashMap) mUpdateMessage.obj).put("adapter", adapter);
mUpdateMessage.sendToTarget();
}
@@ -4458,9 +4457,9 @@ public class WebView extends AbsoluteLayout
case UPDATE_TEXT_ENTRY_ADAPTER:
HashMap data = (HashMap) msg.obj;
if (mTextEntry.isSameTextField(msg.arg1)) {
- ArrayAdapter<String> adapter =
- (ArrayAdapter<String>) data.get("adapter");
- mTextEntry.setAdapter(adapter);
+ AutoCompleteAdapter adapter =
+ (AutoCompleteAdapter) data.get("adapter");
+ mTextEntry.setAdapterCustom(adapter);
}
break;
case UPDATE_CLIPBOARD:
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 024b663..7d52901 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -413,7 +413,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
// when the selection is at the bottom, we block the
// event to avoid going to the next focusable widget
Adapter adapter = mDropDownList.getAdapter();
- if (curIndex == adapter.getCount() - 1) {
+ if (adapter != null && curIndex == adapter.getCount() - 1) {
return true;
}
}
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index 6c0c164..f2cec92 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -393,6 +393,12 @@ public class MediaController extends FrameLayout {
doPauseResume();
show(sDefaultTimeout);
return true;
+ } else if (keyCode == KeyEvent.KEYCODE_STOP) {
+ if (mPlayer.isPlaying()) {
+ mPlayer.pause();
+ updatePausePlay();
+ }
+ return true;
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
// don't show the controls for volume adjustment
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index df40156..1227afd 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -447,7 +447,8 @@ public class VideoView extends SurfaceView implements MediaPlayerControl {
keyCode != KeyEvent.KEYCODE_ENDCALL &&
mMediaPlayer != null &&
mMediaController != null) {
- if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK) {
+ if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK ||
+ keyCode == KeyEvent.KEYCODE_PLAYPAUSE) {
if (mMediaPlayer.isPlaying()) {
pause();
mMediaController.show();
@@ -456,6 +457,10 @@ public class VideoView extends SurfaceView implements MediaPlayerControl {
mMediaController.hide();
}
return true;
+ } else if (keyCode == KeyEvent.KEYCODE_STOP
+ && mMediaPlayer.isPlaying()) {
+ pause();
+ mMediaController.show();
} else {
toggleMediaControlsVisiblity();
}
diff --git a/core/java/com/android/internal/gadget/IGadgetService.aidl b/core/java/com/android/internal/gadget/IGadgetService.aidl
new file mode 100644
index 0000000..0117d1d
--- /dev/null
+++ b/core/java/com/android/internal/gadget/IGadgetService.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2008 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 com.android.internal.gadget;
+
+import android.content.ComponentName;
+import android.gadget.GadgetInfo;
+
+/** {@hide} */
+interface IGadgetService {
+ int allocateGadgetId(String hostPackage);
+ void deleteGadgetId(int gadgetId);
+ void bindGadgetId(int gadgetId, in ComponentName provider);
+ GadgetInfo getGadgetInfo(int gadgetId);
+}
diff --git a/core/java/com/android/internal/gadget/package.html b/core/java/com/android/internal/gadget/package.html
new file mode 100644
index 0000000..db6f78b
--- /dev/null
+++ b/core/java/com/android/internal/gadget/package.html
@@ -0,0 +1,3 @@
+<body>
+{@hide}
+</body> \ No newline at end of file
diff --git a/core/java/com/android/internal/os/HandlerCaller.java b/core/java/com/android/internal/os/HandlerCaller.java
index a7081e3..1ec74a1 100644
--- a/core/java/com/android/internal/os/HandlerCaller.java
+++ b/core/java/com/android/internal/os/HandlerCaller.java
@@ -116,7 +116,7 @@ public class HandlerCaller {
}
public Message obtainMessageI(int what, int arg1) {
- return mH.obtainMessage(what, arg1);
+ return mH.obtainMessage(what, arg1, 0);
}
public Message obtainMessageIO(int what, int arg1, Object arg2) {
diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java
index 3b11a64..558a4c3 100644
--- a/core/java/com/android/internal/view/menu/IconMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java
@@ -143,7 +143,7 @@ public final class IconMenuItemView extends TextView implements MenuView.ItemVie
void setCaptionMode(boolean shortcut) {
- mShortcutCaptionMode = shortcut;
+ mShortcutCaptionMode = shortcut && (mItemData.shouldShowShortcut());
/*
* If there is no item model, don't do any of the below (for example,
@@ -155,7 +155,7 @@ public final class IconMenuItemView extends TextView implements MenuView.ItemVie
CharSequence text = mItemData.getTitleForItemView(this);
- if (shortcut) {
+ if (mShortcutCaptionMode) {
if (mShortcutCaption == null) {
mShortcutCaption = mItemData.getShortcutLabel();
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
index e5d57ad..32513cd 100644
--- a/core/java/com/android/internal/view/menu/ListMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java
@@ -171,9 +171,13 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView
}
public void setShortcut(boolean showShortcut, char shortcutKey) {
- mShortcutView.setText(mItemData.getShortcutLabel());
+ final int newVisibility = (showShortcut && mItemData.shouldShowShortcut())
+ ? VISIBLE : GONE;
+
+ if (newVisibility == VISIBLE) {
+ mShortcutView.setText(mItemData.getShortcutLabel());
+ }
- final int newVisibility = showShortcut ? VISIBLE : GONE;
if (mShortcutView.getVisibility() != newVisibility) {
mShortcutView.setVisibility(newVisibility);
}
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index 2987602..cbc4e9f 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
@@ -279,7 +280,8 @@ public class MenuBuilder implements Menu {
mVisibleItems = new ArrayList<MenuItemImpl>();
mIsVisibleItemsStale = true;
- mShortcutsVisible = true;
+ mShortcutsVisible =
+ (mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS);
}
public void setCallback(Callback callback) {
@@ -687,7 +689,8 @@ public class MenuBuilder implements Menu {
}
/**
- * Sets whether the shortcuts should be visible on menus.
+ * Sets whether the shortcuts should be visible on menus. Devices without hardware
+ * key input will never make shortcuts visible even if this method is passed 'true'.
*
* @param shortcutsVisible Whether shortcuts should be visible (if true and a
* menu item does not have a shortcut defined, that item will
@@ -696,9 +699,11 @@ public class MenuBuilder implements Menu {
public void setShortcutsVisible(boolean shortcutsVisible) {
if (mShortcutsVisible == shortcutsVisible) return;
- mShortcutsVisible = shortcutsVisible;
+ mShortcutsVisible =
+ (mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS)
+ && shortcutsVisible;
- refreshShortcuts(shortcutsVisible, isQwertyMode());
+ refreshShortcuts(mShortcutsVisible, isQwertyMode());
}
/**
diff --git a/core/java/com/android/internal/widget/NumberPicker.java b/core/java/com/android/internal/widget/NumberPicker.java
index 5590f1a..20ea6a6 100644
--- a/core/java/com/android/internal/widget/NumberPicker.java
+++ b/core/java/com/android/internal/widget/NumberPicker.java
@@ -131,6 +131,7 @@ public class NumberPicker extends LinearLayout implements OnClickListener,
mText = (TextView) findViewById(R.id.timepicker_input);
mText.setOnFocusChangeListener(this);
mText.setFilters(new InputFilter[] { mInputFilter });
+ mText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
mSlideUpOutAnimation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF,