Merge change Ic532c956 into eclair-mr2
* changes:
Note to self: Don't reverse the arguments to fseek(o)...
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 30e1712..c4e1877 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -287,6 +287,14 @@
* {@link #onStart} and returns either {@link #START_STICKY}
* or {@link #START_STICKY_COMPATIBILITY}.
*
+ * <p>If you need your application to run on platform versions prior to API
+ * level 5, you can use the following model to handle the older {@link #onStart}
+ * callback in that case. The <code>handleCommand</code> method is implemented by
+ * you as appropriate:
+ *
+ * <pre>{@include development/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java
+ * start_compatibility}</pre>
+ *
* @param intent The Intent supplied to {@link android.content.Context#startService},
* as given. This may be null if the service is being restarted after
* its process has gone away, and it had previously returned anything
@@ -462,6 +470,13 @@
* if your service is performing background music playback, so the user
* would notice if their music stopped playing.
*
+ * <p>If you need your application to run on platform versions prior to API
+ * level 5, you can use the following model to call the the older {@link #setForeground}
+ * or this modern method as appropriate:
+ *
+ * <pre>{@include development/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java
+ * foreground_compatibility}</pre>
+ *
* @param id The identifier for this notification as per
* {@link NotificationManager#notify(int, Notification)
* NotificationManager.notify(int, Notification)}.
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 7df3637..fda9b81 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -199,6 +199,22 @@
}
}
+ /** Check if any A2DP sink is in Non Disconnected state
+ * i.e playing, connected, connecting, disconnecting.
+ * @return a unmodifiable set of connected A2DP sinks, or null on error.
+ * @hide
+ */
+ public Set<BluetoothDevice> getNonDisconnectedSinks() {
+ if (DBG) log("getNonDisconnectedSinks()");
+ try {
+ return Collections.unmodifiableSet(
+ new HashSet<BluetoothDevice>(Arrays.asList(mService.getNonDisconnectedSinks())));
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ return null;
+ }
+ }
+
/** Get the state of an A2DP sink
* @param device Remote BT device.
* @return State code, one of STATE_
diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl
index 002cf4e..168fe3b 100644
--- a/core/java/android/bluetooth/IBluetoothA2dp.aidl
+++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl
@@ -29,6 +29,7 @@
boolean suspendSink(in BluetoothDevice device);
boolean resumeSink(in BluetoothDevice device);
BluetoothDevice[] getConnectedSinks(); // change to Set<> once AIDL supports
+ BluetoothDevice[] getNonDisconnectedSinks(); // change to Set<> once AIDL supports
int getSinkState(in BluetoothDevice device);
boolean setSinkPriority(in BluetoothDevice device, int priority);
int getSinkPriority(in BluetoothDevice device);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index d77a6ca..3344158 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1142,7 +1142,6 @@
* Use with {@link #getSystemService} to retrieve a
* {@link android.accounts.AccountManager} for receiving intents at a
* time of your choosing.
- * TODO STOPSHIP perform a final review of the the account apis before shipping
*
* @see #getSystemService
* @see android.accounts.AccountManager
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 8d69814..a96e896 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -540,10 +540,33 @@
* {@link #putExtra}.
*
* <ul>
- * <li> {@link #EXTRA_TEMPLATE}
+ * <li> {@link #EXTRA_ALARM_COUNT}
+ * <li> {@link #EXTRA_BCC}
+ * <li> {@link #EXTRA_CC}
+ * <li> {@link #EXTRA_CHANGED_COMPONENT_NAME}
+ * <li> {@link #EXTRA_DATA_REMOVED}
+ * <li> {@link #EXTRA_DOCK_STATE}
+ * <li> {@link #EXTRA_DOCK_STATE_CAR}
+ * <li> {@link #EXTRA_DOCK_STATE_DESK}
+ * <li> {@link #EXTRA_DOCK_STATE_UNDOCKED}
+ * <li> {@link #EXTRA_DONT_KILL_APP}
+ * <li> {@link #EXTRA_EMAIL}
+ * <li> {@link #EXTRA_INITIAL_INTENTS}
* <li> {@link #EXTRA_INTENT}
+ * <li> {@link #EXTRA_KEY_EVENT}
+ * <li> {@link #EXTRA_PHONE_NUMBER}
+ * <li> {@link #EXTRA_REMOTE_INTENT_TOKEN}
+ * <li> {@link #EXTRA_REPLACING}
+ * <li> {@link #EXTRA_SHORTCUT_ICON}
+ * <li> {@link #EXTRA_SHORTCUT_ICON_RESOURCE}
+ * <li> {@link #EXTRA_SHORTCUT_INTENT}
* <li> {@link #EXTRA_STREAM}
+ * <li> {@link #EXTRA_SHORTCUT_NAME}
+ * <li> {@link #EXTRA_SUBJECT}
+ * <li> {@link #EXTRA_TEMPLATE}
* <li> {@link #EXTRA_TEXT}
+ * <li> {@link #EXTRA_TITLE}
+ * <li> {@link #EXTRA_UID}
* </ul>
*
* <h3>Flags</h3>
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index d9003a3..657bbcc 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -827,15 +827,6 @@
}
private void closeClosable() {
- /* deallocate all compiled sql statement objects in compiledQueries cache.
- * this should be done before de-referencing all {@link SQLiteClosable} objects
- * from this database object because calling
- * {@link SQLiteClosable#onAllReferencesReleasedFromContainer()} could cause the database
- * to be closed. sqlite doesn't let a database close if there are
- * any unfinalized statements - such as the compiled-sql objects in mCompiledQueries.
- */
- resetCompiledSqlCache();
-
Iterator<Map.Entry<SQLiteClosable, Object>> iter = mPrograms.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<SQLiteClosable, Object> entry = iter.next();
@@ -844,6 +835,13 @@
program.onAllReferencesReleasedFromContainer();
}
}
+
+ // finalize all compiled sql statement objects in compiledQueries cache
+ synchronized (mCompiledQueries) {
+ for (SQLiteCompiledSql compiledStatement : mCompiledQueries.values()) {
+ compiledStatement.releaseSqlStatement();
+ }
+ }
}
/**
@@ -1791,9 +1789,7 @@
*/
public void setMaxSqlCacheSize(int cacheSize) {
synchronized(mCompiledQueries) {
- if (mMaxSqlCacheSize > 0) {
- resetCompiledSqlCache();
- }
+ resetCompiledSqlCache();
mMaxSqlCacheSize = (cacheSize > MAX_SQL_CACHE_SIZE) ? MAX_SQL_CACHE_SIZE
: (cacheSize < 0) ? 0 : cacheSize;
}
@@ -1804,9 +1800,6 @@
*/
public void resetCompiledSqlCache() {
synchronized(mCompiledQueries) {
- for (SQLiteCompiledSql compiledStatement : mCompiledQueries.values()) {
- compiledStatement.releaseSqlStatement();
- }
mCompiledQueries.clear();
}
}
@@ -1842,7 +1835,7 @@
/* reached max cachesize. before adding new entry, remove an entry from the
* cache. we don't want to wipe out the entire cache because of this:
* GCing {@link SQLiteCompiledSql} requires call to sqlite3_finalize
- * JNI method. If entire cache is wiped out, it could cause a big GC activity
+ * JNI method. If entire cache is wiped out, it could be cause a big GC activity
* just because a (rogue) process is using the cache incorrectly.
*/
Set<String> keySet = mCompiledQueries.keySet();
@@ -1851,7 +1844,8 @@
break;
}
}
- mCompiledQueries.put(sql, compiledStatement);
+ compiledSql = new SQLiteCompiledSql(this, sql);
+ mCompiledQueries.put(sql, compiledSql);
}
if (SQLiteDebug.DEBUG_SQL_CACHE) {
Log.v(TAG, "|adding_sql_to_cache|" + getPath() + "|" + mCompiledQueries.size() + "|" +
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index 5ee2f1e..edc15cb 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -100,7 +100,7 @@
* @return a unique identifier for this program
*/
public final int getUniqueId() {
- return (compiledSql != null) ? compiledSql.nStatement : 0;
+ return compiledSql.nStatement;
}
/* package */ String getSqlString() {
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index ac159f4..d90536c 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -930,8 +930,8 @@
/**
* Gets the supported preview sizes.
*
- * @return a List of Size object. null if preview size setting is not
- * supported.
+ * @return a List of Size object. This method will always return a list
+ * with at least one element.
*/
public List<Size> getSupportedPreviewSizes() {
String str = get(KEY_PREVIEW_SIZE + SUPPORTED_VALUES_SUFFIX);
@@ -1065,8 +1065,8 @@
/**
* Gets the supported preview formats.
*
- * @return a List of Integer objects. null if preview format setting is
- * not supported.
+ * @return a List of Integer objects. This method will always return a
+ * list with at least one element.
*/
public List<Integer> getSupportedPreviewFormats() {
String str = get(KEY_PREVIEW_FORMAT + SUPPORTED_VALUES_SUFFIX);
@@ -1104,8 +1104,8 @@
/**
* Gets the supported picture sizes.
*
- * @return a List of Size objects. null if picture size setting is not
- * supported.
+ * @return a List of Size objects. This method will always return a list
+ * with at least one element.
*/
public List<Size> getSupportedPictureSizes() {
String str = get(KEY_PICTURE_SIZE + SUPPORTED_VALUES_SUFFIX);
@@ -1143,12 +1143,18 @@
/**
* Gets the supported picture formats.
*
- * @return a List of Integer objects (values are PixelFormat.XXX). null
- * if picture setting is not supported.
+ * @return a List of Integer objects (values are PixelFormat.XXX). This
+ * method will always return a list with at least one element.
*/
public List<Integer> getSupportedPictureFormats() {
- String str = get(KEY_PICTURE_SIZE + SUPPORTED_VALUES_SUFFIX);
- return splitInt(str);
+ String str = get(KEY_PICTURE_FORMAT + SUPPORTED_VALUES_SUFFIX);
+ ArrayList<Integer> formats = new ArrayList<Integer>();
+ for (String s : split(str)) {
+ int f = pixelFormatForCameraFormat(s);
+ if (f == PixelFormat.UNKNOWN) continue;
+ formats.add(f);
+ }
+ return formats;
}
private String cameraFormatForPixelFormat(int pixel_format) {
@@ -1443,8 +1449,8 @@
/**
* Gets the supported focus modes.
*
- * @return a List of FOCUS_MODE_XXX string constants. null if focus mode
- * setting is not supported.
+ * @return a List of FOCUS_MODE_XXX string constants. This method will
+ * always return a list with at least one element.
*/
public List<String> getSupportedFocusModes() {
String str = get(KEY_FOCUS_MODE + SUPPORTED_VALUES_SUFFIX);
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index 46de708..f2e132b5 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -376,6 +376,16 @@
return sinks.toArray(new BluetoothDevice[sinks.size()]);
}
+ public synchronized BluetoothDevice[] getNonDisconnectedSinks() {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ Set<BluetoothDevice> sinks = lookupSinksMatchingStates(
+ new int[] {BluetoothA2dp.STATE_CONNECTED,
+ BluetoothA2dp.STATE_PLAYING,
+ BluetoothA2dp.STATE_CONNECTING,
+ BluetoothA2dp.STATE_DISCONNECTING});
+ return sinks.toArray(new BluetoothDevice[sinks.size()]);
+ }
+
public synchronized int getSinkState(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Integer state = mAudioDevices.get(device);
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index e960491..0d0d245 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -546,12 +546,14 @@
boolean authorized = false;
ParcelUuid uuid = ParcelUuid.fromString(deviceUuid);
+ BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
+
// Bluez sends the UUID of the local service being accessed, _not_ the
// remote service
if (mBluetoothService.isEnabled() &&
(BluetoothUuid.isAudioSource(uuid) || BluetoothUuid.isAvrcpTarget(uuid)
- || BluetoothUuid.isAdvAudioDist(uuid))) {
- BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
+ || BluetoothUuid.isAdvAudioDist(uuid)) &&
+ (a2dp.getNonDisconnectedSinks().size() == 0)) {
BluetoothDevice device = mAdapter.getRemoteDevice(address);
authorized = a2dp.getSinkPriority(device) > BluetoothA2dp.PRIORITY_OFF;
if (authorized) {
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index fb369d3..ee26218 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -108,6 +108,8 @@
private static final int RECEIVED_TOUCH_ICON_URL = 132;
private static final int GET_VISITED_HISTORY = 133;
private static final int OPEN_FILE_CHOOSER = 134;
+ private static final int SHOW_CUSTOM_VIEW = 135;
+ private static final int HIDE_CUSTOM_VIEW = 136;
// Message triggered by the client to resume execution
private static final int NOTIFY = 200;
@@ -679,6 +681,23 @@
mWebChromeClient.openFileChooser((UploadFile) msg.obj);
}
break;
+
+ case SHOW_CUSTOM_VIEW:
+ if (mWebChromeClient != null) {
+ HashMap<String, Object> map =
+ (HashMap<String, Object>) msg.obj;
+ View view = (View) map.get("view");
+ WebChromeClient.CustomViewCallback callback =
+ (WebChromeClient.CustomViewCallback) map.get("callback");
+ mWebChromeClient.onShowCustomView(view, callback);
+ }
+ break;
+
+ case HIDE_CUSTOM_VIEW:
+ if (mWebChromeClient != null) {
+ mWebChromeClient.onHideCustomView();
+ }
+ break;
}
}
@@ -1385,4 +1404,24 @@
}
return uploadFile.getResult();
}
+
+ /* package */ void showCustomView(View view, WebChromeClient.CustomViewCallback callback) {
+ if (mWebChromeClient == null) {
+ return;
+ }
+ Message msg = obtainMessage(SHOW_CUSTOM_VIEW);
+ HashMap<String, Object> map = new HashMap();
+ map.put("view", view);
+ map.put("callback", callback);
+ msg.obj = map;
+ sendMessage(msg);
+ }
+
+ /* package */ void hideCustomView() {
+ if (mWebChromeClient == null) {
+ return;
+ }
+ Message msg = obtainMessage(HIDE_CUSTOM_VIEW);
+ sendMessage(msg);
+ }
}
diff --git a/core/java/android/webkit/PluginActivity.java b/core/java/android/webkit/PluginActivity.java
deleted file mode 100644
index c60512b..0000000
--- a/core/java/android/webkit/PluginActivity.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2009 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.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.View;
-import android.webkit.plugin.SurfaceDrawingModel;
-import android.webkit.plugin.WebkitPlugin;
-
-/**
- * This activity is invoked when a plugin elects to go into full screen mode.
- * @hide
- */
-public class PluginActivity extends Activity {
-
- private static final String LOGTAG = "PluginActivity";
-
- /* package */ static final String INTENT_EXTRA_NPP_INSTANCE =
- "android.webkit.plugin.NPP_INSTANCE";
-
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- final Intent intent = getIntent();
- if (intent == null) {
- Log.e(LOGTAG, "Unable to retrieve the intent responsible for this activity");
- finish();
- return;
- }
-
- final int npp = intent.getIntExtra(INTENT_EXTRA_NPP_INSTANCE, -1);
-
- if (npp == -1) {
- Log.e(LOGTAG, "The intent did not include the NPP pointer");
- finish();
- return;
- }
-
- // retrieve the plugin's existing java object instead of creating a new one
- WebkitPlugin plugin = nativeGetWebkitPlugin(npp);
-
- if (plugin == null) {
- Log.e(LOGTAG, "Unable to retrieve the plugin's java interface");
- finish();
- return;
- }
- SurfaceDrawingModel fullScreenSurface = plugin.getFullScreenSurface();
- if (fullScreenSurface == null) {
- Log.e(LOGTAG, "The plugin returned a null value for the full-screen interface");
- finish();
- return;
- }
- View pluginView = fullScreenSurface.getSurface();
- if (pluginView != null) {
- setContentView(pluginView);
- } else {
- // No custom full-sreen view returned by the plugin, odd but
- // just in case, finish the activity.
- Log.e(LOGTAG, "The plugin's full-screen interface returned a null view");
- finish();
- }
- }
-
- native WebkitPlugin nativeGetWebkitPlugin(int npp);
-}
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 33f3713c..6079773 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -41,6 +41,7 @@
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
+import android.webkit.plugin.FullScreenDrawingModel;
import android.webkit.plugin.SurfaceDrawingModel;
import android.webkit.plugin.WebkitPlugin;
@@ -2214,16 +2215,36 @@
return pluginManager.getPluginInstance(pkgName, npp);
}
- // called by JNI. PluginWidget function to launch an activity and overlays
- // the activity with the View provided by the plugin class.
- private void startFullScreenPluginActivity(int npp) {
+ // called by JNI. PluginWidget function to launch a full-screen view using a
+ // View object provided by the plugin class.
+ private void showFullScreenPlugin(WebkitPlugin webkitPlugin) {
if (mWebView == null) {
return;
}
- Intent intent = new Intent("android.intent.webkit.PLUGIN");
- intent.putExtra(PluginActivity.INTENT_EXTRA_NPP_INSTANCE, npp);
- mWebView.getContext().startActivity(intent);
+ final FullScreenDrawingModel surface = webkitPlugin.getFullScreenSurface();
+ if(surface == null) {
+ Log.e(LOGTAG, "Attempted to create an full-screen surface with a null drawing model");
+ return;
+ }
+
+ WebChromeClient.CustomViewCallback callback = new WebChromeClient.CustomViewCallback() {
+ public void onCustomViewHidden() {
+ if (surface != null) {
+ surface.onSurfaceRemoved();
+ }
+ }
+ };
+
+ mCallbackProxy.showCustomView(surface.getSurface(), callback);
+ }
+
+ private void hideFullScreenPlugin() {
+ if (mWebView == null) {
+ return;
+ }
+
+ mCallbackProxy.hideCustomView();
}
// called by JNI. PluginWidget functions for creating an embedded View for
diff --git a/core/java/android/webkit/plugin/FullScreenDrawingModel.java b/core/java/android/webkit/plugin/FullScreenDrawingModel.java
new file mode 100644
index 0000000..fe9d197
--- /dev/null
+++ b/core/java/android/webkit/plugin/FullScreenDrawingModel.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package android.webkit.plugin;
+
+/**
+ *
+ * @hide pending API solidification
+ */
+public interface FullScreenDrawingModel extends SurfaceDrawingModel {
+
+ public void onSurfaceRemoved();
+
+}
diff --git a/core/java/android/webkit/plugin/WebkitPlugin.java b/core/java/android/webkit/plugin/WebkitPlugin.java
index 3d13c1c..af02cdc 100644
--- a/core/java/android/webkit/plugin/WebkitPlugin.java
+++ b/core/java/android/webkit/plugin/WebkitPlugin.java
@@ -30,7 +30,7 @@
*/
public interface WebkitPlugin {
- SurfaceDrawingModel getEmbeddedSurface();
- SurfaceDrawingModel getFullScreenSurface();
+ SurfaceDrawingModel getEmbeddedSurface();
+ FullScreenDrawingModel getFullScreenSurface();
}
diff --git a/core/java/com/google/android/collect/Sets.java b/core/java/com/google/android/collect/Sets.java
index f5be0ec..fbfbe50 100644
--- a/core/java/com/google/android/collect/Sets.java
+++ b/core/java/com/google/android/collect/Sets.java
@@ -44,41 +44,50 @@
return new HashSet<K>();
}
- /**
- * Creates a {@code HashSet} instance containing the given elements.
- *
- * <p><b>Note:</b> due to a bug in javac 1.5.0_06, we cannot support the
- * following:
- *
- * <p>{@code Set<Base> set = Sets.newHashSet(sub1, sub2);}
- *
- * <p>where {@code sub1} and {@code sub2} are references to subtypes of {@code
- * Base}, not of {@code Base} itself. To get around this, you must use:
- *
- * <p>{@code Set<Base> set = Sets.<Base>newHashSet(sub1, sub2);}
- *
- * @param elements the elements that the set should contain
- * @return a newly-created {@code HashSet} containing those elements (minus
- * duplicates)
- */
- public static <E> HashSet<E> newHashSet(E... elements) {
- int capacity = elements.length * 4 / 3 + 1;
- HashSet<E> set = new HashSet<E>(capacity);
- Collections.addAll(set, elements);
- return set;
- }
+ /**
+ * Creates a {@code HashSet} instance containing the given elements.
+ *
+ * <p><b>Note:</b> due to a bug in javac 1.5.0_06, we cannot support the
+ * following:
+ *
+ * <p>{@code Set<Base> set = Sets.newHashSet(sub1, sub2);}
+ *
+ * <p>where {@code sub1} and {@code sub2} are references to subtypes of {@code
+ * Base}, not of {@code Base} itself. To get around this, you must use:
+ *
+ * <p>{@code Set<Base> set = Sets.<Base>newHashSet(sub1, sub2);}
+ *
+ * @param elements the elements that the set should contain
+ * @return a newly-created {@code HashSet} containing those elements (minus
+ * duplicates)
+ */
+ public static <E> HashSet<E> newHashSet(E... elements) {
+ int capacity = elements.length * 4 / 3 + 1;
+ HashSet<E> set = new HashSet<E>(capacity);
+ Collections.addAll(set, elements);
+ return set;
+ }
- /**
- * Creates a {@code SortedSet} instance containing the given elements.
- *
- * @param elements the elements that the set should contain
- * @return a newly-created {@code SortedSet} containing those elements (minus
- * duplicates)
- */
- public static <E> SortedSet<E> newSortedSet(E... elements) {
- SortedSet<E> set = new TreeSet<E>();
- Collections.addAll(set, elements);
- return set;
- }
+ /**
+ * Creates an empty {@code SortedSet} instance.
+ *
+ * @return a newly-created, initially-empty {@code SortedSet}.
+ */
+ public static <E> SortedSet<E> newSortedSet() {
+ return new TreeSet<E>();
+ }
+
+ /**
+ * Creates a {@code SortedSet} instance containing the given elements.
+ *
+ * @param elements the elements that the set should contain
+ * @return a newly-created {@code SortedSet} containing those elements (minus
+ * duplicates)
+ */
+ public static <E> SortedSet<E> newSortedSet(E... elements) {
+ SortedSet<E> set = new TreeSet<E>();
+ Collections.addAll(set, elements);
+ return set;
+ }
}
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index a45faad..7e365fc 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -40,6 +40,20 @@
android:textAppearance="?android:attr/textAppearanceMedium"
/>
+ <!-- emergency call button shown when sim is missing or PUKd -->
+ <Button
+ android:id="@+id/emergencyCallButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentRight="true"
+ android:layout_marginTop="10dip"
+ android:layout_marginRight="8dip"
+ android:drawableLeft="@drawable/ic_emergency"
+ style="@style/Widget.Button.Transparent"
+ android:drawablePadding="8dip"
+ />
+
<!-- time and date -->
<com.android.internal.widget.DigitalClock android:id="@+id/time"
android:layout_width="wrap_content"
@@ -121,6 +135,7 @@
android:layout_marginLeft="24dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_marginTop="12dip"
+ android:drawablePadding="4dip"
/>
<com.android.internal.widget.SlidingTab
@@ -132,18 +147,5 @@
android:layout_marginBottom="80dip"
/>
- <!-- emergency call button shown when sim is missing or PUKd -->
- <Button
- android:id="@+id/emergencyCallButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/screenLocked"
- android:layout_marginTop="8dip"
- android:layout_marginLeft="24dip"
- android:drawableLeft="@drawable/ic_emergency"
- style="@style/Widget.Button.Transparent"
- android:drawablePadding="8dip"
- />
-
</RelativeLayout>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index 1001697..33afe93 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -45,6 +45,18 @@
android:textAppearance="?android:attr/textAppearanceMedium"
/>
+ <!-- emergency call button shown when sim is missing or PUKd -->
+ <Button
+ android:id="@+id/emergencyCallButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_marginTop="20dip"
+ android:drawableLeft="@drawable/ic_emergency"
+ style="@style/Widget.Button.Transparent"
+ android:drawablePadding="8dip"
+ />
+
<com.android.internal.widget.DigitalClock android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -122,19 +134,9 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="center"
android:layout_marginTop="12dip"
+ android:drawablePadding="4dip"
/>
- <!-- emergency call button shown when sim is missing or PUKd -->
- <Button
- android:id="@+id/emergencyCallButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/screenLocked"
- android:layout_marginTop="8dip"
- android:drawableLeft="@drawable/ic_emergency"
- style="@style/Widget.Button.Transparent"
- android:drawablePadding="8dip"
- />
</RelativeLayout>
<!-- right side -->
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index f17d1ff..b6af6b2 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -90,5 +90,12 @@
<color name="sliding_tab_text_color_active">@android:color/black</color>
<color name="sliding_tab_text_color_shadow">@android:color/black</color>
+ <!-- keyguard tab -->
+ <color name="keyguard_text_color_normal">#ffffff</color>
+ <color name="keyguard_text_color_unlock">#a7d84c</color>
+ <color name="keyguard_text_color_soundoff">#ffffff</color>
+ <color name="keyguard_text_color_soundon">#e69310</color>
+ <color name="keyguard_text_color_decline">#fe0a5a</color>
+
</resources>
diff --git a/docs/html/guide/developing/tools/aidl.jd b/docs/html/guide/developing/tools/aidl.jd
index abfa8b1..19d9ea1 100644
--- a/docs/html/guide/developing/tools/aidl.jd
+++ b/docs/html/guide/developing/tools/aidl.jd
@@ -297,9 +297,9 @@
as method arguments. </li>
</ul>
<p>Here is some sample code demonstrating calling an AIDL-created service, taken
- from the Remote Activity sample in the ApiDemos project.</p>
-<p>{@sample development/samples/ApiDemos/src/com/example/android/apis/app/RemoteServiceBinding.java
- exposing_a_service}</p>
+ from the Remote Service sample in the ApiDemos project.</p>
+<p>{@sample development/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java
+ calling_a_service}</p>
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index cd62ed1..7763549 100755
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -875,53 +875,51 @@
synchronized(mListeners) {
boolean wasNavigating = mNavigating;
mNavigating = (status == GPS_STATUS_SESSION_BEGIN);
-
- if (wasNavigating == mNavigating) {
- return;
- }
-
- if (mNavigating) {
+
+ if (mNavigating && !mWakeLock.isHeld()) {
if (DEBUG) Log.d(TAG, "Acquiring wakelock");
mWakeLock.acquire();
}
-
- int size = mListeners.size();
- for (int i = 0; i < size; i++) {
- Listener listener = mListeners.get(i);
+
+ if (wasNavigating != mNavigating) {
+ int size = mListeners.size();
+ for (int i = 0; i < size; i++) {
+ Listener listener = mListeners.get(i);
+ try {
+ if (mNavigating) {
+ listener.mListener.onGpsStarted();
+ } else {
+ listener.mListener.onGpsStopped();
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "RemoteException in reportStatus");
+ mListeners.remove(listener);
+ // adjust for size of list changing
+ size--;
+ }
+ }
+
try {
- if (mNavigating) {
- listener.mListener.onGpsStarted();
- } else {
- listener.mListener.onGpsStopped();
+ // update battery stats
+ for (int i=mClientUids.size() - 1; i >= 0; i--) {
+ int uid = mClientUids.keyAt(i);
+ if (mNavigating) {
+ mBatteryStats.noteStartGps(uid);
+ } else {
+ mBatteryStats.noteStopGps(uid);
+ }
}
} catch (RemoteException e) {
Log.w(TAG, "RemoteException in reportStatus");
- mListeners.remove(listener);
- // adjust for size of list changing
- size--;
}
+
+ // send an intent to notify that the GPS has been enabled or disabled.
+ Intent intent = new Intent(GPS_ENABLED_CHANGE_ACTION);
+ intent.putExtra(EXTRA_ENABLED, mNavigating);
+ mContext.sendBroadcast(intent);
}
- try {
- // update battery stats
- for (int i=mClientUids.size() - 1; i >= 0; i--) {
- int uid = mClientUids.keyAt(i);
- if (mNavigating) {
- mBatteryStats.noteStartGps(uid);
- } else {
- mBatteryStats.noteStopGps(uid);
- }
- }
- } catch (RemoteException e) {
- Log.w(TAG, "RemoteException in reportStatus");
- }
-
- // send an intent to notify that the GPS has been enabled or disabled.
- Intent intent = new Intent(GPS_ENABLED_CHANGE_ACTION);
- intent.putExtra(EXTRA_ENABLED, mNavigating);
- mContext.sendBroadcast(intent);
-
- if (!mNavigating) {
+ if (status == GPS_STATUS_ENGINE_OFF && mWakeLock.isHeld()) {
if (DEBUG) Log.d(TAG, "Releasing wakelock");
mWakeLock.release();
}
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 676e5f6..27b631e 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -100,7 +100,7 @@
private boolean mSystemReady;
private ArrayList<Intent> mDeferredBroadcasts;
- private class NetworkAttributes {
+ private static class NetworkAttributes {
/**
* Class for holding settings read from resources.
*/
@@ -108,6 +108,7 @@
public int mType;
public int mRadio;
public int mPriority;
+ public NetworkInfo.State mLastState;
public NetworkAttributes(String init) {
String fragments[] = init.split(",");
mName = fragments[0].toLowerCase();
@@ -128,6 +129,7 @@
mType = ConnectivityManager.TYPE_MOBILE_HIPRI;
}
mPriority = Integer.parseInt(fragments[2]);
+ mLastState = NetworkInfo.State.UNKNOWN;
}
public boolean isDefault() {
return (mType == mRadio);
@@ -135,7 +137,7 @@
}
NetworkAttributes[] mNetAttributes;
- private class RadioAttributes {
+ private static class RadioAttributes {
public String mName;
public int mPriority;
public int mSimultaneity;
@@ -1213,9 +1215,22 @@
switch (msg.what) {
case NetworkStateTracker.EVENT_STATE_CHANGED:
info = (NetworkInfo) msg.obj;
+ int type = info.getType();
+ NetworkInfo.State state = info.getState();
+ if(mNetAttributes[type].mLastState == state) {
+ if (DBG) {
+ // TODO - remove this after we validate the dropping doesn't break anything
+ Log.d(TAG, "Dropping ConnectivityChange for " +
+ info.getTypeName() +": " +
+ state + "/" + info.getDetailedState());
+ }
+ return;
+ }
+ mNetAttributes[type].mLastState = state;
+
if (DBG) Log.d(TAG, "ConnectivityChange for " +
info.getTypeName() + ": " +
- info.getState() + "/" + info.getDetailedState());
+ state + "/" + info.getDetailedState());
// Connectivity state changed:
// [31-13] Reserved for future use
@@ -1233,10 +1248,9 @@
if (info.getDetailedState() ==
NetworkInfo.DetailedState.FAILED) {
handleConnectionFailure(info);
- } else if (info.getState() ==
- NetworkInfo.State.DISCONNECTED) {
+ } else if (state == NetworkInfo.State.DISCONNECTED) {
handleDisconnect(info);
- } else if (info.getState() == NetworkInfo.State.SUSPENDED) {
+ } else if (state == NetworkInfo.State.SUSPENDED) {
// TODO: need to think this over.
// the logic here is, handle SUSPENDED the same as
// DISCONNECTED. The only difference being we are
@@ -1245,7 +1259,7 @@
// opportunity to handle DISCONNECTED and SUSPENDED
// differently, or not.
handleDisconnect(info);
- } else if (info.getState() == NetworkInfo.State.CONNECTED) {
+ } else if (state == NetworkInfo.State.CONNECTED) {
handleConnect(info);
}
break;
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 0ea832b..987a24e 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -25,6 +25,7 @@
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -62,6 +63,7 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.regex.Pattern;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -109,7 +111,7 @@
private int mMulticastDisabled;
private final IBatteryStats mBatteryStats;
-
+
/**
* See {@link Settings.Gservices#WIFI_IDLE_MS}. This is the default value if a
* Settings.Gservices value is not present. This timeout value is chosen as
@@ -162,7 +164,7 @@
* Last UID that asked to enable WIFI.
*/
private int mLastEnableUid = Process.myUid();
-
+
/**
* Number of allowed radio frequency channels in various regulatory domains.
* This list is sufficient for 802.11b/g networks (2.4GHz range).
@@ -177,7 +179,7 @@
mWifiStateTracker = tracker;
mWifiStateTracker.enableRssiPolling(true);
mBatteryStats = BatteryStatsService.getService();
-
+
mScanResultCache = new LinkedHashMap<String, ScanResult>(
SCAN_RESULT_CACHE_SIZE, 0.75f, true) {
/*
@@ -396,7 +398,7 @@
} finally {
Binder.restoreCallingIdentity(ident);
}
-
+
// Update state
mWifiState = wifiState;
@@ -1380,11 +1382,16 @@
}
mPluggedType = pluggedType;
} else if (action.equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED)) {
- boolean isBluetoothPlaying =
- intent.getIntExtra(
- BluetoothA2dp.EXTRA_SINK_STATE,
- BluetoothA2dp.STATE_DISCONNECTED) == BluetoothA2dp.STATE_PLAYING;
+ BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
+ Set<BluetoothDevice> sinks = a2dp.getConnectedSinks();
+ boolean isBluetoothPlaying = false;
+ for (BluetoothDevice sink : sinks) {
+ if (a2dp.getSinkState(sink) == BluetoothA2dp.STATE_PLAYING) {
+ isBluetoothPlaying = true;
+ }
+ }
mWifiStateTracker.setBluetoothScanMode(isBluetoothPlaying);
+
} else {
return;
}
@@ -1396,7 +1403,7 @@
* Determines whether the Wi-Fi chipset should stay awake or be put to
* sleep. Looks at the setting for the sleep policy and the current
* conditions.
- *
+ *
* @see #shouldDeviceStayAwake(int, int)
*/
private boolean shouldWifiStayAwake(int stayAwakeConditions, int pluggedType) {
@@ -1415,7 +1422,7 @@
return shouldDeviceStayAwake(stayAwakeConditions, pluggedType);
}
}
-
+
/**
* Determine whether the bit value corresponding to {@code pluggedType} is set in
* the bit string {@code stayAwakeConditions}. Because a {@code pluggedType} value
@@ -1509,7 +1516,7 @@
intentFilter.addAction(BluetoothA2dp.ACTION_SINK_STATE_CHANGED);
mContext.registerReceiver(mReceiver, intentFilter);
}
-
+
private boolean isAirplaneSensitive() {
String airplaneModeRadios = Settings.System.getString(mContext.getContentResolver(),
Settings.System.AIRPLANE_MODE_RADIOS);
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index 2b9d18f..bee0930 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -283,7 +283,7 @@
private IBinder mBluetoothIcon;
private IconData mBluetoothData;
private int mBluetoothHeadsetState;
- private int mBluetoothA2dpState;
+ private boolean mBluetoothA2dpConnected;
private int mBluetoothPbapState;
private boolean mBluetoothEnabled;
@@ -455,7 +455,7 @@
} else {
mBluetoothEnabled = false;
}
- mBluetoothA2dpState = BluetoothA2dp.STATE_DISCONNECTED;
+ mBluetoothA2dpConnected = false;
mBluetoothHeadsetState = BluetoothHeadset.STATE_DISCONNECTED;
mBluetoothPbapState = BluetoothPbap.STATE_DISCONNECTED;
mService.setIconVisibility(mBluetoothIcon, mBluetoothEnabled);
@@ -636,12 +636,12 @@
int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_DIM_BEHIND;
-
+
if (!mContext.getResources().getBoolean(
com.android.internal.R.bool.config_sf_slowBlur)) {
flags |= WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
}
-
+
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
@@ -1083,7 +1083,6 @@
private final void updateBluetooth(Intent intent) {
int iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth;
-
String action = intent.getAction();
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
@@ -1092,8 +1091,12 @@
mBluetoothHeadsetState = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
BluetoothHeadset.STATE_ERROR);
} else if (action.equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED)) {
- mBluetoothA2dpState = intent.getIntExtra(BluetoothA2dp.EXTRA_SINK_STATE,
- BluetoothA2dp.STATE_DISCONNECTED);
+ BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
+ if (a2dp.getConnectedSinks().size() != 0) {
+ mBluetoothA2dpConnected = true;
+ } else {
+ mBluetoothA2dpConnected = false;
+ }
} else if (action.equals(BluetoothPbap.PBAP_STATE_CHANGED_ACTION)) {
mBluetoothPbapState = intent.getIntExtra(BluetoothPbap.PBAP_STATE,
BluetoothPbap.STATE_DISCONNECTED);
@@ -1101,9 +1104,7 @@
return;
}
- if (mBluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED ||
- mBluetoothA2dpState == BluetoothA2dp.STATE_CONNECTED ||
- mBluetoothA2dpState == BluetoothA2dp.STATE_PLAYING ||
+ if (mBluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED || mBluetoothA2dpConnected ||
mBluetoothPbapState == BluetoothPbap.STATE_CONNECTED) {
iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth_connected;
}