Merge change 25954 into eclair
* changes:
Moving DISPLAY_NAME to column "data1" to keep it "aligned" with other data types.
diff --git a/cmds/keystore/Android.mk b/cmds/keystore/Android.mk
index 8804636..15a199f 100644
--- a/cmds/keystore/Android.mk
+++ b/cmds/keystore/Android.mk
@@ -1,22 +1,36 @@
+#
+# 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.
+#
+
ifneq ($(TARGET_SIMULATOR),true)
LOCAL_PATH:= $(call my-dir)
+
include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- netkeystore.c netkeystore_main.c keymgmt.c
-
-LOCAL_C_INCLUDES := \
- $(call include-path-for, system-core)/cutils \
- external/openssl/include
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils libssl
-
-LOCAL_STATIC_LIBRARIES :=
-
+LOCAL_SRC_FILES := keystore.c
+LOCAL_C_INCLUDES := external/openssl/include
+LOCAL_SHARED_LIBRARIES := libcutils libcrypto
LOCAL_MODULE:= keystore
-
include $(BUILD_EXECUTABLE)
-endif # !simulator))
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := keystore_cli.c
+LOCAL_C_INCLUDES := external/openssl/include
+LOCAL_SHARED_LIBRARIES := libcutils libcrypto
+LOCAL_MODULE:= keystore_cli
+LOCAL_MODULE_TAGS := debug
+include $(BUILD_EXECUTABLE)
+
+endif
diff --git a/cmds/keystore/keystore.c b/cmds/keystore/keystore.c
index 2bcba97..ec4e2a2 100644
--- a/cmds/keystore/keystore.c
+++ b/cmds/keystore/keystore.c
@@ -125,6 +125,12 @@
return length;
}
+static int recv_end_of_file()
+{
+ uint8_t byte;
+ return recv(the_socket, &byte, 1, 0) == 0;
+}
+
static void send_code(int8_t code)
{
send(the_socket, &code, 1, 0);
@@ -217,8 +223,10 @@
/* Here are the actions. Each of them is a function without arguments. All
* information is defined in global variables, which are set properly before
* performing an action. The number of parameters required by each action is
- * fixed and defined in a table. Note that the lengths of parameters are checked
- * when they are received, so boundary checks on parameters are omitted. */
+ * fixed and defined in a table. If the return value of an action is positive,
+ * it will be treated as a response code and transmitted to the client. Note
+ * that the lengths of parameters are checked when they are received, so
+ * boundary checks on parameters are omitted. */
#define MAX_PARAM 2
#define MAX_RETRY 4
@@ -321,12 +329,10 @@
return SYSTEM_ERROR;
}
while ((file = readdir(dir)) != NULL) {
- if (strcmp(".", file->d_name) || strcmp("..", file->d_name)) {
- unlink(file->d_name);
- }
+ unlink(file->d_name);
}
closedir(dir);
- return UNINITIALIZED;
+ return NO_ERROR;
}
#define MASTER_KEY_FILE ".masterkey"
@@ -358,7 +364,8 @@
}
if (n != NO_ERROR || blob.length != MASTER_KEY_SIZE) {
if (retry <= 0) {
- return reset();
+ reset();
+ return UNINITIALIZED;
}
return WRONG_PASSWORD + --retry;
}
@@ -387,7 +394,7 @@
memset(&encryption_key, 0, sizeof(encryption_key));
memset(&decryption_key, 0, sizeof(decryption_key));
state = LOCKED;
- return LOCKED;
+ return NO_ERROR;
}
static int8_t unlock()
@@ -421,9 +428,9 @@
{test, 't', 0, TEST, {0}},
{get, 'g', NO_ERROR, GET, {KEY_SIZE}},
{insert, 'i', NO_ERROR, INSERT, {KEY_SIZE, VALUE_SIZE}},
- {delete, 'd', NO_ERROR, DELETE, {KEY_SIZE}},
- {exist, 'e', NO_ERROR, EXIST, {KEY_SIZE}},
- {scan, 's', NO_ERROR, SCAN, {KEY_SIZE}},
+ {delete, 'd', 0, DELETE, {KEY_SIZE}},
+ {exist, 'e', 0, EXIST, {KEY_SIZE}},
+ {scan, 's', 0, SCAN, {KEY_SIZE}},
{reset, 'r', 0, RESET, {0}},
{password, 'p', 0, PASSWORD, {PASSWORD_SIZE, PASSWORD_SIZE}},
{lock, 'l', NO_ERROR, LOCK, {0}},
@@ -471,6 +478,9 @@
return PROTOCOL_ERROR;
}
}
+ if (!recv_end_of_file()) {
+ return PROTOCOL_ERROR;
+ }
return action->run();
}
diff --git a/cmds/keystore/keystore_cli.c b/cmds/keystore/keystore_cli.c
index b0b76ff..e8afb5a 100644
--- a/cmds/keystore/keystore_cli.c
+++ b/cmds/keystore/keystore_cli.c
@@ -53,8 +53,8 @@
return 0;
}
- sock = socket_local_client("keystore",
- ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+ sock = socket_local_client("keystore", ANDROID_SOCKET_NAMESPACE_RESERVED,
+ SOCK_STREAM);
if (sock == -1) {
puts("Failed to connect");
return 1;
diff --git a/cmds/keystore/keystore_get.h b/cmds/keystore/keystore_get.h
index 7665e81..0e7e1ae 100644
--- a/cmds/keystore/keystore_get.h
+++ b/cmds/keystore/keystore_get.h
@@ -1,53 +1,69 @@
/*
-**
-** Copyright 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.
-*/
+ * 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.
+ */
#ifndef __KEYSTORE_GET_H__
#define __KEYSTORE_GET_H__
#include <stdio.h>
-#include <stdlib.h>
+#include <stdint.h>
#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
-#include "certtool.h"
+#include <cutils/sockets.h>
-/* This function is provided to native components to get values from keystore.
- * Users are required to link against libcutils. If something goes wrong, NULL
- * is returned. Otherwise it returns the value in dynamically allocated memory
- * and sets the size if the pointer is not NULL. One can release the memory by
- * calling free(). */
-static char *keystore_get(const char *key, int *size)
+#define KEYSTORE_MESSAGE_SIZE 65535
+
+/* This function is provided for native components to get values from keystore.
+ * Users are required to link against libcutils. The lengths of keys and values
+ * are limited to KEYSTORE_MESSAGE_SIZE. This function returns the length of
+ * the requested value or -1 if something goes wrong. */
+static int keystore_get(const char *key, char *value)
{
- char buffer[MAX_KEY_VALUE_LENGTH];
- char *value;
- int length;
+ int length = strlen(key);
+ uint8_t bytes[2] = {length >> 8, length};
+ uint8_t code = 'g';
+ int sock;
- if (get_cert(key, (unsigned char *)buffer, &length) != 0) {
- return NULL;
+ if (length > KEYSTORE_MESSAGE_SIZE) {
+ return -1;
}
- value = malloc(length + 1);
- if (!value) {
- return NULL;
+ sock = socket_local_client("keystore", ANDROID_SOCKET_NAMESPACE_RESERVED,
+ SOCK_STREAM);
+ if (sock == -1) {
+ return -1;
}
- memcpy(value, buffer, length);
- value[length] = 0;
- if (size) {
- *size = length;
+ if (send(sock, &code, 1, 0) == 1 && send(sock, bytes, 2, 0) == 2 &&
+ send(sock, key, length, 0) == length && shutdown(sock, SHUT_WR) == 0 &&
+ recv(sock, &code, 1, 0) == 1 && code == /* NO_ERROR */ 1 &&
+ recv(sock, &bytes[0], 1, 0) == 1 && recv(sock, &bytes[1], 1, 0) == 1) {
+ int offset = 0;
+ length = bytes[0] << 8 | bytes[1];
+ while (offset < length) {
+ int n = recv(sock, &value[offset], length - offset, 0);
+ if (n <= 0) {
+ length = -1;
+ break;
+ }
+ offset += n;
+ }
}
- return value;
+ close(sock);
+ return length;
}
#endif
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index d05c9ab..caf72af 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -736,7 +736,8 @@
return false;
}
- if (keyCode == KeyEvent.KEYCODE_SEARCH) {
+ if (keyCode == KeyEvent.KEYCODE_SEARCH && event.getRepeatCount() == 0) {
+ event.startTracking();
// Consume search key for later use.
return true;
}
@@ -1181,7 +1182,7 @@
// report back about the click
if (mGlobalSearchMode) {
// in global search mode, do it via cursor
- mSuggestionsAdapter.callCursorOnClick(c, position);
+ mSuggestionsAdapter.callCursorOnClick(c, position, actionKey, actionMsg);
} else if (intent != null
&& mPreviousComponents != null
&& !mPreviousComponents.isEmpty()) {
@@ -1218,7 +1219,7 @@
cv.put(SearchManager.SUGGEST_COLUMN_INTENT_ACTION, intent.getAction());
cv.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA, intent.getDataString());
cv.put(SearchManager.SUGGEST_COLUMN_INTENT_COMPONENT_NAME,
- intent.getStringExtra(SearchManager.COMPONENT_NAME_KEY));
+ intent.getComponent().flattenToShortString());
// ensure the icons will work for global search
cv.put(SearchManager.SUGGEST_COLUMN_ICON_1,
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 3a14f6f..6a0285d 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1343,6 +1343,10 @@
= "DialogCursorProtocol.CLICK.sendPosition";
public final static String CLICK_SEND_MAX_DISPLAY_POS
= "DialogCursorProtocol.CLICK.sendDisplayPosition";
+ public final static String CLICK_SEND_ACTION_KEY
+ = "DialogCursorProtocol.CLICK.sendActionKey";
+ public final static String CLICK_SEND_ACTION_MSG
+ = "DialogCursorProtocol.CLICK.sendActionMsg";
public final static String CLICK_RECEIVE_SELECTED_POS
= "DialogCursorProtocol.CLICK.receiveSelectedPosition";
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 4f9531e..9234a9c 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -26,7 +26,6 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.Cursor;
-import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
@@ -37,6 +36,7 @@
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
+import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
@@ -47,7 +47,6 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.util.List;
import java.util.WeakHashMap;
/**
@@ -290,12 +289,16 @@
* @param cursor The cursor
* @param position The position that was clicked.
*/
- void callCursorOnClick(Cursor cursor, int position) {
+ void callCursorOnClick(Cursor cursor, int position, int actionKey, String actionMsg) {
if (!mGlobalSearchMode) return;
- final Bundle request = new Bundle(3);
+ final Bundle request = new Bundle(5);
request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.CLICK);
request.putInt(DialogCursorProtocol.CLICK_SEND_POSITION, position);
request.putInt(DialogCursorProtocol.CLICK_SEND_MAX_DISPLAY_POS, mMaxDisplayed);
+ if (actionKey != KeyEvent.KEYCODE_UNKNOWN) {
+ request.putInt(DialogCursorProtocol.CLICK_SEND_ACTION_KEY, actionKey);
+ request.putString(DialogCursorProtocol.CLICK_SEND_ACTION_MSG, actionMsg);
+ }
final Bundle response = cursor.respond(request);
mMaxDisplayed = -1;
mListItemToSelect = response.getInt(
@@ -569,69 +572,91 @@
if (drawableId == null || drawableId.length() == 0 || "0".equals(drawableId)) {
return null;
}
-
- // First, check the cache.
- Drawable.ConstantState cached = mOutsideDrawablesCache.get(drawableId);
- if (cached != null) {
- if (DBG) Log.d(LOG_TAG, "Found icon in cache: " + drawableId);
- return cached.newDrawable(mProviderContext.getResources());
- }
-
- Drawable drawable = null;
try {
- // Not cached, try using it as a plain resource ID in the provider's context.
+ // First, see if it's just an integer
int resourceId = Integer.parseInt(drawableId);
+ // It's an int, look for it in the cache
+ String drawableUri = ContentResolver.SCHEME_ANDROID_RESOURCE
+ + "://" + mProviderContext.getPackageName() + "/" + resourceId;
+ // Must use URI as cache key, since ints are app-specific
+ Drawable drawable = checkIconCache(drawableUri);
+ if (drawable != null) {
+ return drawable;
+ }
+ // Not cached, find it by resource ID
drawable = mProviderContext.getResources().getDrawable(resourceId);
+ // Stick it in the cache, using the URI as key
+ storeInIconCache(drawableUri, drawable);
+ return drawable;
} catch (NumberFormatException nfe) {
- // The id was not an integer resource id, use it as a URI
- try {
- Uri uri = Uri.parse(drawableId);
- String scheme = uri.getScheme();
- if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
- // Load drawables through Resources, to get the source density information
- OpenResourceIdResult r =
- mProviderContext.getContentResolver().getResourceId(uri);
+ // It's not an integer, use it as a URI
+ Drawable drawable = checkIconCache(drawableId);
+ if (drawable != null) {
+ return drawable;
+ }
+ Uri uri = Uri.parse(drawableId);
+ drawable = getDrawable(uri);
+ storeInIconCache(drawableId, drawable);
+ return drawable;
+ } catch (Resources.NotFoundException nfe) {
+ // It was an integer, but it couldn't be found, bail out
+ Log.w(LOG_TAG, "Icon resource not found: " + drawableId);
+ return null;
+ }
+ }
+
+ /**
+ * Gets a drawable by URI, without using the cache.
+ *
+ * @return A drawable, or {@code null} if the drawable could not be loaded.
+ */
+ private Drawable getDrawable(Uri uri) {
+ try {
+ String scheme = uri.getScheme();
+ if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
+ // Load drawables through Resources, to get the source density information
+ OpenResourceIdResult r =
+ mProviderContext.getContentResolver().getResourceId(uri);
+ try {
+ return r.r.getDrawable(r.id);
+ } catch (Resources.NotFoundException ex) {
+ throw new FileNotFoundException("Resource does not exist: " + uri);
+ }
+ } else {
+ // Let the ContentResolver handle content and file URIs.
+ InputStream stream = mProviderContext.getContentResolver().openInputStream(uri);
+ if (stream == null) {
+ throw new FileNotFoundException("Failed to open " + uri);
+ }
+ try {
+ return Drawable.createFromStream(stream, null);
+ } finally {
try {
- drawable = r.r.getDrawable(r.id);
- } catch (Resources.NotFoundException ex) {
- throw new FileNotFoundException("Resource does not exist: " + uri);
- }
- } else {
- // Let the ContentResolver handle content and file URIs.
- InputStream stream = mProviderContext.getContentResolver().openInputStream(uri);
- if (stream == null) {
- throw new FileNotFoundException("Failed to open " + uri);
- }
- try {
- drawable = Drawable.createFromStream(stream, null);
- } finally {
- try {
- stream.close();
- } catch (IOException ex) {
- Log.e(LOG_TAG, "Error closing icon stream for " + uri, ex);
- }
+ stream.close();
+ } catch (IOException ex) {
+ Log.e(LOG_TAG, "Error closing icon stream for " + uri, ex);
}
}
- } catch (FileNotFoundException fnfe) {
- Log.w(LOG_TAG, "Icon not found: " + drawableId + ", " + fnfe.getMessage());
- // drawable = null;
}
- } catch (Resources.NotFoundException nfe) {
- Log.w(LOG_TAG, "Icon resource not found: " + drawableId);
- // drawable = null;
+ } catch (FileNotFoundException fnfe) {
+ Log.w(LOG_TAG, "Icon not found: " + uri + ", " + fnfe.getMessage());
+ return null;
}
+ }
- if (drawable == null) {
- if (DBG) Log.d(LOG_TAG, "Didn't find icon: " + drawableId);
- } else {
- if (DBG) {
- Log.d(LOG_TAG, "Found icon: " + drawableId);
- }
- // Cache it so we don't do this lookup again
- mOutsideDrawablesCache.put(drawableId, drawable.getConstantState());
+ private Drawable checkIconCache(String resourceUri) {
+ Drawable.ConstantState cached = mOutsideDrawablesCache.get(resourceUri);
+ if (cached == null) {
+ return null;
}
+ if (DBG) Log.d(LOG_TAG, "Found icon in cache: " + resourceUri);
+ return cached.newDrawable();
+ }
- return drawable;
+ private void storeInIconCache(String resourceUri, Drawable drawable) {
+ if (drawable != null) {
+ mOutsideDrawablesCache.put(resourceUri, drawable.getConstantState());
+ }
}
/**
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 7859d5a..80613d8 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -514,7 +514,7 @@
public SyncStorageEngine getSyncStorageEngine() {
return mSyncStorageEngine;
}
-
+
private void ensureAlarmService() {
if (mAlarmService == null) {
mAlarmService = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
@@ -1125,7 +1125,7 @@
tobj.set(time);
return tobj.format("%Y-%m-%d %H:%M:%S");
}
-
+
protected void dumpSyncState(PrintWriter pw, StringBuilder sb) {
pw.print("sync enabled: "); pw.println(isSyncEnabled());
pw.print("data connected: "); pw.println(mDataConnectionIsConnected);
@@ -1219,13 +1219,13 @@
= mSyncStorageEngine.getAuthority(status.authorityId);
if (authority != null) {
Account curAccount = authority.account;
-
+
if (processedAccounts.contains(curAccount)) {
continue;
}
-
+
processedAccounts.add(curAccount);
-
+
pw.print(" Account "); pw.print(authority.account.name);
pw.print(" "); pw.print(authority.account.type);
pw.println(":");
@@ -1271,7 +1271,7 @@
pw.print(time/1000); pw.print('.'); pw.print((time/100)%10);
pw.print('s');
}
-
+
private void dumpDayStatistic(PrintWriter pw, SyncStorageEngine.DayStats ds) {
pw.print("Success ("); pw.print(ds.successCount);
if (ds.successCount > 0) {
@@ -1285,7 +1285,7 @@
}
pw.println(")");
}
-
+
protected void dumpSyncHistory(PrintWriter pw, StringBuilder sb) {
SyncStorageEngine.DayStats dses[] = mSyncStorageEngine.getDayStatistics();
if (dses != null && dses[0] != null) {
@@ -1295,18 +1295,18 @@
int today = dses[0].day;
int i;
SyncStorageEngine.DayStats ds;
-
+
// Print each day in the current week.
for (i=1; i<=6 && i < dses.length; i++) {
ds = dses[i];
if (ds == null) break;
int delta = today-ds.day;
if (delta > 6) break;
-
+
pw.print(" Day-"); pw.print(delta); pw.print(": ");
dumpDayStatistic(pw, ds);
}
-
+
// Aggregate all following days into weeks and print totals.
int weekDay = today;
while (i < dses.length) {
@@ -1321,7 +1321,7 @@
int delta = weekDay-ds.day;
if (delta > 6) break;
i++;
-
+
if (aggr == null) {
aggr = new SyncStorageEngine.DayStats(weekDay);
}
@@ -1336,7 +1336,7 @@
}
}
}
-
+
ArrayList<SyncStorageEngine.SyncHistoryItem> items
= mSyncStorageEngine.getSyncHistory();
if (items != null && items.size() > 0) {
@@ -2132,7 +2132,8 @@
final long now = System.currentTimeMillis();
EventLog.writeEvent(2720, syncOperation.authority,
- SyncStorageEngine.EVENT_START, source);
+ SyncStorageEngine.EVENT_START, source,
+ syncOperation.account.name.hashCode());
return mSyncStorageEngine.insertStartSyncEvent(
syncOperation.account, syncOperation.authority, now, source);
@@ -2141,7 +2142,8 @@
public void stopSyncEvent(long rowId, SyncOperation syncOperation, String resultMessage,
int upstreamActivity, int downstreamActivity, long elapsedTime) {
EventLog.writeEvent(2720, syncOperation.authority,
- SyncStorageEngine.EVENT_STOP, syncOperation.syncSource);
+ SyncStorageEngine.EVENT_STOP, syncOperation.syncSource,
+ syncOperation.account.name.hashCode());
mSyncStorageEngine.stopSyncEvent(rowId, elapsedTime, resultMessage,
downstreamActivity, upstreamActivity);
@@ -2173,7 +2175,7 @@
syncOperation.pendingOperation = op;
add(syncOperation, op);
}
-
+
if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */);
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index fb33561..2a92e05 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -420,6 +420,7 @@
private static final int STD_SPEED = 480; // pixels per second
// time for the longest scroll animation
private static final int MAX_DURATION = 750; // milliseconds
+ private static final int SLIDE_TITLE_DURATION = 500; // milliseconds
private Scroller mScroller;
private boolean mWrapContent;
@@ -2000,7 +2001,7 @@
getGlobalVisibleRect(r, p);
r.offset(-p.x, -p.y);
if (mFindIsUp) {
- r.bottom -= FIND_HEIGHT;
+ r.bottom -= mFindHeight;
}
}
@@ -2072,9 +2073,6 @@
}
}
- // Make sure this stays in sync with the actual height of the FindDialog.
- private static final int FIND_HEIGHT = 79;
-
@Override
protected int computeVerticalScrollRange() {
if (mDrawHistory) {
@@ -2305,7 +2303,11 @@
* that were found.
*/
public int findAll(String find) {
- mFindIsUp = true;
+ if (mFindIsUp == false) {
+ recordNewContentSize(mContentWidth, mContentHeight + mFindHeight,
+ false);
+ mFindIsUp = true;
+ }
int result = nativeFindAll(find.toLowerCase(), find.toUpperCase());
invalidate();
return result;
@@ -2314,6 +2316,7 @@
// Used to know whether the find dialog is open. Affects whether
// or not we draw the highlights for matches.
private boolean mFindIsUp;
+ private int mFindHeight;
/**
* Return the first substring consisting of the address of a physical
@@ -2369,7 +2372,11 @@
* Clear the highlighting surrounding text matches created by findAll.
*/
public void clearMatches() {
- mFindIsUp = false;
+ if (mFindIsUp) {
+ recordNewContentSize(mContentWidth, mContentHeight - mFindHeight,
+ false);
+ mFindIsUp = false;
+ }
nativeSetFindIsDown();
// Now that the dialog has been removed, ensure that we scroll to a
// location that is not beyond the end of the page.
@@ -2378,6 +2385,16 @@
}
/**
+ * @hide
+ */
+ public void setFindDialogHeight(int height) {
+ if (DebugFlags.WEB_VIEW) {
+ Log.v(LOGTAG, "setFindDialogHeight height=" + height);
+ }
+ mFindHeight = height;
+ }
+
+ /**
* Query the document to see if it contains any image references. The
* message object will be dispatched with arg1 being set to 1 if images
* were found and 0 if the document does not reference any images.
@@ -2419,7 +2436,6 @@
private boolean pinScrollBy(int dx, int dy, boolean animate, int animationDuration) {
return pinScrollTo(mScrollX + dx, mScrollY + dy, animate, animationDuration);
}
-
// helper to pin the scrollTo parameters (already in view coordinates)
// returns true if the scroll was changed
private boolean pinScrollTo(int x, int y, boolean animate, int animationDuration) {
@@ -2431,15 +2447,6 @@
if ((dx | dy) == 0) {
return false;
}
- // By this point we have added in the title bar's height. If the site
- // is trying to scroll to the top of the page, scroll it to the top
- // of the WebView including showing the title bar.
- // mobile sites prefer to scroll to (0, 1), thus the + 1 below
- if (getVisibleTitleHeight() > 0 && x == 0
- && y <= getTitleHeight() + 1) {
- y = 0;
- animate = false;
- }
if (animate) {
// Log.d(LOGTAG, "startScroll: " + dx + " " + dy);
mScroller.startScroll(mScrollX, mScrollY, dx, dy,
@@ -2502,6 +2509,17 @@
int vy = contentToViewY(cy);
// Log.d(LOGTAG, "content scrollTo [" + cx + " " + cy + "] view=[" +
// vx + " " + vy + "]");
+ // Some mobile sites attempt to scroll the title bar off the page by
+ // scrolling to (0,0) or (0,1). If we are at the top left corner of the
+ // page, assume this is an attempt to scroll off the title bar, and
+ // animate the title bar off screen slowly enough that the user can see
+ // it.
+ if (cx == 0 && cy <= 1 && mScrollX == 0 && mScrollY == 0) {
+ pinScrollTo(vx, vy, true, SLIDE_TITLE_DURATION);
+ // Since we are animating, we have not yet reached the desired
+ // scroll position. Do not return true to request another attempt
+ return false;
+ }
pinScrollTo(vx, vy, false, 0);
// If the request was to scroll to a negative coordinate, treat it as if
// it was a request to scroll to 0
@@ -4867,7 +4885,8 @@
final boolean updateLayout = viewSize.x == mLastWidthSent
&& viewSize.y == mLastHeightSent;
recordNewContentSize(draw.mWidthHeight.x,
- draw.mWidthHeight.y, updateLayout);
+ draw.mWidthHeight.y
+ + (mFindIsUp ? mFindHeight : 0), updateLayout);
if (DebugFlags.WEB_VIEW) {
Rect b = draw.mInvalRegion.getBounds();
Log.v(LOGTAG, "NEW_PICTURE_MSG_ID {" +
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 71c6ff5..89581e6 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1172,6 +1172,8 @@
<public type="style" name="Theme.Wallpaper.NoTitleBar.Fullscreen" />
<public type="style" name="Theme.WallpaperSettings" />
<public type="style" name="Theme.Light.WallpaperSettings" />
+ <public type="style" name="TextAppearance.SearchResult.Title" />
+ <public type="style" name="TextAppearance.SearchResult.Subtitle" />
<!-- Semi-transparent background that can be used when placing a dark
themed UI on top of some arbitrary background (such as the
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 04402fd..b29e571 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -59,11 +59,7 @@
<item name="textAppearanceLargeInverse">@android:style/TextAppearance.Large.Inverse</item>
<item name="textAppearanceMediumInverse">@android:style/TextAppearance.Medium.Inverse</item>
<item name="textAppearanceSmallInverse">@android:style/TextAppearance.Small.Inverse</item>
-
- <!-- @hide -->
<item name="textAppearanceSearchResultTitle">@android:style/TextAppearance.SearchResult.Title</item>
-
- <!-- @hide -->
<item name="textAppearanceSearchResultSubtitle">@android:style/TextAppearance.SearchResult.Subtitle</item>
<item name="textAppearanceButton">@android:style/TextAppearance.Widget.Button</item>
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index 28c2992..43042c0b 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -28,9 +28,12 @@
*/
public class Credentials {
private static final String LOGTAG = "Credentials";
- private static final String UNLOCK_ACTION = "android.credentials.UNLOCK";
- private static final String INSTALL_ACTION = "android.credentials.INSTALL";
- private static Credentials singleton;
+
+ public static final String UNLOCK_ACTION = "android.credentials.UNLOCK";
+
+ public static final String INSTALL_ACTION = "android.credentials.INSTALL";
+
+ public static final String SYSTEM_INSTALL_ACTION = "android.credentials.SYSTEM_INSTALL";
/** Key prefix for CA certificates. */
public static final String CA_CERTIFICATE = "CACERT_";
@@ -59,6 +62,8 @@
/** Data type for PKCS12. */
public static final String PKCS12 = "PKCS12";
+ private static Credentials singleton;
+
public static Credentials getInstance() {
if (singleton == null) {
singleton = new Credentials();
@@ -95,4 +100,12 @@
Log.w(LOGTAG, e.toString());
}
}
+
+ public void installFromSdCard(Context context) {
+ try {
+ context.startActivity(new Intent(INSTALL_ACTION));
+ } catch (ActivityNotFoundException e) {
+ Log.w(LOGTAG, e.toString());
+ }
+ }
}
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
new file mode 100644
index 0000000..b47e399
--- /dev/null
+++ b/keystore/java/android/security/KeyStore.java
@@ -0,0 +1,208 @@
+/*
+ * 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.security;
+
+import android.net.LocalSocketAddress;
+import android.net.LocalSocket;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+
+/**
+ * {@hide}
+ */
+public class KeyStore {
+ public static int NO_ERROR = 1;
+ public static int LOCKED = 2;
+ public static int UNINITIALIZED = 3;
+ public static int SYSTEM_ERROR = 4;
+ public static int PROTOCOL_ERROR = 5;
+ public static int PERMISSION_DENIED = 6;
+ public static int KEY_NOT_FOUND = 7;
+ public static int VALUE_CORRUPTED = 8;
+ public static int UNDEFINED_ACTION = 9;
+ public static int WRONG_PASSWORD = 10;
+
+ private static final LocalSocketAddress sAddress = new LocalSocketAddress(
+ "keystore", LocalSocketAddress.Namespace.RESERVED);
+
+ private int mError = NO_ERROR;
+
+ private KeyStore() {}
+
+ public static KeyStore getInstance() {
+ return new KeyStore();
+ }
+
+ public int test() {
+ execute('t');
+ return mError;
+ }
+
+ public byte[] get(byte[] key) {
+ byte[][] values = execute('g', key);
+ return (values == null) ? null : values[0];
+ }
+
+ public String get(String key) {
+ byte[] value = get(key.getBytes());
+ return (value == null) ? null : new String(value);
+ }
+
+ public boolean put(byte[] key, byte[] value) {
+ execute('i', key, value);
+ return mError == NO_ERROR;
+ }
+
+ public boolean put(String key, String value) {
+ return put(key.getBytes(), value.getBytes());
+ }
+
+ public boolean delete(byte[] key) {
+ execute('d', key);
+ return mError == NO_ERROR;
+ }
+
+ public boolean delete(String key) {
+ return delete(key.getBytes());
+ }
+
+ public boolean contains(byte[] key) {
+ execute('e', key);
+ return mError == NO_ERROR;
+ }
+
+ public boolean contains(String key) {
+ return contains(key.getBytes());
+ }
+
+ public byte[][] scan(byte[] prefix) {
+ return execute('s', prefix);
+ }
+
+ public String[] scan(String prefix) {
+ byte[][] values = scan(prefix.getBytes());
+ if (values == null) {
+ return null;
+ }
+ String[] strings = new String[values.length];
+ for (int i = 0; i < values.length; ++i) {
+ strings[i] = new String(values[i]);
+ }
+ return strings;
+ }
+
+ public boolean reset() {
+ execute('r');
+ return mError == NO_ERROR;
+ }
+
+ public boolean password(byte[] oldPassword, byte[] newPassword) {
+ execute('p', oldPassword, newPassword);
+ return mError == NO_ERROR;
+ }
+
+ public boolean password(String oldPassword, String newPassword) {
+ return password(oldPassword.getBytes(), newPassword.getBytes());
+ }
+
+ public boolean password(byte[] password) {
+ return password(password, password);
+ }
+
+ public boolean password(String password) {
+ return password(password.getBytes());
+ }
+
+ public boolean lock() {
+ execute('l');
+ return mError == NO_ERROR;
+ }
+
+ public boolean unlock(byte[] password) {
+ execute('u', password);
+ return mError == NO_ERROR;
+ }
+
+ public boolean unlock(String password) {
+ return unlock(password.getBytes());
+ }
+
+ public int getLastError() {
+ return mError;
+ }
+
+ private byte[][] execute(int code, byte[]... parameters) {
+ mError = PROTOCOL_ERROR;
+
+ for (byte[] parameter : parameters) {
+ if (parameter == null || parameter.length > 65535) {
+ return null;
+ }
+ }
+
+ LocalSocket socket = new LocalSocket();
+ try {
+ socket.connect(sAddress);
+
+ OutputStream out = socket.getOutputStream();
+ out.write(code);
+ for (byte[] parameter : parameters) {
+ out.write(parameter.length >> 8);
+ out.write(parameter.length);
+ out.write(parameter);
+ }
+ out.flush();
+ socket.shutdownOutput();
+
+ InputStream in = socket.getInputStream();
+ code = in.read();
+ if (code == -1) {
+ return null;
+ }
+
+ ArrayList<byte[]> results = new ArrayList<byte[]>();
+ while (true) {
+ int i, j;
+ if ((i = in.read()) == -1) {
+ break;
+ }
+ if ((j = in.read()) == -1) {
+ return null;
+ }
+ byte[] result = new byte[i << 8 | j];
+ for (i = 0; i < result.length; i += j) {
+ if ((j = in.read(result, i, result.length - i)) == -1) {
+ return null;
+ }
+ }
+ results.add(result);
+ }
+ mError = code;
+ return results.toArray(new byte[results.size()][]);
+ } catch (IOException e) {
+ // ignore
+ } finally {
+ try {
+ socket.close();
+ } catch (IOException e) {}
+ }
+ return null;
+ }
+}
diff --git a/services/java/com/android/server/ProcessStats.java b/services/java/com/android/server/ProcessStats.java
index eaab3eb..ac3b723 100644
--- a/services/java/com/android/server/ProcessStats.java
+++ b/services/java/com/android/server/ProcessStats.java
@@ -509,23 +509,26 @@
}
int speed = 0;
String file = readFile("/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state", '\0');
- StringTokenizer st = new StringTokenizer(file, "\n ");
- while (st.hasMoreElements()) {
- String token = st.nextToken();
- try {
- long val = Long.parseLong(token);
- tempSpeeds[speed] = val;
- token = st.nextToken();
- val = Long.parseLong(token);
- tempTimes[speed] = val;
- speed++;
- if (speed == MAX_SPEEDS) break; // No more
- if (localLOGV && out == null) {
- Log.v(TAG, "First time : Speed/Time = " + tempSpeeds[speed - 1]
- + "\t" + tempTimes[speed - 1]);
+ // Note: file may be null on kernels without cpufreq (i.e. the emulator's)
+ if (file != null) {
+ StringTokenizer st = new StringTokenizer(file, "\n ");
+ while (st.hasMoreElements()) {
+ String token = st.nextToken();
+ try {
+ long val = Long.parseLong(token);
+ tempSpeeds[speed] = val;
+ token = st.nextToken();
+ val = Long.parseLong(token);
+ tempTimes[speed] = val;
+ speed++;
+ if (speed == MAX_SPEEDS) break; // No more
+ if (localLOGV && out == null) {
+ Log.v(TAG, "First time : Speed/Time = " + tempSpeeds[speed - 1]
+ + "\t" + tempTimes[speed - 1]);
+ }
+ } catch (NumberFormatException nfe) {
+ Log.i(TAG, "Unable to parse time_in_state");
}
- } catch (NumberFormatException nfe) {
- Log.i(TAG, "Unable to parse time_in_state");
}
}
if (out == null) {
diff --git a/services/java/com/android/server/SystemBackupAgent.java b/services/java/com/android/server/SystemBackupAgent.java
index 17d0f1d..8903ebd 100644
--- a/services/java/com/android/server/SystemBackupAgent.java
+++ b/services/java/com/android/server/SystemBackupAgent.java
@@ -32,23 +32,33 @@
import java.io.IOException;
/**
- * Backup agent for various system-managed data
+ * Backup agent for various system-managed data, currently just the system wallpaper
*/
public class SystemBackupAgent extends BackupHelperAgent {
private static final String TAG = "SystemBackupAgent";
+ // These paths must match what the WallpaperManagerService uses
private static final String WALLPAPER_IMAGE = "/data/data/com.android.settings/files/wallpaper";
private static final String WALLPAPER_INFO = "/data/system/wallpaper_info.xml";
@Override
- public void onCreate() {
+ public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+ ParcelFileDescriptor newState) throws IOException {
+ // We only back up the data under the current "wallpaper" schema with metadata
addHelper("wallpaper", new AbsoluteFileBackupHelper(SystemBackupAgent.this,
new String[] { WALLPAPER_IMAGE, WALLPAPER_INFO }));
+ super.onBackup(oldState, data, newState);
}
@Override
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
throws IOException {
+ // On restore, we also support a previous data schema "system_files"
+ addHelper("wallpaper", new AbsoluteFileBackupHelper(SystemBackupAgent.this,
+ new String[] { WALLPAPER_IMAGE, WALLPAPER_INFO }));
+ addHelper("system_files", new AbsoluteFileBackupHelper(SystemBackupAgent.this,
+ new String[] { WALLPAPER_IMAGE }));
+
boolean success = false;
try {
super.onRestore(data, appVersionCode, newState);