summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ActivityManager.java7
-rw-r--r--core/java/android/app/ActivityManagerNative.java6
-rw-r--r--core/java/android/app/IActivityManager.java2
-rw-r--r--core/java/android/app/SearchDialog.java1
-rw-r--r--core/java/android/os/Looper.java17
-rw-r--r--core/java/android/view/HardwareRenderer.java16
-rw-r--r--core/java/android/view/IWindowSession.aidl5
-rw-r--r--core/java/android/view/ViewRoot.java66
-rw-r--r--core/java/android/webkit/BrowserFrame.java40
-rw-r--r--core/java/android/webkit/CallbackProxy.java16
-rw-r--r--core/java/android/webkit/SearchBox.java92
-rw-r--r--core/java/android/webkit/SearchBoxImpl.java227
-rw-r--r--core/java/android/webkit/WebView.java9
-rw-r--r--core/java/android/webkit/WebViewCore.java11
-rw-r--r--core/java/android/widget/EdgeGlow.java4
-rw-r--r--core/java/android/widget/SearchView.java13
-rwxr-xr-xcore/res/res/drawable-hdpi/stat_sys_adb.pngbin625 -> 578 bytes
-rw-r--r--core/res/res/drawable-ldpi/stat_sys_adb.pngbin408 -> 362 bytes
-rw-r--r--core/res/res/drawable-mdpi/stat_sys_adb.pngbin514 -> 380 bytes
-rw-r--r--media/java/android/media/MediaScanner.java9
-rw-r--r--packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg.9.pngbin41746 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_normal.9.pngbin0 -> 86133 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.pngbin0 -> 81588 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/status_bar_veto_pressed.pngbin1139 -> 288 bytes
-rw-r--r--packages/SystemUI/res/drawable/notify_panel_clock_bg.xml22
-rw-r--r--packages/SystemUI/res/layout-xlarge/status_bar_notification_panel_title.xml5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java3
-rw-r--r--services/java/com/android/server/MountService.java2
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java11
-rw-r--r--services/java/com/android/server/usb/UsbDeviceSettingsManager.java10
-rw-r--r--services/java/com/android/server/wm/Session.java4
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java34
-rw-r--r--services/java/com/android/server/wm/WindowState.java4
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java4
36 files changed, 638 insertions, 60 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 77dc08486810..930c6b0591ac 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1253,8 +1253,13 @@ public class ActivityManager {
return new HashMap<String, Integer>();
}
+ PkgUsageStats[] allPkgUsageStats = usageStatsService.getAllPkgUsageStats();
+ if (allPkgUsageStats == null) {
+ return new HashMap<String, Integer>();
+ }
+
Map<String, Integer> launchCounts = new HashMap<String, Integer>();
- for (PkgUsageStats pkgUsageStats : usageStatsService.getAllPkgUsageStats()) {
+ for (PkgUsageStats pkgUsageStats : allPkgUsageStats) {
launchCounts.put(pkgUsageStats.packageName, pkgUsageStats.launchCount);
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index d3d379294789..64266354edcc 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1020,7 +1020,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
data.enforceInterface(IActivityManager.descriptor);
int[] pids = data.createIntArray();
String reason = data.readString();
- boolean res = killPids(pids, reason);
+ boolean secure = data.readInt() != 0;
+ boolean res = killPids(pids, reason, secure);
reply.writeNoException();
reply.writeInt(res ? 1 : 0);
return true;
@@ -2636,12 +2637,13 @@ class ActivityManagerProxy implements IActivityManager
mRemote.transact(NOTE_WAKEUP_ALARM_TRANSACTION, data, null, 0);
data.recycle();
}
- public boolean killPids(int[] pids, String reason) throws RemoteException {
+ public boolean killPids(int[] pids, String reason, boolean secure) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeIntArray(pids);
data.writeString(reason);
+ data.writeInt(secure ? 1 : 0);
mRemote.transact(KILL_PIDS_TRANSACTION, data, reply, 0);
boolean res = reply.readInt() != 0;
data.recycle();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index f42e8fb73e86..61e6fc8466c2 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -250,7 +250,7 @@ public interface IActivityManager extends IInterface {
public void noteWakeupAlarm(IIntentSender sender) throws RemoteException;
- public boolean killPids(int[] pids, String reason) throws RemoteException;
+ public boolean killPids(int[] pids, String reason, boolean secure) throws RemoteException;
// Special low-level communication with activity manager.
public void startRunning(String pkg, String cls, String action,
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index e95a23d715cb..db8d5e93cdcf 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -255,6 +255,7 @@ public class SearchDialog extends Dialog {
// of any bad state in the AutoCompleteTextView etc
createContentView();
mSearchView.setSearchableInfo(mSearchable);
+ mSearchView.setAppSearchData(mAppSearchData);
show();
}
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index 898c64272206..8204e3c82da2 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -112,6 +112,12 @@ public class Looper {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
MessageQueue queue = me.mQueue;
+
+ // Make sure the identity of this thread is that of the local process,
+ // and keep track of what that identity token actually is.
+ Binder.clearCallingIdentity();
+ final long ident = Binder.clearCallingIdentity();
+
while (true) {
Message msg = queue.next(); // might block
if (msg != null) {
@@ -127,6 +133,17 @@ public class Looper {
if (me.mLogging != null) me.mLogging.println(
"<<<<< Finished to " + msg.target + " "
+ msg.callback);
+
+ // Make sure that during the course of dispatching the
+ // identity of the thread wasn't corrupted.
+ final long newIdent = Binder.clearCallingIdentity();
+ if (ident != newIdent) {
+ Log.wtf("Looper", "Thread identity changed from 0x"
+ + Long.toHexString(ident) + " to 0x"
+ + Long.toHexString(newIdent) + " while dispatching to "
+ + msg.target + " " + msg.callback + " what=" + msg.what);
+ }
+
msg.recycle();
}
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index d46dacc2e55d..b53aa21b955b 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -108,14 +108,14 @@ public abstract class HardwareRenderer {
*
* @return True if the initialization was successful, false otherwise.
*/
- abstract boolean initialize(SurfaceHolder holder);
+ abstract boolean initialize(SurfaceHolder holder) throws Surface.OutOfResourcesException;
/**
* Updates the hardware renderer for the specified surface.
*
* @param holder The holder for the surface to hardware accelerate.
*/
- abstract void updateSurface(SurfaceHolder holder);
+ abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException;
/**
* Setup the hardware renderer for drawing. This is called for every
@@ -189,7 +189,7 @@ public abstract class HardwareRenderer {
* @param holder
*/
void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
- SurfaceHolder holder) {
+ SurfaceHolder holder) throws Surface.OutOfResourcesException {
if (isRequested()) {
// We lost the gl context, so recreate it.
if (!isEnabled()) {
@@ -366,7 +366,7 @@ public abstract class HardwareRenderer {
}
@Override
- boolean initialize(SurfaceHolder holder) {
+ boolean initialize(SurfaceHolder holder) throws Surface.OutOfResourcesException {
if (isRequested() && !isEnabled()) {
initializeEgl();
mGl = createEglSurface(holder);
@@ -395,7 +395,7 @@ public abstract class HardwareRenderer {
}
@Override
- void updateSurface(SurfaceHolder holder) {
+ void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException {
if (isRequested() && isEnabled()) {
createEglSurface(holder);
}
@@ -446,7 +446,7 @@ public abstract class HardwareRenderer {
sEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
}
- GL createEglSurface(SurfaceHolder holder) {
+ GL createEglSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException {
// Check preconditions.
if (sEgl == null) {
throw new RuntimeException("egl not initialized");
@@ -494,7 +494,7 @@ public abstract class HardwareRenderer {
* the context is current and bound to a surface.
*/
if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) {
- throw new RuntimeException("eglMakeCurrent failed "
+ throw new Surface.OutOfResourcesException("eglMakeCurrent failed "
+ getEGLErrorString(sEgl.eglGetError()));
}
@@ -516,7 +516,7 @@ public abstract class HardwareRenderer {
@Override
void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
- SurfaceHolder holder) {
+ SurfaceHolder holder) throws Surface.OutOfResourcesException {
if (isRequested()) {
checkEglErrors();
super.initializeIfNeeded(width, height, attachInfo, holder);
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 1218e81d7708..990af083d859 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -84,6 +84,11 @@ interface IWindowSession {
out Surface outSurface);
/**
+ * Called by a client to report that it ran out of graphics memory.
+ */
+ boolean outOfMemory(IWindow window);
+
+ /**
* Give the window manager a hint of the part of the window that is
* completely transparent, allowing it to work with the surface flinger
* to optimize compositing of this part of the window.
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 965c959f2db4..546823047b24 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1066,7 +1066,20 @@ public final class ViewRoot extends Handler implements ViewParent,
mPreviousTransparentRegion.setEmpty();
if (mAttachInfo.mHardwareRenderer != null) {
- hwInitialized = mAttachInfo.mHardwareRenderer.initialize(mHolder);
+ try {
+ hwInitialized = mAttachInfo.mHardwareRenderer.initialize(mHolder);
+ } catch (Surface.OutOfResourcesException e) {
+ Log.e(TAG, "OutOfResourcesException initializing HW surface", e);
+ try {
+ if (!sWindowSession.outOfMemory(mWindow)) {
+ Slog.w(TAG, "No processes killed for memory; killing self");
+ Process.killProcess(Process.myPid());
+ }
+ } catch (RemoteException ex) {
+ }
+ mLayoutRequested = true; // ask wm for a new surface next time.
+ return;
+ }
}
}
} else if (!mSurface.isValid()) {
@@ -1081,7 +1094,20 @@ public final class ViewRoot extends Handler implements ViewParent,
} else if (surfaceGenerationId != mSurface.getGenerationId() &&
mSurfaceHolder == null && mAttachInfo.mHardwareRenderer != null) {
fullRedrawNeeded = true;
- mAttachInfo.mHardwareRenderer.updateSurface(mHolder);
+ try {
+ mAttachInfo.mHardwareRenderer.updateSurface(mHolder);
+ } catch (Surface.OutOfResourcesException e) {
+ Log.e(TAG, "OutOfResourcesException updating HW surface", e);
+ try {
+ if (!sWindowSession.outOfMemory(mWindow)) {
+ Slog.w(TAG, "No processes killed for memory; killing self");
+ Process.killProcess(Process.myPid());
+ }
+ } catch (RemoteException ex) {
+ }
+ mLayoutRequested = true; // ask wm for a new surface next time.
+ return;
+ }
}
} catch (RemoteException e) {
}
@@ -1569,14 +1595,24 @@ public final class ViewRoot extends Handler implements ViewParent,
canvas.setDensity(mDensity);
} catch (Surface.OutOfResourcesException e) {
Log.e(TAG, "OutOfResourcesException locking surface", e);
- // TODO: we should ask the window manager to do something!
- // for now we just do nothing
+ try {
+ if (!sWindowSession.outOfMemory(mWindow)) {
+ Slog.w(TAG, "No processes killed for memory; killing self");
+ Process.killProcess(Process.myPid());
+ }
+ } catch (RemoteException ex) {
+ }
mLayoutRequested = true; // ask wm for a new surface next time.
return;
} catch (IllegalArgumentException e) {
Log.e(TAG, "IllegalArgumentException locking surface", e);
- // TODO: we should ask the window manager to do something!
- // for now we just do nothing
+ try {
+ if (!sWindowSession.outOfMemory(mWindow)) {
+ Slog.w(TAG, "No processes killed for memory; killing self");
+ Process.killProcess(Process.myPid());
+ }
+ } catch (RemoteException ex) {
+ }
mLayoutRequested = true; // ask wm for a new surface next time.
return;
}
@@ -2033,8 +2069,22 @@ public final class ViewRoot extends Handler implements ViewParent,
if (mAttachInfo.mHardwareRenderer != null &&
mSurface != null && mSurface.isValid()) {
mFullRedrawNeeded = true;
- mAttachInfo.mHardwareRenderer.initializeIfNeeded(mWidth, mHeight,
- mAttachInfo, mHolder);
+ try {
+ mAttachInfo.mHardwareRenderer.initializeIfNeeded(mWidth, mHeight,
+ mAttachInfo, mHolder);
+ } catch (Surface.OutOfResourcesException e) {
+ Log.e(TAG, "OutOfResourcesException locking surface", e);
+ try {
+ if (!sWindowSession.outOfMemory(mWindow)) {
+ Slog.w(TAG, "No processes killed for memory; killing self");
+ Process.killProcess(Process.myPid());
+ }
+ } catch (RemoteException ex) {
+ }
+ // Retry in a bit.
+ sendMessageDelayed(obtainMessage(msg.what, msg.arg1, msg.arg2), 500);
+ return;
+ }
}
}
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index fc1240f77f25..ab4bfe19f3f9 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -46,7 +46,6 @@ import java.lang.ref.WeakReference;
import java.net.URLEncoder;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
-import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
@@ -89,6 +88,9 @@ class BrowserFrame extends Handler {
// Key store handler when Chromium HTTP stack is used.
private KeyStoreHandler mKeyStoreHandler = null;
+ // Implementation of the searchbox API.
+ private final SearchBoxImpl mSearchBox;
+
// message ids
// a message posted when a frame loading is completed
static final int FRAME_COMPLETED = 1001;
@@ -225,6 +227,9 @@ class BrowserFrame extends Handler {
sConfigCallback.addHandler(this);
mJSInterfaceMap = javascriptInterfaces;
+ if (mJSInterfaceMap == null) {
+ mJSInterfaceMap = new HashMap<String, Object>();
+ }
mSettings = settings;
mContext = context;
@@ -232,6 +237,9 @@ class BrowserFrame extends Handler {
mDatabase = WebViewDatabase.getInstance(appContext);
mWebViewCore = w;
+ mSearchBox = new SearchBoxImpl(mWebViewCore, mCallbackProxy);
+ mJSInterfaceMap.put(SearchBoxImpl.JS_INTERFACE_NAME, mSearchBox);
+
AssetManager am = context.getAssets();
nativeCreateFrame(w, am, proxy.getBackForwardList());
@@ -587,17 +595,17 @@ class BrowserFrame extends Handler {
* We should re-attach any attached js interfaces.
*/
private void windowObjectCleared(int nativeFramePointer) {
- if (mJSInterfaceMap != null) {
- Iterator iter = mJSInterfaceMap.keySet().iterator();
- while (iter.hasNext()) {
- String interfaceName = (String) iter.next();
- Object object = mJSInterfaceMap.get(interfaceName);
- if (object != null) {
- nativeAddJavascriptInterface(nativeFramePointer,
- mJSInterfaceMap.get(interfaceName), interfaceName);
- }
+ Iterator<String> iter = mJSInterfaceMap.keySet().iterator();
+ while (iter.hasNext()) {
+ String interfaceName = iter.next();
+ Object object = mJSInterfaceMap.get(interfaceName);
+ if (object != null) {
+ nativeAddJavascriptInterface(nativeFramePointer,
+ mJSInterfaceMap.get(interfaceName), interfaceName);
}
}
+
+ stringByEvaluatingJavaScriptFromString(SearchBoxImpl.JS_BRIDGE);
}
/**
@@ -620,16 +628,11 @@ class BrowserFrame extends Handler {
public void addJavascriptInterface(Object obj, String interfaceName) {
assert obj != null;
removeJavascriptInterface(interfaceName);
- if (mJSInterfaceMap == null) {
- mJSInterfaceMap = new HashMap<String, Object>();
- }
+
mJSInterfaceMap.put(interfaceName, obj);
}
public void removeJavascriptInterface(String interfaceName) {
- if (mJSInterfaceMap == null) {
- return;
- }
if (mJSInterfaceMap.containsKey(interfaceName)) {
mJSInterfaceMap.remove(interfaceName);
}
@@ -1234,6 +1237,11 @@ class BrowserFrame extends Handler {
}
}
+
+ /*package*/ SearchBox getSearchBox() {
+ return mSearchBox;
+ }
+
//==========================================================================
// native functions
//==========================================================================
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 160fc2e84498..c66d70162adc 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -42,6 +42,7 @@ import com.android.internal.R;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
/**
@@ -115,6 +116,7 @@ class CallbackProxy extends Handler {
private static final int HISTORY_INDEX_CHANGED = 136;
private static final int AUTH_CREDENTIALS = 137;
private static final int SET_INSTALLABLE_WEBAPP = 138;
+ private static final int NOTIFY_SEARCHBOX_LISTENERS = 139;
// Message triggered by the client to resume execution
private static final int NOTIFY = 200;
@@ -781,6 +783,12 @@ class CallbackProxy extends Handler {
mWebChromeClient.setInstallableWebApp();
}
break;
+ case NOTIFY_SEARCHBOX_LISTENERS:
+ SearchBoxImpl searchBox = (SearchBoxImpl) mWebView.getSearchBox();
+
+ @SuppressWarnings("unchecked")
+ List<String> suggestions = (List<String>) msg.obj;
+ searchBox.handleSuggestions(msg.getData().getString("query"), suggestions);
}
}
@@ -1557,4 +1565,12 @@ class CallbackProxy extends Handler {
// See bug 3166409
return mContext instanceof Activity;
}
+
+ void onSearchboxSuggestionsReceived(String query, List<String> suggestions) {
+ Message msg = obtainMessage(NOTIFY_SEARCHBOX_LISTENERS);
+ msg.obj = suggestions;
+ msg.getData().putString("query", query);
+
+ sendMessage(msg);
+ }
}
diff --git a/core/java/android/webkit/SearchBox.java b/core/java/android/webkit/SearchBox.java
new file mode 100644
index 000000000000..57c7b035efad
--- /dev/null
+++ b/core/java/android/webkit/SearchBox.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.webkit;
+
+import java.util.List;
+
+/**
+ * Defines the interaction between the browser/renderer and the page running on
+ * a given WebView frame, if the page supports the chromium SearchBox API.
+ *
+ * http://dev.chromium.org/searchbox
+ *
+ * The browser or container app can query the page for search results using
+ * SearchBox.query() and receive suggestions by registering a listener on the
+ * SearchBox object.
+ *
+ * @hide pending API council approval.
+ */
+public interface SearchBox {
+ /**
+ * Sets the current searchbox query. Note that the caller must call
+ * onchange() to ensure that the search page processes this query.
+ */
+ void setQuery(String query);
+
+ /**
+ * Verbatim is true if the caller suggests that the search page
+ * treat the current query as a verbatim search query (as opposed to a
+ * partially typed search query). As with setQuery, onchange() must be
+ * called to ensure that the search page processes the query.
+ */
+ void setVerbatim(boolean verbatim);
+
+ /**
+ * These attributes must contain the offset to the characters that immediately
+ * follow the start and end of the selection in the search box. If there is
+ * no such selection, then both selectionStart and selectionEnd must be the offset
+ * to the character that immediately follows the text entry cursor. In the case
+ * that there is no explicit text entry cursor, the cursor is
+ * implicitly at the end of the input.
+ */
+ void setSelection(int selectionStart, int selectionEnd);
+
+ /**
+ * Sets the dimensions of the view (if any) that overlaps the current
+ * window object. This is to ensure that the page renders results in
+ * a manner that allows them to not be obscured by such a view. Note
+ * that a call to onresize() is required if these dimensions change.
+ */
+ void setDimensions(int x, int y, int width, int height);
+
+ /**
+ * Notify the search page of any changes to the searchbox. Such as
+ * a change in the typed query (onchange), the user commiting a given query
+ * (onsubmit), or a change in size of a suggestions dropdown (onresize).
+ */
+ void onchange();
+ void onsubmit();
+ void onresize();
+ void oncancel();
+
+ /**
+ * Add and remove listeners to the given Searchbox. Listeners are notified
+ * of any suggestions to the query that the underlying search engine might
+ * provide.
+ */
+ void addSearchBoxListener(SearchBoxListener l);
+ void removeSearchBoxListener(SearchBoxListener l);
+
+ /**
+ * Listeners (if any) will be called on the thread that created the
+ * webview.
+ */
+ interface SearchBoxListener {
+ void onSuggestionsReceived(String query, List<String> suggestions);
+ }
+}
diff --git a/core/java/android/webkit/SearchBoxImpl.java b/core/java/android/webkit/SearchBoxImpl.java
new file mode 100644
index 000000000000..480f5d7a5b44
--- /dev/null
+++ b/core/java/android/webkit/SearchBoxImpl.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.util.Log;
+import android.webkit.WebViewCore.EventHub;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.json.JSONStringer;
+
+/**
+ * The default implementation of the SearchBox interface. Implemented
+ * as a java bridge object and a javascript adapter that is called into
+ * by the page hosted in the frame.
+ */
+final class SearchBoxImpl implements SearchBox {
+ private static final String TAG = "WebKit.SearchBoxImpl";
+
+ /* package */ static final String JS_INTERFACE_NAME = "searchBoxJavaBridge_";
+
+ /* package */ static final String JS_BRIDGE
+ = "(function()"
+ + "{"
+ + "if (!window.chrome) {"
+ + " window.chrome = {};"
+ + "}"
+ + "if (!window.chrome.searchBox) {"
+ + " var sb = window.chrome.searchBox = {};"
+ + " sb.setSuggestions = function(suggestions) {"
+ + " if (window.searchBoxJavaBridge_) {"
+ + " window.searchBoxJavaBridge_.setSuggestions(JSON.stringify(suggestions));"
+ + " }"
+ + " };"
+ + " sb.setValue = function(valueArray) { sb.value = valueArray[0]; };"
+ + " sb.value = '';"
+ + " sb.x = 0;"
+ + " sb.y = 0;"
+ + " sb.width = 0;"
+ + " sb.height = 0;"
+ + " sb.selectionStart = 0;"
+ + " sb.selectionEnd = 0;"
+ + " sb.verbatim = false;"
+ + "}"
+ + "})();";
+
+ private static final String SET_QUERY_SCRIPT
+ = "if (window.chrome && window.chrome.searchBox) {"
+ + " window.chrome.searchBox.setValue(%s);"
+ + "}";
+
+ private static final String SET_VERBATIM_SCRIPT
+ = "if (window.chrome && window.chrome.searchBox) {"
+ + " window.chrome.searchBox.verbatim = %s;"
+ + "}";
+
+ private static final String SET_SELECTION_SCRIPT
+ = "if (window.chrome && window.chrome.searchBox) {"
+ + " var f = window.chrome.searchBox;"
+ + " f.selectionStart = %d"
+ + " f.selectionEnd = %d"
+ + "}";
+
+ private static final String SET_DIMENSIONS_SCRIPT
+ = "if (window.chrome && window.chrome.searchBox) { "
+ + " var f = window.chrome.searchBox;"
+ + " f.x = %d;"
+ + " f.y = %d;"
+ + " f.width = %d;"
+ + " f.height = %d;"
+ + "}";
+
+ private static final String DISPATCH_EVENT_SCRIPT
+ = "if (window.chrome && window.chrome.searchBox &&"
+ + " window.chrome.searchBox.on%1$s) { window.chrome.searchBox.on%1$s(); }";
+
+ private final List<SearchBoxListener> mListeners;
+ private final WebViewCore mWebViewCore;
+ private final CallbackProxy mCallbackProxy;
+
+ SearchBoxImpl(WebViewCore webViewCore, CallbackProxy callbackProxy) {
+ mListeners = new ArrayList<SearchBoxListener>();
+ mWebViewCore = webViewCore;
+ mCallbackProxy = callbackProxy;
+ }
+
+ @Override
+ public void setQuery(String query) {
+ final String formattedQuery = jsonSerialize(query);
+ if (formattedQuery != null) {
+ final String js = String.format(SET_QUERY_SCRIPT, formattedQuery);
+ dispatchJs(js);
+ }
+ }
+
+ @Override
+ public void setVerbatim(boolean verbatim) {
+ final String js = String.format(SET_VERBATIM_SCRIPT, String.valueOf(verbatim));
+ dispatchJs(js);
+ }
+
+
+ @Override
+ public void setSelection(int selectionStart, int selectionEnd) {
+ final String js = String.format(SET_SELECTION_SCRIPT, selectionStart, selectionEnd);
+ dispatchJs(js);
+ }
+
+ @Override
+ public void setDimensions(int x, int y, int width, int height) {
+ final String js = String.format(SET_DIMENSIONS_SCRIPT, x, y, width, height);
+ dispatchJs(js);
+ }
+
+ @Override
+ public void onchange() {
+ dispatchEvent("change");
+ }
+
+ @Override
+ public void onsubmit() {
+ dispatchEvent("submit");
+ }
+
+ @Override
+ public void onresize() {
+ dispatchEvent("resize");
+ }
+
+ @Override
+ public void oncancel() {
+ dispatchEvent("cancel");
+ }
+
+ private void dispatchEvent(String eventName) {
+ final String js = String.format(DISPATCH_EVENT_SCRIPT, eventName);
+ dispatchJs(js);
+ }
+
+ private void dispatchJs(String js) {
+ mWebViewCore.sendMessage(EventHub.EXECUTE_JS, js);
+ }
+
+ @Override
+ public void addSearchBoxListener(SearchBoxListener l) {
+ synchronized (mListeners) {
+ mListeners.add(l);
+ }
+ }
+
+ @Override
+ public void removeSearchBoxListener(SearchBoxListener l) {
+ synchronized (mListeners) {
+ mListeners.remove(l);
+ }
+ }
+
+ // This is used as a hackish alternative to javascript escaping.
+ // There appears to be no such functionality in the core framework.
+ private String jsonSerialize(String query) {
+ JSONStringer stringer = new JSONStringer();
+ try {
+ stringer.array().value(query).endArray();
+ } catch (JSONException e) {
+ Log.w(TAG, "Error serializing query : " + query);
+ return null;
+ }
+ return stringer.toString();
+ }
+
+ // Called by Javascript through the Java bridge.
+ public void setSuggestions(String jsonArguments) {
+ if (jsonArguments == null) {
+ return;
+ }
+
+ String query = null;
+ List<String> suggestions = new ArrayList<String>();
+ try {
+ JSONObject suggestionsJson = new JSONObject(jsonArguments);
+ query = suggestionsJson.getString("query");
+
+ final JSONArray suggestionsArray = suggestionsJson.getJSONArray("suggestions");
+ for (int i = 0; i < suggestionsArray.length(); ++i) {
+ final JSONObject suggestion = suggestionsArray.getJSONObject(i);
+ final String value = suggestion.getString("value");
+ if (value != null) {
+ suggestions.add(value);
+ }
+ // We currently ignore the "type" of the suggestion. This isn't
+ // documented anywhere in the API documents.
+ // final String type = suggestions.getString("type");
+ }
+ } catch (JSONException je) {
+ Log.w(TAG, "Error parsing json [" + jsonArguments + "], exception = " + je);
+ return;
+ }
+
+ mCallbackProxy.onSearchboxSuggestionsReceived(query, suggestions);
+ }
+
+ /* package */ void handleSuggestions(String query, List<String> suggestions) {
+ synchronized (mListeners) {
+ for (int i = mListeners.size() - 1; i >= 0; i--) {
+ mListeners.get(i).onSuggestionsReceived(query, suggestions);
+ }
+ }
+ }
+}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index af20ddbbcfe6..975f81570964 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -5033,6 +5033,13 @@ public class WebView extends AbsoluteLayout
}
/**
+ * @hide pending API Council approval.
+ */
+ public SearchBox getSearchBox() {
+ return mWebViewCore.getBrowserFrame().getSearchBox();
+ }
+
+ /**
* Returns the currently highlighted text as a string.
*/
String getSelection() {
@@ -8389,7 +8396,7 @@ public class WebView extends AbsoluteLayout
private native void nativeSetFindIsUp(boolean isUp);
private native void nativeSetHeightCanMeasure(boolean measure);
private native void nativeSetBaseLayer(int layer, Rect invalRect,
- boolean showVisualIndciator);
+ boolean showVisualIndicator);
private native void nativeShowCursorTimed();
private native void nativeReplaceBaseContent(int content);
private native void nativeCopyBaseContentToPicture(Picture pict);
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 38288c58638a..c18c9e498db0 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1003,6 +1003,8 @@ final class WebViewCore {
static final int PROXY_CHANGED = 193;
+ static final int EXECUTE_JS = 194;
+
// private message ids
private static final int DESTROY = 200;
@@ -1562,6 +1564,15 @@ final class WebViewCore {
mWebView.mPrivateHandler.obtainMessage(WebView.AUTOFILL_COMPLETE, null)
.sendToTarget();
break;
+
+ case EXECUTE_JS:
+ if (msg.obj instanceof String) {
+ if (DebugFlags.WEB_VIEW_CORE) {
+ Log.d(LOGTAG, "Executing JS : " + msg.obj);
+ }
+ mBrowserFrame.stringByEvaluatingJavaScriptFromString((String) msg.obj);
+ }
+ break;
}
}
};
diff --git a/core/java/android/widget/EdgeGlow.java b/core/java/android/widget/EdgeGlow.java
index c2cb0a053659..75cef3810ae8 100644
--- a/core/java/android/widget/EdgeGlow.java
+++ b/core/java/android/widget/EdgeGlow.java
@@ -260,7 +260,7 @@ public class EdgeGlow {
glowHeight * MAX_GLOW_HEIGHT);
if (mWidth < mMinWidth) {
// Center the glow and clip it.
- int glowLeft = (mWidth - glowWidth)/2;
+ int glowLeft = (mWidth - mMinWidth)/2;
mGlow.setBounds(glowLeft, 0, mWidth - glowLeft, glowBottom);
} else {
// Stretch the glow to fit.
@@ -274,7 +274,7 @@ public class EdgeGlow {
int edgeBottom = (int) (edgeHeight * mEdgeScaleY);
if (mWidth < mMinWidth) {
// Center the edge and clip it.
- int edgeLeft = (mWidth - edgeWidth)/2;
+ int edgeLeft = (mWidth - mMinWidth)/2;
mEdge.setBounds(edgeLeft, 0, mWidth - edgeLeft, edgeBottom);
} else {
// Stretch the edge to fit.
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 22edcd0e9462..2d164fd75812 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -96,6 +96,7 @@ public class SearchView extends LinearLayout {
private boolean mVoiceButtonEnabled;
private SearchableInfo mSearchable;
+ private Bundle mAppSearchData;
// For voice searching
private final Intent mVoiceWebSearchIntent;
@@ -263,6 +264,15 @@ public class SearchView extends LinearLayout {
updateViewsVisibility(mIconifiedByDefault);
}
+ /**
+ * Sets the APP_DATA for legacy SearchDialog use.
+ * @param appSearchData bundle provided by the app when launching the search dialog
+ * @hide
+ */
+ public void setAppSearchData(Bundle appSearchData) {
+ mAppSearchData = appSearchData;
+ }
+
/** @hide */
@Override
public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
@@ -1115,6 +1125,9 @@ public class SearchView extends LinearLayout {
if (extraData != null) {
intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData);
}
+ if (mAppSearchData != null) {
+ intent.putExtra(SearchManager.APP_DATA, mAppSearchData);
+ }
if (actionKey != KeyEvent.KEYCODE_UNKNOWN) {
intent.putExtra(SearchManager.ACTION_KEY, actionKey);
intent.putExtra(SearchManager.ACTION_MSG, actionMsg);
diff --git a/core/res/res/drawable-hdpi/stat_sys_adb.png b/core/res/res/drawable-hdpi/stat_sys_adb.png
index 58c17468f7cd..af713e87a41f 100755
--- a/core/res/res/drawable-hdpi/stat_sys_adb.png
+++ b/core/res/res/drawable-hdpi/stat_sys_adb.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_adb.png b/core/res/res/drawable-ldpi/stat_sys_adb.png
index cdead240aab5..86b945b5f16b 100644
--- a/core/res/res/drawable-ldpi/stat_sys_adb.png
+++ b/core/res/res/drawable-ldpi/stat_sys_adb.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_adb.png b/core/res/res/drawable-mdpi/stat_sys_adb.png
index 255ce949ff02..2c4d2b575df3 100644
--- a/core/res/res/drawable-mdpi/stat_sys_adb.png
+++ b/core/res/res/drawable-mdpi/stat_sys_adb.png
Binary files differ
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index b2dc1e3f5122..74d65d190a1c 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -794,6 +794,15 @@ public class MediaScanner
long time = exif.getGpsDateTime();
if (time != -1) {
values.put(Images.Media.DATE_TAKEN, time);
+ } else {
+ // If no time zone information is available, we should consider using
+ // EXIF local time as taken time if the difference between file time
+ // and EXIF local time is not less than 1 Day, otherwise MediaProvider
+ // will use file time as taken time.
+ time = exif.getDateTime();
+ if (Math.abs(mLastModified * 1000 - time) >= 86400000) {
+ values.put(Images.Media.DATE_TAKEN, time);
+ }
}
int orientation = exif.getAttributeInt(
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg.9.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg.9.png
deleted file mode 100644
index 85d9795d90d3..000000000000
--- a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_normal.9.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_normal.9.png
new file mode 100644
index 000000000000..2266d15c2b5b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png
new file mode 100644
index 000000000000..4fc6b46a767d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_veto_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_veto_pressed.png
index 3b7c9c7c9da5..653acbbe0c13 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_veto_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_veto_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/notify_panel_clock_bg.xml b/packages/SystemUI/res/drawable/notify_panel_clock_bg.xml
new file mode 100644
index 000000000000..c83d8783786c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/notify_panel_clock_bg.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true"
+ android:drawable="@drawable/notify_panel_clock_bg_pressed" />
+ <item android:drawable="@drawable/notify_panel_clock_bg_normal" />
+</selector>
+
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel_title.xml b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel_title.xml
index 0cf28a79da57..1afb2e3f1254 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel_title.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel_title.xml
@@ -22,6 +22,7 @@
android:layout_height="0dp"
android:orientation="vertical"
android:background="@drawable/notify_panel_clock_bg"
+ android:clickable="true"
>
<LinearLayout
android:id="@+id/icons"
@@ -171,10 +172,12 @@
android:layout_marginLeft="32dp"
/>
- <Button
+ <view
+ class="com.android.systemui.statusbar.tablet.NotificationPanel$ModeToggle"
android:id="@+id/mode_toggle"
android:background="@null"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:clickable="true"
/>
</RelativeLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index e81cec2290ac..c82220dbb552 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -129,13 +129,14 @@ public class KeyButtonView extends ImageView {
setPressed(false);
if (mSending) {
mSending = false;
+ final int flags = KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY;
removeCallbacks(mCheckLongPress);
if (doIt) {
- sendEvent(KeyEvent.ACTION_UP,
- KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY);
-
+ sendEvent(KeyEvent.ACTION_UP, flags);
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
playSoundEffect(SoundEffectConstants.CLICK);
+ } else {
+ sendEvent(KeyEvent.ACTION_UP, flags | KeyEvent.FLAG_CANCELED);
}
}
break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index 8a88792a38e7..64a4f160830f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -28,7 +28,10 @@ import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Slog;
+import android.view.accessibility.AccessibilityEvent;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.SoundEffectConstants;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
@@ -51,7 +54,7 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel,
boolean mShowing;
int mNotificationCount = 0;
View mTitleArea;
- View mModeToggle;
+ ModeToggle mModeToggle;
View mSettingsButton;
View mNotificationButton;
View mNotificationScroller;
@@ -65,6 +68,48 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel,
Choreographer mChoreo = new Choreographer();
+ static class ModeToggle extends View {
+ NotificationPanel mPanel;
+ View mTitle;
+ public ModeToggle(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+ public void setPanel(NotificationPanel p) {
+ mPanel = p;
+ }
+ public void setTitleArea(View v) {
+ mTitle = v;
+ }
+ @Override
+ public boolean onTouchEvent(MotionEvent e) {
+ final int x = (int)e.getX();
+ final int y = (int)e.getY();
+ switch (e.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mTitle.setPressed(true);
+ break;
+ case MotionEvent.ACTION_MOVE:
+ mTitle.setPressed(x >= 0
+ && x < getWidth()
+ && y >= 0
+ && y < getHeight());
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ mTitle.setPressed(false);
+ break;
+ case MotionEvent.ACTION_UP:
+ if (mTitle.isPressed()) {
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
+ playSoundEffect(SoundEffectConstants.CLICK);
+ mPanel.swapPanels();
+ mTitle.setPressed(false);
+ }
+ break;
+ }
+ return true;
+ }
+ }
+
public NotificationPanel(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -82,8 +127,10 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel,
mContentParent = (ViewGroup)findViewById(R.id.content_parent);
mContentParent.bringToFront();
mTitleArea = findViewById(R.id.title_area);
- mModeToggle = findViewById(R.id.mode_toggle);
+ mModeToggle = (ModeToggle) findViewById(R.id.mode_toggle);
mModeToggle.setOnClickListener(this);
+ mModeToggle.setPanel(this);
+ mModeToggle.setTitleArea(mTitleArea);
mSettingsButton = (ImageView)findViewById(R.id.settings_button);
mNotificationButton = (ImageView)findViewById(R.id.notification_button);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
index 1135b73c6736..737a52beab1f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
@@ -362,6 +362,9 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O
mRecentsContainer.addFooterView(footer, null, false);
mRecentsContainer.setAdapter(mListAdapter = new ActvityDescriptionAdapter(mContext));
mRecentsContainer.setOnItemClickListener(this);
+ final int leftPadding = mContext.getResources()
+ .getDimensionPixelOffset(R.dimen.status_bar_recents_thumbnail_left_margin);
+ mRecentsContainer.setOverScrollEffectPadding(leftPadding, 0);
mRecentsGlowView = findViewById(R.id.recents_glow);
mRecentsScrim = (View) findViewById(R.id.recents_bg_protect);
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 436eff0befbe..91ada6bf52b1 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -374,7 +374,7 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
done = true;
} else {
// Eliminate system process here?
- ams.killPids(pids, "unmount media");
+ ams.killPids(pids, "unmount media", true);
// Confirm if file references have been freed.
pids = getStorageUsers(path);
if (pids == null || pids.length == 0) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 40417b18daa9..0fab964b5fd8 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -6189,7 +6189,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- public boolean killPids(int[] pids, String pReason) {
+ public boolean killPids(int[] pids, String pReason, boolean secure) {
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("killPids only available to the system");
}
@@ -6212,11 +6212,18 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- // If the worse oom_adj is somewhere in the hidden proc LRU range,
+ // If the worst oom_adj is somewhere in the hidden proc LRU range,
// then constrain it so we will kill all hidden procs.
if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
worstType = HIDDEN_APP_MIN_ADJ;
}
+
+ // If this is not a secure call, don't let it kill processes that
+ // are important.
+ if (!secure && worstType < SECONDARY_SERVER_ADJ) {
+ worstType = SECONDARY_SERVER_ADJ;
+ }
+
Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
for (int i=0; i<pids.length; i++) {
ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
diff --git a/services/java/com/android/server/usb/UsbDeviceSettingsManager.java b/services/java/com/android/server/usb/UsbDeviceSettingsManager.java
index 9a96e7fe4c3d..2f22fe1a5d7c 100644
--- a/services/java/com/android/server/usb/UsbDeviceSettingsManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceSettingsManager.java
@@ -615,8 +615,11 @@ class UsbDeviceSettingsManager {
defaultPackage = mDevicePreferenceMap.get(new DeviceFilter(device));
}
+ int count = matches.size();
+ // don't show the resolver activity if there are no choices available
+ if (count == 0) return;
+
if (defaultPackage != null) {
- int count = matches.size();
for (int i = 0; i < count; i++) {
ResolveInfo rInfo = matches.get(i);
if (rInfo.activityInfo != null &&
@@ -666,8 +669,11 @@ class UsbDeviceSettingsManager {
defaultPackage = mAccessoryPreferenceMap.get(new AccessoryFilter(accessory));
}
+ int count = matches.size();
+ // don't show the resolver activity if there are no choices available
+ if (count == 0) return;
+
if (defaultPackage != null) {
- int count = matches.size();
for (int i = 0; i < count; i++) {
ResolveInfo rInfo = matches.get(i);
if (rInfo.activityInfo != null &&
diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java
index b9db17702a81..0f09356f95e5 100644
--- a/services/java/com/android/server/wm/Session.java
+++ b/services/java/com/android/server/wm/Session.java
@@ -161,6 +161,10 @@ final class Session extends IWindowSession.Stub
return res;
}
+ public boolean outOfMemory(IWindow window) {
+ return mService.outOfMemoryWindow(this, window);
+ }
+
public void setTransparentRegion(IWindow window, Region region) {
mService.setTransparentRegionWindow(this, window, region);
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index b5d84e87f382..eed41a0c0e9a 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -2717,6 +2717,22 @@ public class WindowManagerService extends IWindowManager.Stub
| (displayed ? WindowManagerImpl.RELAYOUT_FIRST_TIME : 0);
}
+ public boolean outOfMemoryWindow(Session session, IWindow client) {
+ long origId = Binder.clearCallingIdentity();
+
+ try {
+ synchronized(mWindowMap) {
+ WindowState win = windowForClientLocked(session, client, false);
+ if (win == null) {
+ return false;
+ }
+ return reclaimSomeSurfaceMemoryLocked(win, "from-client", false);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
public void finishDrawingWindow(Session session, IWindow client) {
final long origId = Binder.clearCallingIdentity();
synchronized(mWindowMap) {
@@ -7443,7 +7459,7 @@ public class WindowManagerService extends IWindowManager.Stub
+ " pos=(" + w.mShownFrame.left
+ "," + w.mShownFrame.top + ")", e);
if (!recoveringMemory) {
- reclaimSomeSurfaceMemoryLocked(w, "position");
+ reclaimSomeSurfaceMemoryLocked(w, "position", true);
}
}
}
@@ -7471,7 +7487,7 @@ public class WindowManagerService extends IWindowManager.Stub
Slog.e(TAG, "Error resizing surface of " + w
+ " size=(" + width + "x" + height + ")", e);
if (!recoveringMemory) {
- reclaimSomeSurfaceMemoryLocked(w, "size");
+ reclaimSomeSurfaceMemoryLocked(w, "size", true);
}
}
}
@@ -7618,7 +7634,7 @@ public class WindowManagerService extends IWindowManager.Stub
} catch (RuntimeException e) {
Slog.w(TAG, "Error updating surface in " + w, e);
if (!recoveringMemory) {
- reclaimSomeSurfaceMemoryLocked(w, "update");
+ reclaimSomeSurfaceMemoryLocked(w, "update", true);
}
}
}
@@ -8077,13 +8093,15 @@ public class WindowManagerService extends IWindowManager.Stub
Slog.w(TAG, "Failure showing surface " + win.mSurface + " in " + win, e);
}
- reclaimSomeSurfaceMemoryLocked(win, "show");
+ reclaimSomeSurfaceMemoryLocked(win, "show", true);
return false;
}
- void reclaimSomeSurfaceMemoryLocked(WindowState win, String operation) {
+ boolean reclaimSomeSurfaceMemoryLocked(WindowState win, String operation, boolean secure) {
final Surface surface = win.mSurface;
+ boolean leakedSurface = false;
+ boolean killedApps = false;
EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, win.toString(),
win.mSession.mPid, operation);
@@ -8098,7 +8116,6 @@ public class WindowManagerService extends IWindowManager.Stub
// window list to make sure we haven't left any dangling surfaces
// around.
int N = mWindows.size();
- boolean leakedSurface = false;
Slog.i(TAG, "Out of memory for surface! Looking for leaks...");
for (int i=0; i<N; i++) {
WindowState ws = mWindows.get(i);
@@ -8130,7 +8147,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- boolean killedApps = false;
if (!leakedSurface) {
Slog.w(TAG, "No leaked surfaces; killing applicatons!");
SparseIntArray pidCandidates = new SparseIntArray();
@@ -8146,7 +8162,7 @@ public class WindowManagerService extends IWindowManager.Stub
pids[i] = pidCandidates.keyAt(i);
}
try {
- if (mActivityManager.killPids(pids, "Free memory")) {
+ if (mActivityManager.killPids(pids, "Free memory", secure)) {
killedApps = true;
}
} catch (RemoteException e) {
@@ -8173,6 +8189,8 @@ public class WindowManagerService extends IWindowManager.Stub
} finally {
Binder.restoreCallingIdentity(callingIdentity);
}
+
+ return leakedSurface || killedApps;
}
private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index d0eec898c3af..f8ff5f8133b6 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -594,7 +594,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
+ " / " + this);
} catch (Surface.OutOfResourcesException e) {
Slog.w(WindowManagerService.TAG, "OutOfResourcesException creating surface");
- mService.reclaimSomeSurfaceMemoryLocked(this, "create");
+ mService.reclaimSomeSurfaceMemoryLocked(this, "create", true);
return null;
} catch (Exception e) {
Slog.e(WindowManagerService.TAG, "Exception creating surface", e);
@@ -628,7 +628,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
} catch (RuntimeException e) {
Slog.w(WindowManagerService.TAG, "Error creating surface in " + w, e);
- mService.reclaimSomeSurfaceMemoryLocked(this, "create-init");
+ mService.reclaimSomeSurfaceMemoryLocked(this, "create-init", true);
}
mLastHidden = true;
} finally {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
index 8422d4890b0a..ab8c4ec75152 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -85,6 +85,10 @@ public final class BridgeWindowSession implements IWindowSession {
return 0;
}
+ public boolean outOfMemory(IWindow window) throws RemoteException {
+ return false;
+ }
+
public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
// pass for now.
}